On 3/29/21 11:59 AM, Joel Jacobson wrote:
> On Sun, Mar 28, 2021, at 16:04, Tom Lane wrote:
>> I'm imagining a syntax in which
>> you give the constraint name instead of the column name. Thought
>> experiment: how could the original syntax proposal make any use of
>> a multi-column foreign key?
>
> Thanks for coming up with this genius idea.
>
> At first I didn't see the beauty of it; I wrongly thought the constraint name needed to be
> unique per schema, but I realize we could just use the foreign table's name
> as the constraint name, which will allow a nice syntax:
>
> SELECT DISTINCT order_details.orders.customers.company_name
> FROM order_details
> WHERE order_details.products.product_name = 'Chocolade';
>
> Given this data model:
>
> CREATE TABLE customers (
> customer_id bigint NOT NULL GENERATED ALWAYS AS IDENTITY,
> company_name text,
> PRIMARY KEY (customer_id)
> );
>
> CREATE TABLE orders (
> order_id bigint NOT NULL GENERATED ALWAYS AS IDENTITY,
> customer_id bigint NOT NULL,
> PRIMARY KEY (order_id),
> CONSTRAINT customers FOREIGN KEY (customer_id) REFERENCES customers
> );
>
> CREATE TABLE products (
> product_id bigint NOT NULL GENERATED ALWAYS AS IDENTITY,
> product_name text NOT NULL,
> PRIMARY KEY (product_id)
> );
>
> CREATE TABLE order_details (
> order_id bigint NOT NULL,
> product_id bigint NOT NULL,
> PRIMARY KEY (order_id, product_id),
> CONSTRAINT orders FOREIGN KEY (order_id) REFERENCES orders,
> CONSTRAINT products FOREIGN KEY (product_id) REFERENCES products
> );
If you write your schema like this, then it becomes standards compliant:
CREATE TYPE customers AS (
company_name text
);
CREATE TABLE customers OF customers (
REF IS customer_id SYSTEM GENERATED
);
CREATE TYPE orders AS (
customer REF(customers) NOT NULL
);
CREATE TABLE orders OF orders (
REF IS order_id SYSTEM GENERATED
);
CREATE TYPE products AS (
product_name text
);
CREATE TABLE products OF products (
REF IS product_id SYSTEM GENERATED
);
CREATE TABLE order_details (
"order" REF(orders),
product REF(products),
quantity integer,
PRIMARY KEY ("order", product)
);
And the query would be:
SELECT DISTINCT order_details."order"->customer->company_name
FROM order_details
WHERE order_details.product->product_name = 'Chocolade';
Postgres already supports most of that, but not all of it.
--
Vik Fearing