查询的奇怪行为

时间:2017-07-05 13:25:03

标签: sql sql-server

我从开发者那里找到了这个查询:

at asset.pipeline.AssetPipelineGrailsPlugin$_doWithSpring_closure1.doCall(AssetPipelineGrailsPlugin.groovy:104)

此查询删除表 MYSIGN

中的所有记录

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

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

它会抛出正确的错误,因为缺少了列。

我们使用正确的列更正了查询,但我们没有弄明白:

  • 为什么第一个查询有效?
  • 为什么要删除所有记录?

规范:数据库位于SQL SERVER 2016 SP1,CU3上。

2 个答案:

答案 0 :(得分:6)

显然你在<%= social_share_button_tag(raw("<b>#{job.title}</b>").html_safe, :url => "google.com" ) %> 中有USERID所以它正是sql-server在[MYDB].[dbo].[MYSIGN]中解析未加前缀的USERID - 它将其解析为(select USERID from [MYDB].[dbo].[MYUSER] where Surname = 'Rossi') }

使用别名,它将失败

[MYDB].[dbo].[MYSIGN].USERID

它被称为&#34;意外相关的子查询&#34;正如@NenadZivkovic所说,我喜欢这个词。

答案 1 :(得分:1)

问题是子查询的范围规则。如果在子查询表中找不到该列,则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');

遵循一条简单的规则可以使您的代码更具可读性并且不易出错。