Control panel with toggle switches, one set differently, representing SQL Server SET options on objects

SQL Server Objects Created with the Wrong SET Options: Msg 1934, Filtered Indexes and ARITHABORT

Why procedures created with QUOTED_IDENTIFIER or ANSI_NULLS off break filtered indexes and indexed views with Msg 1934, how to find and fix them, and the SSMS vs application plan difference.

February 2, 2022

Some SET options in SQL Server don’t just affect the current session; they permanently affect the objects you create. A stored procedure, view or trigger records the ANSI_NULLS and QUOTED_IDENTIFIER settings in effect when it was created, and every time it runs it uses those recorded settings, whatever the calling session’s settings are. A procedure created years ago with the wrong settings can start failing the moment a filtered index is added to a table today.

This article covers which SET options matter, which features require the right settings, how to find problem objects, and how these settings relate to the “fast in SSMS, slow in the application” problem.

SQL Server Consulting

Is old code blocking new features?

Aryasoft finds incompatible settings in your database objects and makes features such as filtered indexes and indexed views safe to use.

Get Support

Which Features Require the Right SET Options?

Filtered indexes, indexed views, indexes on computed columns, XML data type methods and a few other features require the session working on the tables that use them to run with these settings:

SET option Required value
ANSI_NULLS ON
ANSI_PADDING ON
ANSI_WARNINGS ON
ARITHABORT ON
CONCAT_NULL_YIELDS_NULL ON
QUOTED_IDENTIFIER ON
NUMERIC_ROUNDABORT OFF

If that isn’t met, for example when a procedure that inserts into a table with a filtered index was created with QUOTED_IDENTIFIER OFF, the operation fails with this error:

▤ Messages

Msg 1934, Level 16, State 1 INSERT 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.

This error usually comes from an old procedure that writes to a table, right after a new filtered index is added to it for performance.

Why Are ANSI_NULLS and QUOTED_IDENTIFIER Permanent?

Other SET options come from the session at execution time, but these two are recorded when the module is created. So if you created a procedure with a script containing SET QUOTED_IDENTIFIER OFF, the procedure always runs with OFF. This is typically seen in objects created with old tools or with script templates that explicitly turn these settings off.

Finding Problem Objects

SELECT OBJECT_SCHEMA_NAME(m.object_id) + N'.' + OBJECT_NAME(m.object_id) AS object_name,
       o.type_desc,
       m.uses_ansi_nulls,
       m.uses_quoted_identifier
FROM sys.sql_modules AS m
JOIN sys.objects AS o ON o.object_id = m.object_id
WHERE m.uses_ansi_nulls = 0 OR m.uses_quoted_identifier = 0
ORDER BY o.type_desc, object_name;

Table columns also keep the ANSI_PADDING setting from when they were created; older tables may contain char and varchar columns created with OFF:

SELECT OBJECT_NAME(c.object_id) AS table_name, c.name AS column_name,
       TYPE_NAME(c.user_type_id) AS data_type, c.is_ansi_padded
FROM sys.columns AS c
JOIN sys.tables AS t ON t.object_id = c.object_id
WHERE c.is_ansi_padded = 0
  AND TYPE_NAME(c.user_type_id) IN (N'char', N'varchar', N'binary', N'varbinary');

Fixing It

The way to fix a problem module is to recreate it with the right settings:

SET ANSI_NULLS ON;
SET QUOTED_IDENTIFIER ON;
GO
CREATE OR ALTER PROCEDURE dbo.AddOrder
    @CustomerId int, @Amount decimal(19, 4)
AS
BEGIN
    INSERT INTO dbo.Orders (CustomerId, Amount) VALUES (@CustomerId, @Amount);
END
GO

With QUOTED_IDENTIFIER ON, double quotes delimit object names instead of strings. If old code writes strings in double quotes (WHERE Status = "Active"), change them to single quotes before recreating; otherwise you get an “Invalid column name” error.

Warning

Don’t run a bulk fix directly in production. Script the modules first, check for double-quote usage, and recreate and run them in a test environment. Recreating a procedure keeps its permissions (with CREATE OR ALTER or ALTER); DROP and CREATE removes them.

“Fast in SSMS, Slow in the Application”: ARITHABORT

SSMS connects with ARITHABORT ON by default, while many application drivers connect with OFF. Because SET options are part of the plan cache key, the same query run from SSMS and from the application compiles two separate plans. If the application’s plan was compiled for an unlucky parameter value, the query looks slow in the application and fast in SSMS; that usually comes from the different plans, not from ARITHABORT itself.

Tip

When investigating why a query is slow in the application, match your SSMS session to the application’s settings (for example SET ARITHABORT OFF) to reach the same plan, and compare the set_options values of the two plans with sys.dm_exec_plan_attributes. The lasting fix is usually to address parameter sensitivity or pin the good plan with Query Store.

Checklist

  • All modules were created with ANSI_NULLS and QUOTED_IDENTIFIER ON.
  • Script templates don’t turn these settings off.
  • Objects that write to a table were checked before adding a filtered index or indexed view.
  • Strings written in double quotes were changed to single quotes.
  • Plan differences between the application and SSMS were compared through set_options.
Because an operation runs on a table with a filtered index, indexed view or computed column index without the required SET options (for example QUOTED_IDENTIFIER ON). The culprit is often an old procedure created with the wrong settings.
ANSI_NULLS and QUOTED_IDENTIFIER. The module runs with the settings in effect when it was created.
List modules in sys.sql_modules with uses_ansi_nulls = 0 or uses_quoted_identifier = 0.
SSMS and the application connect with different SET options, so two separate plans are compiled for the same query. The application’s plan may have been compiled for a different parameter value.

SQL Server Consulting

Get old code ready for new features

Aryasoft’s senior DBA team finds incompatible SET settings and syntax problems in your database objects, fixes them with testing, and safely introduces features such as filtered indexes and indexed views.

4.7/5