通过 Management Studio 在脚本中使用 EXISTS 返回错误值

Posted

技术标签:

【中文标题】通过 Management Studio 在脚本中使用 EXISTS 返回错误值【英文标题】:Using EXISTS return wrong values in Script via Management Studio 【发布时间】:2015-06-03 08:11:36 【问题描述】:

我对以下查询有疑问。

第 1 部分

更新表格。

第 2 部分

更改列名。

如果我通过 Management Studio 重新运行脚本,我会收到错误,

“permissiontype_id”列不存在。

Exists 中的 Select 语句显示正确的结果...

我的脚本中有一些语句出现此类错误,需要删除它们...

第一陈述

IF EXISTS (
    SELECT 1
    FROM sys.columns
    WHERE NAME = N'permissiontype_id'
        AND Object_ID = Object_ID(N'[dbo].[gptbl_user_permission]')
    )
BEGIN
UPDATE gptbl_user_permission
SET permissiontype_id = 1
WHERE objecttype_id = 'resultinfo'
END
GO

第二个陈述

IF EXISTS (
    SELECT *
    FROM sys.columns
    WHERE NAME = N'permissiontype_id'
        AND Object_ID = Object_ID(N'[dbo].[gptbl_user_permission]')
    )
BEGIN
ALTER TABLE [dbo].[gptbl_user_permission]

DROP CONSTRAINT PK_gptbl_user_permission

EXEC sp_rename '[dbo].[gptbl_user_permission].[permissiontype_id]'
    , 'permissiontype'
    , 'COLUMN';

ALTER TABLE [dbo].[gptbl_user_permission] ADD CONSTRAINT PK_gptbl_user_permission PRIMARY KEY CLUSTERED (
    [objecttype_id] ASC
    , [permissiontype] ASC
    , [user_id] ASC
    )
    WITH (
            PAD_INDEX = OFF
            , STATISTICS_NORECOMPUTE = OFF
            , IGNORE_DUP_KEY = OFF
            , ALLOW_ROW_LOCKS = ON
            , ALLOW_PAGE_LOCKS = ON
            )
END
GO

【问题讨论】:

If I rerun the script: 如果你真的是说rerun 那么它应该会失败,因为该列被重命名为permissiontype 而不是permissiontype_id.. 脚本第一次运行时没有错误吗?你能告诉我们gptbl_user_permission的DDL吗? 【参考方案1】:

这个错误是编译时错误,不是因为EXISTS。如果您在第二次运行后运行 EXISTS 查询,它不会返回任何内容

SELECT 1
FROM sys.columns
WHERE NAME = N'permissiontype_id'
    AND Object_ID = Object_ID(N'[dbo].[gptbl_user_permission]')

因此在运行时,控件在第一次运行后永远不会到达您的UPDATE

UPDATE gptbl_user_permission
SET permissiontype_id = 1
WHERE objecttype_id = 'resultinfo'

您收到此错误的原因是在初始运行后,SQL Server 检查查询的语法、该查询中涉及的表和列。此时 SQL Server 知道没有列 permissiontype_id 并引发错误。

解决方案

由于此错误是由于编译导致的,因此您可以使用动态 sql 强制在运行时为 UPDATE 进行编译,如下所示:

IF EXISTS (
    SELECT 1
    FROM sys.columns
    WHERE NAME = N'permissiontype_id'
        AND Object_ID = Object_ID(N'[dbo].[gptbl_user_permission]')
    )
BEGIN
EXEC sp_executeSQL N'
UPDATE gptbl_user_permission
SET permissiontype_id = 1
WHERE objecttype_id = ''resultinfo'''
END
GO

由于EXISTS在第一次运行后每次都会返回false,因此动态UPDATE语句将永远不会被编译并且你不会得到错误。

【讨论】:

太棒了。 executeSQL 在这一点上解决了它。现在将用这个重写我的脚本的某些部分。谢谢=) @SteveFörster - 几年前我遇到了同样的问题。 IF EXISTS 只能带你走这么远:)

以上是关于通过 Management Studio 在脚本中使用 EXISTS 返回错误值的主要内容,如果未能解决你的问题,请参考以下文章

SQL Management Studio Express 在记事本中打开 SQL 脚本

SQL Server Management Studio 2008 Runas 用户在不同的域上通过 ***

SQL Server Management Studio 中的脚本大小限制

SQL Management Studio 在脚本创建后无法识别表存在

Management Studio 生成的 Sql 脚本在作为查询运行时出现错误

如何修改 SQL Server Management Studio 中自动生成的脚本文件的默认文件名格式?