Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 查询的奇怪行为_Sql_Sql Server - Fatal编程技术网

Sql 查询的奇怪行为

Sql 查询的奇怪行为,sql,sql-server,Sql,Sql Server,我从一个开发人员那里找到了这个查询: DELETE FROM [MYDB].[dbo].[MYSIGN] where USERID in (select USERID from [MYDB].[dbo].[MYUSER] where Surname = 'Rossi'); 此查询删除表MYSIGN中的每条记录 表MYUSER中不存在字段USERID。如果仅运行子查询: select USERID from [MYDB].[dbo].[MYUSER] where Surname = 'Rossi

我从一个开发人员那里找到了这个查询:

DELETE FROM [MYDB].[dbo].[MYSIGN] where USERID in
(select USERID from [MYDB].[dbo].[MYUSER] where Surname = 'Rossi');
此查询删除表MYSIGN中的每条记录

表MYUSER中不存在字段USERID。如果仅运行子查询:

select USERID from [MYDB].[dbo].[MYUSER] where Surname = 'Rossi'
它抛出正确的错误,因为缺少列

我们使用右边的列更正了查询,但没有发现:

为什么第一个查询有效? 为什么它会删除所有记录? 规格:数据库位于SQL SERVER 2016 SP1,CU3上。

显然您在[MYDB].[dbo].[MYSIGN]中有用户ID,所以SQL SERVER正是这样解析[MYDB].[dbo].[MYUSER]中的select USERID中未固定的用户ID的,其中姓氏='Rossi'-它将其解析为[MYDB].[dbo].[MYSIGN].USERID]

使用别名,它将失败

DELETE FROM [MYDB].[dbo].[MYSIGN] where USERID in
(select t.USERID from [MYDB].[dbo].[MYUSER] t where Surname = 'Rossi');

它被称为意外相关子查询@NenadZivkovic,我喜欢这个术语

问题在于子查询的范围规则。如果在子查询表中找不到该列,那么SQL引擎将开始查找下一个级别,在SQL Server中也是如此

每当查询中有多个表时,请始终限定列名。这意味着,将表名或别名与列别名放在一起。那么你就没有歧义了:

DELETE
    FROM [MYDB].[dbo].[MYSIGN] m
    WHERE m.USERID IN (SELECT u.USERID FROM [MYDB].[dbo].[MYUSER] u WHERE u.Surname = 'Rossi');

一个简单的规则可以让你的代码更具可读性,更不容易出错。

请共享表结构。然后子查询中的USERID解析为MYSIGN.USERID,因此自然匹配所有行-限定名称。我的理解是:SQL通过对外部查询进行隐含的左连接来评估你的子查询。结果集包含外部查询中的所有行,因此删除将删除所有行。@AlexK.-令人惊叹的我仍然有一个问题:为什么会这样?如果你真的希望在子查询中有一个外部查询列呢?另一种选择是强制使用一个完全限定的名称,但规范规定它们是可选的。很好。这是非常奇怪的行为,应该被视为一个bug。不,这正是符合语言规范的行为。否则MSFT不会等到SQL 2016我们才讨论它。这不是bug,这是设计的。然而,通过别名将所有内容显式化应该是一条规则,这将有助于避免混淆,这就是所谓的意外相关子查询。通常,您可以在子查询中使用外部查询中的列,使其相互关联。在这种情况下,你在没有意识到的情况下就这样做了,而且效果很好。