From 870cff8bf0fa960f341a8b29e59b454839e7dad3 Mon Sep 17 00:00:00 2001 From: sommarskog Date: Sat, 18 Jul 2026 21:17:50 +0200 Subject: [PATCH] Update set-arithabort-transact-sql.md A thorough review of the topic: - Removed "Always set ARITHABORT to ON in your logon sessions. Setting ARITHABORT to OFF can negatively impact query optimization, leading to performance issues." which is bad and incorrect advice. - Clearly stating that as long as ANSI_WARNINGS is ON, this setting has no effect. - Removed all references to compat level 80, since it is only supported in SQL 2008 and earlier. - Removed text and passages that seemed to just rehash what had been said already. - Changed "those errors" and similar to "arithmetic errors". - Reworked the example so that it actually shows something interesting. --- .../statements/set-arithabort-transact-sql.md | 96 ++++++++++++------- 1 file changed, 64 insertions(+), 32 deletions(-) diff --git a/docs/t-sql/statements/set-arithabort-transact-sql.md b/docs/t-sql/statements/set-arithabort-transact-sql.md index d3fe5537cc7..40eeafffe80 100644 --- a/docs/t-sql/statements/set-arithabort-transact-sql.md +++ b/docs/t-sql/statements/set-arithabort-transact-sql.md @@ -30,7 +30,7 @@ monikerRange: ">=aps-pdw-2016 || =azuresqldb-current || =azure-sqldw-latest || > # SET ARITHABORT (Transact-SQL) [!INCLUDE [sql-asdb-asdbmi-asa-pdw-fabricse-fabricdw-fabricsqldb](../../includes/applies-to-version/sql-asdb-asdbmi-asa-pdw-fabricse-fabricdw-fabricsqldb.md)] -Ends a query when an overflow or divide-by-zero error occurs during query execution. +Ends a query when an overflow or divide-by-zero error occurs during query execution. :::image type="icon" source="../../includes/media/topic-link-icon.svg" border="false"::: [Transact-SQL syntax conventions](../../t-sql/language-elements/transact-sql-syntax-conventions-transact-sql.md) @@ -48,29 +48,17 @@ SET ARITHABORT ON ## Remarks -Always set ARITHABORT to ON in your logon sessions. Setting ARITHABORT to OFF can negatively impact query optimization, leading to performance issues. +When the setting ANSI_WARNINGS is ON (the default), the setting of ARITHABORT has no functional effect. Arithmetic errors cause the query to end, but the batch will not be aborted (as long as the setting XACT_ABORT is OFF). > [!WARNING] -> The default ARITHABORT setting for [!INCLUDE [ssManStudioFull](../../includes/ssmanstudiofull-md.md)] is ON. Client applications setting ARITHABORT to OFF might receive different query plans, making it difficult to troubleshoot poorly performing queries. That is, the same query might execute fast in management studio but slow in the application. When troubleshooting queries with [!INCLUDE [ssManStudio](../../includes/ssmanstudio-md.md)], always match the client ARITHABORT setting. +> The default ARITHABORT setting for [!INCLUDE [ssManStudioFull](../../includes/ssmanstudiofull-md.md)] is ON, while a client connection in an application defaults to ARITHABORT OFF. Even if there is no functional difference as long as ANSI_WARNINGS is ON, the setting for ARITHABORT is still a cache key. Therefore, SSMS and an application both using their respective defaults, will have different cache entries, and may get different query plans, making it difficult to troubleshoot poorly performing queries. That is, the same query might execute fast in management studio but slow in the application. When troubleshooting queries with [!INCLUDE [ssManStudio](../../includes/ssmanstudio-md.md)], always match the client ARITHABORT setting. + +When SET ARITHABORT is ON and SET ANSI WARNINGS is OFF, these arithmetic errors cause the batch to end. If the errors occur in a transaction, the transaction is rolled back. -When SET ARITHABORT and SET ANSI WARNINGS are ON, these error conditions cause the query to end. - -When SET ARITHABORT is ON and SET ANSI WARNINGS is OFF, these error conditions cause the batch to end. If the errors occur in a transaction, the transaction is rolled back. When SET ARITHABORT is OFF and one of these errors occurs, a warning message appears and the result of the arithmetic operation is `NULL`. - -If SET ARITHABORT and SET ANSI WARNINGS are OFF and one of these errors occurs, a warning message appears, and the result of the arithmetic operation is `NULL`. - -> [!NOTE] -> If neither SET ARITHABORT nor SET ARITHIGNORE is ON, [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] returns `NULL` and a warning message appears after the query runs. +If both SET ARITHABORT and SET ANSI WARNINGS are OFF and one of these errors occurs, a warning message appears (unless SET ARITHIGNORE is ON), and the result of the arithmetic operation is `NULL`. -When ANSI_WARNINGS has a value of ON and the database compatibility level is set to 90 or higher then ARITHABORT is implicitly ON regardless of its value setting. If the database compatibility level is set to 80 or earlier, the ARITHABORT option must be explicitly set to ON. - -For expression evaluation, if SET ARITHABORT is OFF and an INSERT, UPDATE, or DELETE statement comes across an arithmetic, overflow, divide-by-zero, or domain error, [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] inserts or updates a `NULL` value. If the target column isn't nullable, the insert or update action fails and the user sees an error. - -When either SET ARITHABORT or SET ARITHIGNORE is OFF and SET ANSI_WARNINGS is ON, [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] still returns an error message when encountering divide-by-zero or overflow errors. - -When SET ARITHABORT is OFF and an abort error occurs during the evaluation of the Boolean condition of an IF statement, the FALSE branch executes. -SET ARITHABORT must be ON when you're creating or changing indexes on computed columns or indexed views. If SET ARITHABORT is OFF, CREATE, UPDATE, INSERT, and DELETE statements on tables with indexes on computed columns or indexed views fail. +For expression evaluation, if both SET ANSI_WARNINGS and SET ARITHABORT are OFF and an INSERT, UPDATE, or DELETE statement comes across an arithmetic, overflow, divide-by-zero, or domain error, [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] inserts or updates a `NULL` value. If the target column isn't nullable, the insert or update action fails and the user sees an error. The setting of SET ARITHABORT happens at execute or run time and not at parse time. @@ -101,7 +89,7 @@ CREATE TABLE t1 ( b TINYINT ); CREATE TABLE t2 ( - a TINYINT + a TINYINT NOT NULL ); GO INSERT INTO t1 @@ -109,17 +97,57 @@ VALUES (1, 0); INSERT INTO t1 VALUES (255, 1); GO + +-- First run with ANSI_WARNINGS to see the default behaviour. +PRINT '*** SET ANSI_WARNINGS ON'; +SET ANSI_WARNINGS ON; +SET XACT_ABORT OFF; -- To make sure that we have the default setting for this option. +go +PRINT '*** Testing divide by zero during SELECT'; +GO +SELECT a / b AS ab +FROM t1; +PRINT 'This prints, despite the error message.'; +GO -PRINT '*** SET ARITHABORT ON'; +PRINT '*** Testing divide by zero during INSERT'; +GO +INSERT INTO t2 +SELECT a / b AS ab +FROM t1; +PRINT 'This prints, despite the error message.'; +GO + +PRINT '*** Testing tinyint overflow'; +GO +INSERT INTO t2 +SELECT a + b AS ab +FROM t1; +PRINT 'This prints, despite the error message.'; GO --- SET ARITHABORT ON and testing. + +PRINT '*** Resulting data - should be no data'; +GO +SELECT * +FROM t2; +GO + +-- Truncate table t2. +TRUNCATE TABLE t2; +GO + +-- Turn off ANSI_WARNINGS so that ARITHABORT has any affect, and let ARITHABORT be ON. +PRINT '*** SET ANSI_WARNINGS OFF; SET ARITHABORT ON'; +GO +SET ANSI_WARNINGS OFF; SET ARITHABORT ON; GO PRINT '*** Testing divide by zero during SELECT'; GO -SELECT a / b AS ab +SELECT a / b AS ab FROM t1; +PRINT 'This does not print.'; GO PRINT '*** Testing divide by zero during INSERT'; @@ -127,16 +155,17 @@ GO INSERT INTO t2 SELECT a / b AS ab FROM t1; +PRINT 'This does not print.'; GO - PRINT '*** Testing tinyint overflow'; GO INSERT INTO t2 SELECT a + b AS ab FROM t1; +PRINT 'This does not print.' ; GO -PRINT '*** Resulting data - should be no data'; +PRINT '*** Resulting data - should be 0 rows'; GO SELECT * FROM t2; @@ -145,29 +174,30 @@ GO -- Truncate table t2. TRUNCATE TABLE t2; GO - --- SET ARITHABORT OFF and testing. + +-- SET ARITHABORT to OFF PRINT '*** SET ARITHABORT OFF'; GO SET ARITHABORT OFF; GO --- This works properly. PRINT '*** Testing divide by zero during SELECT'; GO +-- Returns NULL. SELECT a / b AS ab FROM t1; GO --- This works as if SET ARITHABORT was ON. PRINT '*** Testing divide by zero during INSERT'; GO +-- Fails with NOT NULL violation. INSERT INTO t2 SELECT a / b AS ab FROM t1; GO PRINT '*** Testing tinyint overflow'; GO +-- Fails with NOT NULL violation INSERT INTO t2 SELECT a + b AS ab FROM t1; @@ -178,11 +208,13 @@ GO SELECT * FROM t2; GO - --- Drop tables t1 and t2. + + +-- Drop tables t1 and t2 and restore ANSI_WARNINGS DROP TABLE t1; DROP TABLE t2; -GO +SET ANSI_WARNINGS ON +GO ``` ## Related content