Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of QUOTED_IDENTIFIER to overcome 'ALTER INDEX failed' error

Like others previously, today in my SQL logs I can see that a scheduled job has failed to execute due to Error 1934.

ALTER INDEX failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'

After reading here, here and here, I still feel unsure about whether my hack (below) is introducing risk based upon advice given elsewhere. My lack of experience is the main driver for this question.

The original code is:

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;

I believe that this error began occuring after an index was added to an XML column in one particular table, but I'm not 100% sure. Elsewhere we also have stored procedures that use XPATH. I know others have experienced the same error, but without the experience of manually setting QUOTED_IDENTIFIER, I'm looking for advice plus a way to improve my fix.

Based on what I've read, this revised code does execute without error:

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

My concerns are:

  1. Does this change introduce any risk or other danger that is not immediately apparent (just because it runs without errors doesn't settle my nerves!)
  2. If not, is there a way to identify exactly what causes this (e.g. a parituclar index or DB column/procedure)?
  3. If so, can that be accounted for in the dynamic SQL and more elegantly dealt with?

Thank you in advance for sharing your expertise.

like image 492
EvilDr Avatar asked Oct 31 '16 11:10

EvilDr


1 Answers

  1. No, there is no risk.
  2. Catch the error using TRY / CATCH block, so you can log the variables' contents somewhere.
  3. You can change default connection settings in the server properties so that QUOTED_IDENTIFIER will always be on. However, it's not a 100% guarantee, since data access drivers can override connection settings (different drivers - ODBC, OLE DB, Native Client, etc. - have slightly different defaults).
like image 136
Roger Wolf Avatar answered Sep 28 '22 05:09

Roger Wolf