使用 QUOTED_IDENTIFIER 克服“ALTER INDEX failed”错误

Evi*_*lDr 5 t-sql sql-server sql-server-2012

以前的其他人一样,今天在我的 SQL 日志中,我可以看到由于错误 1934 导致计划作业未能执行。

ALTER INDEX 失败,因为以下 SET 选项的设置不正确:'QUOTED_IDENTIFIER'

在阅读了这里这里这里之后,我仍然不确定我的hack(下面)是否根据其他地方给出的建议引入了风险。我缺乏经验是这个问题的主要驱动因素。

原代码是:

DECLARE @Database varchar(255);
DECLARE @Table varchar(255);
DECLARE @cmd nvarchar(500);
DECLARE @fillfactor int = 90;

DECLARE DatabaseCursor CURSOR FOR
SELECT
    name
FROM
    MASTER.dbo.sysdatabases
WHERE
    name IN ('MyDbName')
ORDER BY
    name;

OPEN DatabaseCursor;
FETCH NEXT FROM DatabaseCursor INTO @Database;
WHILE (@@FETCH_STATUS = 0)
    BEGIN
        SET @cmd = 'DECLARE TableCursor CURSOR FOR SELECT ''['' + table_catalog + ''].['' + table_schema + ''].['' +
      table_name + '']'' as tableName FROM ' + @Database + '.INFORMATION_SCHEMA.TABLES
      WHERE table_type = ''BASE TABLE''';

        -- create table cursor  
        EXEC (@cmd);
        OPEN TableCursor;
        FETCH NEXT FROM TableCursor INTO @Table;
        WHILE (@@FETCH_STATUS = 0)
            BEGIN
                SET @cmd = 'ALTER INDEX ALL ON ' + @Table + ' REBUILD WITH (FILLFACTOR = ' + CONVERT(varchar(3), @fillfactor) + ')';

                EXEC (@cmd);
                FETCH NEXT FROM TableCursor INTO @Table;
            END

        CLOSE TableCursor;
        DEALLOCATE TableCursor;
        FETCH NEXT FROM DatabaseCursor INTO @Database;
    END
CLOSE DatabaseCursor;
DEALLOCATE DatabaseCursor;

USE MyDbName;
GO
EXEC sys.sp_updatestats;
Run Code Online (Sandbox Code Playgroud)

我相信在将索引添加到一个特定表中的 XML 列后,此错误开始发生,但我不是 100% 确定。在其他地方,我们也有使用 XPATH 的存储过程。我知道其他人也遇到过同样的错误,但没有手动设置 QUOTED_IDENTIFIER 的经验,我正在寻找建议以及改进修复的方法

根据我所阅读的内容,此修改后的代码确实可以正确执行:

 SET @cmd = 'SET QUOTED_IDENTIFIER ON; ' + 
            'ALTER INDEX ALL ON ' + @Table + ' REBUILD WITH (FILLFACTOR = ' + CONVERT(varchar(3), @fillfactor) + ')';
Run Code Online (Sandbox Code Playgroud)

我的担忧是:

  1. 此更改是否会引入任何风险或其他不会立即显现的危险(仅仅因为它没有错误地运行并不能安抚我的神经!)
  2. 如果没有,有没有办法准确确定导致这种情况的原因(例如 parituclar 索引或 DB 列/过程)?
  3. 如果是这样,是否可以在动态 SQL 中考虑并更优雅地处理?

预先感谢您分享您的专业知识。

Rog*_*olf 3

  1. 不,没有风险。
  2. 使用块捕获错误TRY / CATCH,以便您可以在某处记录变量的内容。
  3. 您可以更改服务器属性中的默认连接设置,使其QUOTED_IDENTIFIER始终处于打开状态。但是,这并不是 100% 的保证,因为数据访问驱动程序可以覆盖连接设置(不同的驱动程序 - ODBC、OLE DB、Native Client 等 - 的默认值略有不同)。