为什么一个T-SQL块给,即使它甚至不应该执行的错误?(Why does a T-SQL block

2019-09-21 13:46发布

我正在写一(貌似)直线前进SQL是删除一列就可以确保列中存在后段。
问题:如果列不存在,IF子句的代码抱怨说,它无法找到列! 好了, 卫生署 ,这就是为什么它是IF子句中!
所以我的问题是,为什么不应该执行的一段代码给出错误?

这里的片段:

IF exists (select * from syscolumns
    WHERE id=object_id('Table_MD') and name='timeout')
BEGIN
    ALTER TABLE [dbo].[Table_MD]
        DROP COLUMN timeout
END
GO

...这是错误:

Error executing SQL script [...]. Invalid column name 'timeout'

我使用的Microsoft SQL Server 2005 Express版本。

Answer 1:

IF exists (select * from syscolumns
    WHERE id=object_id('Table_MD') and name='timeout')
BEGIN
    DECLARE @SQL nvarchar(1000)
    SET @SQL = N'ALTER TABLE [dbo].[Table_MD] DROP COLUMN timeout'
    EXEC sp_executesql @SQL
END
GO

原因:当SQL Server编译代码,他们检查它使用的对象(如果存在的话)。 这种检查方法忽略任何“IF”,“虽然”,等等结构和简单地检查代码中所有使用的对象。



Answer 2:

它可能永远不会被执行,但它是由SQL Server解析的有效性。 为“避开”的唯一途径,这是构建动态SQL块,然后有选择地执行它



Answer 3:

下面是我如何开始工作:

IF子句里,我改变了ALTER ... DROP ...用命令exec ('ALTER ... DROP ...')

这似乎在解析时它的SQL服务器上做的代码有效性检查,并看到一个不存在的列被引用的地方(即使这段代码不会被执行)。
使用exec(ute)命令会将在字符串中有问题的代码,解析器不抱怨,并且代码只被执行时必要的。 下面是修改的摘录:

IF exists (select * from syscolumns
    WHERE id=object_id('Table_MD') and name='timeout')
BEGIN
    exec ('ALTER TABLE [dbo].[Table_MD] DROP COLUMN timeout')
END
GO


Answer 4:

顺便说一句,有在甲骨文类似的问题,并使用“立即执行”的条款类似的解决方法。



文章来源: Why does a T-SQL block give an error even if it shouldn't even be executed?
标签: sql tsql