1

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

    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 失败,因为以下 SET 选项的设置不正确:'QUOTED_IDENTIFIER'。验证 SET 选项对于索引视图和/或计算列上的索引和/或过滤索引和/或查询通知和/或 XML 数据类型方法和/或空间索引操作是否正确。[SQLSTATE 42000](错误 1934)。步骤失败。

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

MSDN 上查找 Index Options,没有关于 QUOTED_IDENTIFIERS 的内容。

我们的 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

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

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

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 代理作业运行。删除索引后,此代码按预期运行,说明任务不存在的错误:

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 with ANSWER: 正如下面有用的答案所指出的,我不得不把

SET QUOTED_IDENTIFIER ON

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

SET QUOTED_IDENTIFIER ON

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

4

2 回答 2

2

有:SET QUOTED_IDENTIFIER (Transact-SQL)

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

于 2016-08-15T00:55:22.003 回答
2

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

但是,一旦创建,该表上的任何 DML 操作(不仅仅是更新)似乎都需要您将QUOTED_IDENTIFER设置设置ON为。这是您当前缺少的内容,也是您收到错误的原因。

所以,我不知道你的上下文是什么update,无论你是作为临时语句运行它,还是它是存储过程的一部分。无论哪种方式,请确保SET QUOTED_IDENTIFIER ON在开头的某处包含该语句。

于 2016-08-15T02:32:07.507 回答