tra*_*max 2 sql sql-server sql-server-2012
我的同事用一个我认为实际上应该失败的工作SQL使我感到困惑.
[IdentityUserRoles]:列RoleId,UserId; [IdentityRoles]:列Id,Name;执行的SQL有效:
Delete from IdentityUserRoles where RoleId in (
Select RoleId
FROM [dbo].[IdentityRoles]
where Name in ('TeamManager','Manager')
)
Run Code Online (Sandbox Code Playgroud)
它看起来是合法的,但如果你仔细查看子查询,表IdentityRoles没有RoleId列,它应该是Id.
所以,如果我单独运行子查询:
Select RoleId
FROM [dbo].[IdentityRoles]
where Name in ('TeamManager','Manager')
Run Code Online (Sandbox Code Playgroud)
我收到错误消息:
消息207,级别16,状态1,行1
无效的列名称"RoleId".
这是预期的,因为列RoleId确实不存在.
问题是,如果子查询包含语法错误,为什么父查询会继续执行?
我在SQL Server 2012 Express Edition(v11.0.5058.0)中运行它
更新 使此查询工作 - 没问题.问题是为什么它首先起作用并且没有抛出语法错误.
这里的SQL Server没有任何问题.这是预期的行为!
错误地在子查询中指定RoleId导致SQL Server认为它是一个相关的子查询.
SQL Server评估它的方式是,它首先在IdentityRoles中搜索RoleId,但在那里找不到它,所以它在IdentityUserRoles表中搜索.在那里发现了!所以这是一个有效的查询.
但是,如果您期望自包含子查询的行为不同...添加别名,如下所示.
Delete from IdentityUserRoles where RoleId in
(
Select r.RoleId FROM [dbo].[IdentityRoles] r where Name in ('TeamManager','Manager')
)
Run Code Online (Sandbox Code Playgroud)
上述查询将失败,因为SQL Server将在IdentityRoles表中显式搜索该列.
但是,如果遵循一些最佳实践,则不会出现这种无意的错误.最佳实践(99%的情况下)是使相同的列名表示相同的属性.
另一件事是,作为一种做法,最好遵循连接,子查询等的别名,并在选择中引用具有这些别名的列名.这样可以避免任何此类意外的错误或问题.
希望有所帮助!
| 归档时间: |
|
| 查看次数: |
127 次 |
| 最近记录: |