寻找一个片段,说明在 where 子句中连接的模糊结果

aje*_*jeh 0 join sql-server

不久前(大约 2004 年),我在一个团队中担任后端开发人员,每个人都使用 where 子句加入。作为使用内/外连接的支持者,我向他们展示了一个 where 子句连接的示例,该示例说明了它如何根据数据产生不明确的结果,以及外连接如何避免该问题。

我必须做同样的演示,但再也找不到那个片段了。它在我的文件档案中的某个地方,不幸的是我无权访问。有没有人有一个方便的例子?

Aar*_*and 5

这只能在设置为 80 兼容级别(或 SQL Server <= 2000)的数据库上证明。

CREATE TABLE dbo.splunge(splunge_id INT);

CREATE TABLE dbo.mort(splunge_id INT, name VARCHAR(32));

INSERT dbo.splunge(splunge_id) SELECT 1 UNION SELECT 2 UNION SELECT 3;

INSERT dbo.mort(splunge_id, name) SELECT 1,'hi' UNION SELECT 2,NULL;

-- returns all three rows - should it?
SELECT * 
  FROM dbo.splunge AS s, dbo.mort AS m
  WHERE s.splunge_id *= m.splunge_id
  AND m.name IS NULL;

-- returns rows 2 and 3
SELECT * 
  FROM dbo.splunge AS s
  LEFT OUTER JOIN dbo.mort AS m
  ON s.splunge_id = m.splunge_id
  WHERE m.name IS NULL;

DROP TABLE dbo.splunge, dbo.mort;
Run Code Online (Sandbox Code Playgroud)

不想使用可为空的名称列来演示?好的,一个可为空的外键列怎么样?

CREATE TABLE dbo.splunge(splunge_id INT);

CREATE TABLE dbo.mort(splunge_id INT);

INSERT dbo.splunge(splunge_id) SELECT 1 UNION SELECT 2 UNION SELECT 3;

INSERT dbo.mort(splunge_id) SELECT 1 UNION SELECT 2 UNION SELECT NULL;

-- returns all three rows - should it?
SELECT * 
  FROM dbo.splunge AS s, dbo.mort AS m
  WHERE s.splunge_id *= m.splunge_id
  AND m.splunge_id IS NULL;

-- only returns row 3 (because it was the only row truly missing)
SELECT * 
  FROM dbo.splunge AS s
  LEFT OUTER JOIN dbo.mort AS m
  ON s.splunge_id = m.splunge_id
  WHERE m.splunge_id IS NULL;

DROP TABLE dbo.splunge, dbo.mort;
Run Code Online (Sandbox Code Playgroud)

不知道为什么你今天需要证明这一点 - 你根本不应该使用*= / =*连接,无论你是否可以重现一些模棱两可的行为 - 它们已被弃用并且在任何不支持 80 兼容性的数据库中都不起作用等级。如果您使用的是 80 级兼容性,则在最终升级时,您需要为大量其他功能差异和潜在的破坏性更改做好准备。