Mic*_*rst 3 sql-server query t-sql
我有以下查询:
IF EXISTS( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'NotificationTableLogRows' AND COLUMN_NAME = 'DestinationAddress') BEGIN
UPDATE NotificationTableLogRows
SET [HandlerID] = m.ID
FROM [Unicare].dbo.MobileDevices m
WHERE HandlerID is null
AND m.CallNumber = NotificationTableLogRows.DestinationAddress AND NotificationTableLogRows.HandlerTypeID = 2
END
print 'end'
Run Code Online (Sandbox Code Playgroud)
但运行后,我仍然收到错误:
Msg 207, Level 16, State 1, Line 6
Invalid column name 'DestinationAddress'.
Run Code Online (Sandbox Code Playgroud)
但是它应该只打印结束
我究竟做错了什么?
编辑:
即使:
IF 1 = 0 BEGIN
UPDATE NotificationTableLogRows
SET [HandlerID] = m.ID
FROM [Unicare].dbo.MobileDevices m
WHERE HandlerID is null
AND m.CallNumber = NotificationTableLogRows.DestinationAddress AND NotificationTableLogRows.HandlerTypeID = 2
END
Run Code Online (Sandbox Code Playgroud)
它产生相同的错误,问题似乎出在 sql 检查预执行查询的方式上。
这是解析时错误,而不是运行时错误。您不能使用IF检查来确定列引用是否可以使用,因为列引用首先在运行之前进行验证IF(这就是为什么IF 1 = 0也会失败)。
注意:如果您将脚本复制到您自己的系统(其中不存在这些对象) ,问题中的脚本似乎可以工作(例如,它将打印)。由于延迟名称解析,如果任何对象尚不存在,则解析检查将成功,但如果所有对象都存在,但任何列不存在,则解析检查将失败。
end
作为证明,比较:
IF 1 = 0
BEGIN
SELECT 1 FROM sys.columns AS c
INNER JOIN sys.objects AS o
ON c.blat = o.splunge;
END
GO
/*
Msg 207, Level 16, State 1
Invalid column name 'blat'.
Msg 207, Level 16, State 1
Invalid column name 'splunge'.
*/
IF 1 = 0
BEGIN
SELECT 1 FROM dbo.blats AS b
INNER JOIN dbo.splunges AS s
ON b.blat = s.splunge;
END
GO
/*
"success"
*/
Run Code Online (Sandbox Code Playgroud)
现在创建一个名为 的表dbo.blats,但没有名为 的列blat:
CREATE TABLE dbo.blats(id int);
Run Code Online (Sandbox Code Playgroud)
第二个脚本仍然成功,因为仍然有一个对象尚不存在,并且 SQL Server 为您提供了怀疑的好处 - 至少在解析时 - 您将在执行脚本之前创建它。dbo.splunges当您添加第二个表 ,但没有引用的列时,它将失败splunge:
CREATE TABLE dbo.splunges(id int);
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,您可以使用这个麻烦的解决方法,或者只使用动态 SQL(这里我使用sys.columns 而不是INFORMATION_SCHEMA,嗯,因为):
IF EXISTS
(
SELECT 1
FROM sys.columns AS c
INNER JOIN sys.objects AS o
ON o.[object_id] = c.[object_id]
INNER JOIN sys.schemas AS s
ON o.[schema_id] = s.[schema_id]
WHERE s.name = N'schema_name'
AND o.name = N'object_name'
AND c.name = N'column_name'
)
BEGIN
EXEC sys.sp_executesql N'UPDATE ... <query that references column_name> ...;';
END
Run Code Online (Sandbox Code Playgroud)
这也是为什么我避免使用速记元数据帮助器(例如OBJECT_NAME(),SCHEMA_NAME()等),而是建议创建您自己的帮助器视图。
| 归档时间: |
|
| 查看次数: |
7111 次 |
| 最近记录: |