由于不正确的 'QUOTED_IDENTIFIER' 设置导致更新失败的过滤唯一索引

Filtered Unique Index causing UPDATE to fail because incorrect 'QUOTED_IDENTIFIER' settings

我们在 SQL Server 2016 数据库中的 table 上放置了以下过滤索引:

    CREATE UNIQUE NONCLUSTERED INDEX [fix_SystemPKeyExecutionOrder] ON [DataInt].[TaskMaster]
(
    [SystemPkey] ASC,
    [ExecutionOrder] ASC
)
WHERE ([ExecutionOrder] IS NOT NULL)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 95)
GO

导致 SQL 代码现在失败并出现以下错误:

UPDATE failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations. [SQLSTATE 42000] (Error 1934). The step failed.

删除过滤索引后,代码运行完美无缺。

MSDN for Index Options上看,QUOTED_IDENTIFIERS什么都没有。

None 我们 SQL 代码中的 UPDATE 语句对任何值都有双引号。我们能看到的唯一双引号如下:

SET @ROWCOUNT = @@ROWCOUNT

    If (@ROWCOUNT = 0)
    BEGIN
        RAISERROR('The "File Import" task ACTIVE_YN could not be updated to "Y". Either the task does not exist or the system "File Import To Stage" does not exist.', 16, 1)
    END
    ELSE
    BEGIN
        Print 'Successfully updated the "File Import" task ACTIVE_YN to "Y".'
    END

即使我们将那些双引号 " 更改为两个单引号 '',代码仍然会失败并出现相同的错误。

table 本身是通过以下方式创建的:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [DataInt].[TaskMaster](
    [Pkey] [bigint] IDENTITY(1,1) NOT NULL,
    [ScheduleMasterPkey] [int] NOT NULL,
    [SystemPkey] [int] NOT NULL,
    [SourcePkey] [int] NOT NULL,
    [TargetPkey] [int] NOT NULL,
    [TaskName] [varchar](255) NOT NULL,
    [TaskTypePkey] [int] NOT NULL,
    [Active_YN] [char](1) NOT NULL,
    [ModifiedDate] [datetime] NULL,
    [ModifiedBy] [varchar](100) NULL,
    [RowVersion] [timestamp] NOT NULL,
    [ExecutionOrder] [int] NULL,
 CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED 
(
    [Pkey] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 95) ON [PRIMARY],
 CONSTRAINT [uc_TaskName] UNIQUE NONCLUSTERED 
(
    [TaskName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 95) ON [PRIMARY]
) ON [PRIMARY]

GO

就像我说的,如果我们不创建过滤索引,整个代码 运行 是完美的;它只对索引失败。

那么为什么过滤后的索引突然导致我们的 SQL 崩溃,我们该如何解决呢?

更新: 这是重现失败的一小段代码。此代码是 运行 通过 SQL 代理作业。删除索引后,此代码 运行s 如预期的那样指出错误任务不存在:

DECLARE @ROWCOUNT INT = 0

UPDATE [DataIntegrationMaster].[DataInt].[TaskMaster]
    Set Active_YN = 'Y'
    where TaskName = 'File Import'
    and SystemPkey = 0

    SET @ROWCOUNT = @@ROWCOUNT

    If (@ROWCOUNT = 0)
    BEGIN
        RAISERROR('The "File Import" task ACTIVE_YN could not be updated to "Y". Either the task does not exist or the system "File Import To Stage" does not exist.', 16, 1)
    END
    ELSE
    BEGIN
        Print 'Successfully updated the "File Import" task ACTIVE_YN to "Y".'
    END

UPDATE2 回答: 正如下面有用的答案所指出的,我不得不把

SET QUOTED_IDENTIFIER ON

在 SQL 的顶部以使其正常工作。

SET QUOTED_IDENTIFIER ON

当我使用它创建索引时没有效果。

有:SET QUOTED_IDENTIFIER (Transact-SQL)

为了防止出现类似问题,我建议检查创建过滤索引的确切要求:CREATE INDEX (Transact-SQL)。它有一个漂亮整洁的 table,显示了创建过滤索引所需的 SET 选项。

正如@Roger Wolf 的回答中所指出的,创建过滤索引要求您将 QUOTED_IDENTIFER 设置设置为 ON,这正是您所做的。如果您不这样做,您将无法首先创建过滤索引。

但是,一旦创建,table 上的任何 DML 操作(不仅仅是更新)似乎都要求您将 QUOTED_IDENTIFER 设置设置为 ON,因为出色地。这是您目前所缺少的,也是您收到错误的原因。

因此,我不知道您 update 的上下文是什么,您是 运行 这是一个临时语句,还是存储过程的一部分。无论哪种方式,请确保在开头的某处包含 SET QUOTED_IDENTIFIER ON 语句。