可用版本: Dev (3.21) | 最新 (3.20) | 3.19 | 3.18 | 3.17 | 3.16 | 3.15 | 3.14 | 3.13 | 3.12 | 3.11

SQL: NATURAL JOIN 或 JOIN USING

适用于 ✅ 开源版   ✅ 专业版   ✅ 企业版

NATURAL JOINJOIN .. USING 起初看起来是很有用的工具,当一个规范化的模式被设计得非常好,以至于 PRIMARY KEYFOREIGN KEY 列名总是匹配时(在 NATURAL JOIN 的情况下,所有其他列名永远不会匹配)。 Sakila 数据库 就是后者的一个例子,其中包含如下表格

CREATE TABLE actor (
  actor_id BIGINT PRIMARY KEY,
  first_name TEXT,
  last_name TEXT,
  last_update TIMESTAMP
);

CREATE TABLE film (
  film_id BIGINT PRIMARY KEY,
  title TEXT,
  last_update TIMESTAMP
);

CREATE TABLE film_actor (
  actor_id BIGINT REFERENCES film,
  film_id BIGINT REFERENCES film,
  last_update TIMESTAMP
)

事实上,例如,ACTOR_ID 存在于 ACTORFILM_ACTOR 表中,并且在两个表中都表示相同的事物,这对于如下查询非常方便

SELECT *
FROM actor
JOIN film_actor USING (actor_id)
JOIN film USING (film_id);

但即使是这个简单的模式也表明我们不能使用 NATURAL JOIN,因为 LAST_UPDATE 列不应成为 JOIN 谓词的一部分。

SELECT *
FROM actor
NATURAL JOIN film_actor -- Wrong, because it joins on actor.last_update = film_actor.last_update
NATURAL JOIN film       -- Wrong, because it joins on film_actor.last_update = film.last_update

即使 USING 也可能遭受这种歧义,例如,当我们恰好向 FILM 表添加一个 ACTOR_ID 列时

-- Where actor_id means the "main" actor ID
ALTER TABLE film ADD actor_id BIGINT REFERENCES actor;

这种添加是有争议的,因为

  • 这个命名似乎没有充分描述它是“主要”演员的事实
  • 从规范化的角度来看,在 FILM 表上重复此信息似乎是多余的,因为 FILM_ACTOR 表可以有一个关于演员是电影中“主要”演员的附加标志。

可以看出,包含 NATURAL JOINJOIN .. USING 的查询很容易出错(通常是微妙的),并且当模式演变时更容易破坏。 因此,最好完全避免使用该语言功能,除非是偶尔的临时查询。

反馈

您对此页面有任何反馈吗? 我们很乐意听到!

The jOOQ Logo