在查询中的复合外键/主键列上连接表
Posted
技术标签:
【中文标题】在查询中的复合外键/主键列上连接表【英文标题】:Join tables on columns of composite foreign / primary key in a query 【发布时间】:2014-03-14 12:42:26 【问题描述】:CREATE TABLE subscription (
magazine_id bigint,
user_id bigint,
PRIMARY KEY (magazine_id, user_id)
);
CREATE TABLE delivery (
magazine_id bigint,
user_id bigint,
FOREIGN KEY (subscription) REFERENCES subscription (magazine_id, user_id)
);
在给定特定订阅的情况下,查询交付的好方法是什么?有没有办法将列名分配给PRIMARY KEY (magazine_id, user_id)
和相应的外键,以便我可以这样查询:
SELECT *
FROM subscription
JOIN delivery ON (delivery.subscription_fk = delivery.subscription_pk);
注意:我可以这样写:
SELECT *
FROM subscription
JOIN delivery ON (delivery.magazine_id = subscription.magazine_id
AND delivery.user_id = subscription.user_id);
但是,我的印象是有一种不那么冗长的方法来实现这一点。
【问题讨论】:
【参考方案1】:delivery
不是有两列代表外键吗?然后它应该像使用非复合主键 SELECT * FROM subscription JOIN delivery ON (delivery.magazine_id = subscription.magazine_id AND delivery.user_id = subscription.user_id)
一样工作。
【讨论】:
是的,我正在寻找一种方法来编写这个,以便查询不那么冗长。我的印象是可以做到这一点【参考方案2】:有一个NATURAL JOIN
:
SELECT *
FROM subscription
NATURAL JOIN delivery;
引用the manual on SELECT
:
NATURAL
NATURAL
是USING
列表的简写,它提到了两个表中同名的所有列。
它适用于您的测试设置,但它并非严格按照您的要求进行。该连接基于共享相同名称的所有列。不考虑外键。 NATURAL JOIN
是个好主意的情况很少见。
简化代码/减少冗长
对于初学者,您可以使用表别名,并且您不需要在 ON
的连接条件周围加上括号(与 USING
不同):
SELECT *
FROM subscription s
JOIN delivery d ON d.magazine_id = s.magazine_id
AND d.user_id = s.user_id;
由于连接条件中的列名相同,可以进一步简化为USING
:
SELECT *
FROM subscription s
JOIN delivery d USING (magazine_id, user_id);
没有根据外键约束自动进行连接的语法变体。您必须查询系统目录并动态构建 SQL。
【讨论】:
@alumns:我添加了更多细节。 为这种情况创建自定义类型会有什么特别的优势吗? @IamIC:不知道你要去哪里。您可能会开始一个包含详细信息的新问题。您可以随时链接到此链接以获取上下文 - 并可选择在此处发表评论。 这是一个很好的答案,因为它展示了您可以如何做到这一点,但也明确指出了这一点,虽然它可能适用于给定的设置,这不是因为任何自动 FK 魔法以上是关于在查询中的复合外键/主键列上连接表的主要内容,如果未能解决你的问题,请参考以下文章