SQLServerCentral Article

How to Decipher @@Options

,

There is a variable in SQL Server called @@OPTIONS. This contains all of the settings that you have configured using the SET command. However, understanding the values inside of this variable can be a bit cumbersome. This article will show you a quick way to determine what settings you have in your environment.

Decoding @@Options

The @@Options variable contains an integer. This integer contains the values of all the SET options. As an example, I can run this:

SET option values

What does this mean? The values are stored as a bitmap, which means that this value, 5496, is made up of a binary string. This means that these are equivalent

5496 = 001010101111000

The left side is decimal, or base 10. The right side is binary, or base 2. Each place in the number on the right represents a setting that is used by SQL Server. For example, the first 1 (leftmost) is for the setting CONCAT_NULL_YIELDS_NULL. This is set to 1.

Note, in this case, there are actually leading zeros in the number since there are more settings than shown.

There is a value for each place in the right, binary, number. If we start reading from the right, we see 0,0,0,1. These values for the places are: 1,2,4,8. We're counting in powers of 2 here. This means the entire number is this, reading left to right.

  • 0 - 16384
  • 0 - 8192
  • 1 - 4096
  • 0 - 2048
  • 1 - 1024
  • 0 - 512
  • 1 - 256
  • 0 - 128
  • 1 - 64
  • 1 - 32
  • 1 - 16
  • 1 - 8
  • 0 - 4
  • 0 - 2
  • 0 - 1

I can use a bitwise operation to actually get these values from the decimal 5496 (or @@OPTIONS). For example, if I do this:

SELECT 5496 & 8

This returns the value 8. I've done a bitwise operation, which will return 1000. There are actually other, leading zeros, but in this case, the base 2 1000 is the value 8 in decimal.

I can use this technique to decode all of the settings in the @@OPTIONS variable. I can use a bitwise operation with powers of 2 and then capture the values. If the value is 0, the setting is off. A setting that equals the value of the power of two means the setting is on. I could use a series of statements like this:

IF ((@@OPTIONS & 1) = 1)
    SELECT 'IMPLICIT_TRANSACTIONS are ON';
IF ((@@OPTIONS & 2) = 2)
    SELECT 'IMPLICIT_TRANSACTIONS are ON';
IF ((@@OPTIONS & 4) = 4)
    SELECT 'CURSOR_CLOSE_ON_COMMIT is ON';
IF ((@@OPTIONS & 8) = 8)
    SELECT 'ANSI_WARNINGS';
IF ((@@OPTIONS & 16) = 16)
    SELECT 'ANSI_PADDING';

I think there's a better way.

Keeping This Handy

I decided that a stored procedure that will easily get the settings would be the best choice. Functions work, but then I have to do some SELECT * from Function, which is harder to remember. I'd prefer to:

EXEC sp_GetSetOptions

To build the procedure, I had to decide on whether to return a wide result set or a long one. I'll actually give you both, but I prefer the long one. This necessitates me UNIONing a bunch of SELECT statements. To go wide, I would make each operation a separate item in the SELECT list.

The basic structure is what is shown above, wrapped in a stored procedure. I take the @@OPTIONS value and then perform a bitwise operation against this with different values. Each of these is then part of a SELECT, and I include the value used in the result set to make things easy. Here is the code:

USE master
GO
CREATE OR ALTER PROCEDURE dbo.sp_GetSetOptions
AS
DECLARE @o INT
SELECT @o = @@OPTIONS;
SELECT CASE
                    WHEN (@o & 1) = 0 THEN
                        'Disable_DEFERRED_CONSTRAINT_Checking IS OFF'
                    ELSE
                        'Disable_DEFERRED_CONSTRAINT_Checking IS ON'
                END AS [Option Setting]
, 1 AS [BinaryValue]
         UNION
         SELECT CASE
                    WHEN (@o & 2) = 0 THEN
                        'Implicit Transactions are OFF'
                    ELSE
                        'Implicit Transactions are ON'
                END
, 2
         UNION
         SELECT CASE
                    WHEN (@o & 4) = 0 THEN
                        'Close cursor on commit is OFF'
                    ELSE
                        'Close cursor on commit is ON'
                END
, 4
         UNION
         SELECT CASE
                    WHEN (@o & 8) = 0 THEN
                        'ANSI Warnings are OFF'
                    ELSE
                        'ANSI Warnings are ON'
                END
, 8
         UNION
         SELECT CASE
                    WHEN (@o & 16) = 0 THEN
                        'ANSI PADDING is OFF'
                    ELSE
                        'ANSI PADDING is ON'
                END
, 16
         UNION
         SELECT CASE
                    WHEN (@o & 32) = 0 THEN
                        'ANSI NULLs are OFF'
                    ELSE
                        'ANSI NULLs are ON'
                END
, 32
         UNION
         SELECT CASE
                    WHEN (@o & 64) = 0 THEN
                        'ARITHABORT is OFF'
                    ELSE
                        'ARITHABORT is ON'
                END
, 64
         UNION
         SELECT CASE
                    WHEN (@o & 128) = 0 THEN
                        'ARITHIGNORE is OFF'
                    ELSE
                        'ARITHIGNORE is ON'
                END
, 128
         UNION
         SELECT CASE
                    WHEN (@o & 256) = 0 THEN
                        'Quoted Identifers is OFF'
                    ELSE
                        'Quoted Identifers is ON'
                END
, 256
         UNION
         SELECT CASE
                    WHEN (@o & 512) = 0 THEN
                        'NOCOUNT is OFF'
                    ELSE
                        'NOCOUNT is ON'
                END
,512
         UNION
         SELECT CASE
                    WHEN (@o & 1024) = 0 THEN
                        'ANSI NULL Defaults ON is set'
                    WHEN (@o & 2048) = 0 THEN
                        'ANSI NULL Defaults OFF is set'
                    ELSE
                        'ANSI NULL Defaults ON is NOT set'
                END
, 1024
         UNION
         SELECT CASE
                    WHEN (@o & 4096) = 0 THEN
                        'CONCAT_NULL_YIELDS_NULL is OFF'
                    ELSE
                        'CONCAT_NULL_YIELDS_NULL is ON'
                END
,4096
         UNION
         SELECT CASE
                    WHEN (@o & 8192) = 0 THEN
                        'NUMERIC_ROUNDABORT is OFF'
                    ELSE
                        'NUMERIC_ROUNDABORT is ON'
                END
,8192
         UNION
         SELECT CASE
                    WHEN (@o & 16384) = 0 THEN
                        'XACT Abort is OFF'
                    ELSE
                        'XACT Abort is ON'
                END
, 16384
         

I decided to put this in master so I can quickly query it from anywhere. I know this isn't recommended, but this is a utility procedure I use when we sometimes have strange behavior from T-SQL among different members of our team.

When I run this, I get a result like this:

SET option results

I don't care about ordering, because I am usually looking at the various settings and then comparing them with a set of results from another machine. This format works well for me.

If I wanted a wide result set, I'd do something like this.

USE master
GO
CREATE OR ALTER PROCEDURE dbo.sp_GetSetOptions2
AS
DECLARE @o INT
SELECT @o = @@OPTIONS;
SELECT CASE
                    WHEN (@o & 1) = 0 THEN
                        'Disable_DEFERRED_CONSTRAINT_Checking IS OFF'
                    ELSE
                        'Disable_DEFERRED_CONSTRAINT_Checking IS ON'
                END AS [BitMap 1]
, CASE
                    WHEN (@o & 2) = 0 THEN
                        'Implicit Transactions are OFF'
                    ELSE
                        'Implicit Transactions are ON'
                END AS [BitMap 2]
, CASE
                    WHEN (@o & 4) = 0 THEN
                        'Close cursor on commit is OFF'
                    ELSE
                        'Close cursor on commit is ON'
                END AS [BitMap 4]
,CASE
                    WHEN (@o & 8) = 0 THEN
                        'ANSI Warnings are OFF'
                    ELSE
                        'ANSI Warnings are ON'
                END AS [BitMap 8]
,CASE
                    WHEN (@o & 16) = 0 THEN
                        'ANSI PADDING is OFF'
                    ELSE
                        'ANSI PADDING is ON'
                END AS [BitMap 16]
,CASE
                    WHEN (@o & 32) = 0 THEN
                        'ANSI NULLs are OFF'
                    ELSE
                        'ANSI NULLs are ON'
                END AS [BitMap 32]
,CASE
                    WHEN (@o & 64) = 0 THEN
                        'ARITHABORT is OFF'
                    ELSE
                        'ARITHABORT is ON'
                END AS [BitMap 64]
, CASE
                    WHEN (@o & 128) = 0 THEN
                        'ARITHIGNORE is OFF'
                    ELSE
                        'ARITHIGNORE is ON'
                END AS [BitMap 128]
, CASE
                    WHEN (@o & 256) = 0 THEN
                        'Quoted Identifers is OFF'
                    ELSE
                        'Quoted Identifers is ON'
                END AS [BitMap 256]
, CASE
                    WHEN (@o & 512) = 0 THEN
                        'NOCOUNT is OFF'
                    ELSE
                        'NOCOUNT is ON'
                END AS [BitMap 512]
, CASE
                    WHEN (@o & 1024) = 0 THEN
                        'ANSI NULL Defaults ON is set'
                    WHEN (@o & 2048) = 0 THEN
                        'ANSI NULL Defaults OFF is set'
                    ELSE
                        'ANSI NULL Defaults ON is NOT set'
                END AS [BitMap 1024 and 2048]
, CASE
                    WHEN (@o & 4096) = 0 THEN
                        'CONCAT_NULL_YIELDS_NULL is OFF'
                    ELSE
                        'CONCAT_NULL_YIELDS_NULL is ON'
                END AS [BitMap 4096]
, CASE
                    WHEN (@o & 8192) = 0 THEN
                        'NUMERIC_ROUNDABORT is OFF'
                    ELSE
                        'NUMERIC_ROUNDABORT is ON'
                END AS [BitMap 8192]
, CASE
                    WHEN (@o & 16384) = 0 THEN
                        'XACT Abort is OFF'
                    ELSE
                        'XACT Abort is ON'
                END AS [BitMap 16384]

In this case, I included the bitwise value as the column name.

With either way, I can quickly get a set of option values decoded in my environment. Usually I'll do something like this in two sessions:

CREATE TABLE ##options(optionvalue varchar(200), bitwise int)
INSERT ##options 
EXEC dbo.sp_GetSetOptions

I'll repeat this code with a "2" for the table in another session. I can then run this code to determine if two clients have any different settings.

SELECT *
 FROM ##options2 AS o2
 INNER JOIN ##options AS o
 ON o.bitwise = o2.bitwise
 AND o2.optionvalue != o.optionvalue

Summary

Many of us rely on defaults for the creation of objects and execution of our code. In many cases, things are very consistent and this isn't an issue. However, there can be strange behaviors when defaults are changed or new team members configure systems differently. Having a way to quickly determine if our settings are the same is valuable.

Since I work in a team with people located in different countries, we sometimes find that settings have been changed, or a developer is experimenting and makes changes. When we can determine that an option has changed, we can more quickly debug the issues.

Hopefully you find this useful.

References

These are the links I used for this article:

Rate

4.75 (4)

You rated this post out of 5. Change rating

Share

Share

Rate

4.75 (4)

You rated this post out of 5. Change rating