Rav*_* HV 6 sql-server t-sql sql-server-2008-r2
是否有任何解释可以解释为什么 SSMS 没有为以下带有本身无效的子查询的删除查询引发任何编译错误?
以下是重现该行为的步骤序列:
CREATE TABLE [dbo].[delete_test]
(
[id] [int] IDENTITY(1,1) NOT NULL,
[name] [nchar](10) NOT NULL
) ON [PRIMARY];
Run Code Online (Sandbox Code Playgroud)
种子数据:
insert dbo.delete_test(name) values(N'a'),(N'b'),(N'c'),(N'd'),(N'e');
Run Code Online (Sandbox Code Playgroud)
创建备份表:
select id, name
into dbo.delete_test_backup
from dbo.delete_test where id > 2;
Run Code Online (Sandbox Code Playgroud)
理想情况下,下面的语句不应执行,即使它执行,也应仅删除id
具有已备份值的行:
delete dbo.delete_test where id in (
select id delete_test_backup
);
Run Code Online (Sandbox Code Playgroud)
该消息显示删除了 5 行,但我预计只有 3 行被删除:
(5 row(s) affected)
Run Code Online (Sandbox Code Playgroud)
尝试将子查询作为独立执行失败:
select id delete_test_backup ;
Run Code Online (Sandbox Code Playgroud)
无效的列名“id”
下面一个按预期执行:
select id from dbo.delete_test_backup ;
Run Code Online (Sandbox Code Playgroud)
输出 :
id
--
3
4
5
Run Code Online (Sandbox Code Playgroud)
这与:
(
SELECT id AS delete_test_backup
)
Run Code Online (Sandbox Code Playgroud)
换句话说,您只是为 分配了一个列别名id
,而根本没有对名为 的表的引用delete_test_backup
。
根据 ANSI 标准,在这种情况下 SQL Server 应该做的事情 - 当它有一个子查询并且id
在该范围内没有找到时 - 是遍历外部范围,直到找到一个。如果是,则假定这就是您的意思。
看:
* Microsoft 决定删除所有 Connect 而不是存档内容,并且出于某种原因也删除了知识库文章。
为避免该问题,请始终使用表别名,这使您可以 100% 明确地了解列来自哪个表(不命名每个键列也有id
帮助)。当然,您可以意外地忽略这些前缀,就像您忽略了 一样FROM
,但是以下语法会如您所料地失败,并且大多数其他遗漏都会给您带来解析错误而不是意外执行:
(
SELECT x.id FROM delete_test_backup AS x
)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1149 次 |
最近记录: |