如何区分没有行和外键引用不存在?

How to differentiate between no rows and foreign key reference not existing?

我的 users table 包含 Alice、Bob 和 Charles。 Alice 和 Bob 分别有 3 和 2 fruits。查尔斯 none。使用外键约束 foreign key (user_id) references users (id)unique (user_id, name) 约束建立关系,允许每个用户零个或一个水果。

create table users (
  id         integer primary key,
  firstname  varchar(64)
);

create table fruits (
  id          integer primary key not null,
  user_id     integer not null,
  name        varchar(64) not null,
  foreign key (user_id) references users (id),
  unique (user_id, name)
);

insert into users (id, firstname) values (1, 'Alice');
insert into users (id, firstname) values (2, 'Bob');
insert into users (id, firstname) values (3, 'Charles');

insert into fruits (id, user_id, name) values (1, 1, 'grape');
insert into fruits (id, user_id, name) values (2, 1, 'apple');
insert into fruits (id, user_id, name) values (3, 1, 'pear');
insert into fruits (id, user_id, name) values (4, 2, 'orange');
insert into fruits (id, user_id, name) values (5, 2, 'cherry');

Charles 没有橙子,因此没有结果行(下面的第一个查询)。但是,运行 对不存在的用户的相同查询(下面的第二个查询)也 returns 没有结果。

test=# select * from fruits where user_id = 3 and name = 'orange';
 id | user_id | name 
----+---------+------
(0 rows)

test=# select * from fruits where user_id = 99 and name = 'orange';
 id | user_id | name 
----+---------+------
(0 rows)

是否可以在执行单个查询的同时区分用户不存在与用户存在但没有水果?

如果是这样,是否也可以这样做来查找属于特定用户的所有水果(即 select * from fruits where user_id = 3select * from fruits where user_id = 99.

使用 LEFT [OUTER] JOIN:

SELECT u.id, u.firstname, f.name AS fruit
--   , COALESCE(f.name, '') AS fruit  -- alternatively an empty string
FROM   users u
LEFT   JOIN fruits f ON f.user_id = u.id
                    AND f.name = 'orange'
WHERE  u.id = 3;

如果用户存在,你总是得到一行。
如果用户没有水果(那个名字),fruit 默认为 NULL - 这是不可能的,因为 fruit.name 被定义为 NOT NULL.

要获取空字符串,请输入 COALESCE(). But no fruit can be named '' then or it'll be ambiguous again. Add a CHECK constraint 以确保。

相关:

旁白 1:“名字”不是一个好名字。
旁白 2:通常,这将是一个包含三个表的 many-to-many 设计:“users”、“fruits”和“user_fruits”。参见:

  • How to implement a many-to-many relationship in PostgreSQL?