Understanding SET QUOTED_IDENTIFIER ON/OFF and SET ANSI_NULLS ON/OFF

Written by Ranjith in SQL Server

These are the two widely used SET options in SQL Server. Most developers explicitly set these options while creating Stored Procedures, Triggers and User Defined Functions but many are unclear on why we need to explicitly SET them? And why they are special compared to other options?

這兩個SET 選項是在SQL SERVER中被廣泛使用的選項。大多數的開發人員都會在創建存儲過程,觸發器,和自定義函數時,明確設置這些選項,但是還是有很多人不清楚我們爲什麼要明確設置這些選項?並且也不清楚這些選擇和其他的選項比,有什麼特別之處?

Below is the typical usage of these options.

下面是這些選項的典型用法

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE SampleProcedure
AS
BEGIN
 -- select employees
 SELECT * FROM HumanResources.Employee
END

Lets first understand what they exactly mean to SQL Server and then we will move on to why they are special.

首先讓我們理解這些選項在SQL SERVER中準確的含義,然後我們再看下這些選項的特別之處。

SET QUOTED_IDENTIFIER ON/OFF:

It specifies how SQL Server treats the data that is defined in Single Quotes and Double Quotes. When it is set to ON any character set that is defined in the double quotes “” is treated as a T-SQL Identifier (Table Name, Proc Name, Column Name….etc) and the T-SQL rules for naming identifiers will not be applicable to it. And any character set that is defined in the Single Quotes ‘’ is treated as a literal.

SET QUOTED_IDENTIFIER選項,指明瞭SQL SERVER應該如果對待定義在單引號中間,和雙引號中間的數據;

當這個選項被設置成ON時,任何被定義在雙引號中間的字符都被當做T-SQL的標識符(如:表名,過程名,列名...等),

在使用了雙引號括起來的標識符不會受到T-SQL的標識符命名的限制。

在SET QUOTED_IDENTIFIER爲ON時,任何被定義單單引號中間的字符,都會被當做一個字符串。

 

SET QUOTED_IDENTIFIER ON CREATE TABLE "SELECT" ("TABLE" int) -- SUCCESS GO(可以成功執行)

SET QUOTED_IDENTIFIER ON SELECT "sometext" AS Value -- FAIL because “sometext” is not a literal(這個執行會失敗)

 

Though the SELECT” and “TABLE” are reserved keywords  we are able to create the table because they are now treated as identifiers and the T SQL rules for identifier names are ignored.

儘管SELECT 和TABLE是保留的關鍵字,但是我們是可以創建這樣的表的,因爲它們現在是被當做標識符(如表名,過程名等),並且這時T-SQL的標識符命名規則是被忽略的(即,執行時不會報標識符不合法的錯誤)。

When it is set to OFF any character set that is defined either in Single Quotes or in Double Quotes is treated as a literal.

當將SET QUOTED_IDENTIFIER選項設置爲OFF時,任何定義在單引號或者是雙引號中間的字符都會被當做字符串看待。

 

SET QUOTED_IDENTIFIER OFF CREATE TABLE "SELECT"(“TABLE” int) -- FAIL GO(這個執行失敗)

SET QUOTED_IDENTIFIER OFF SELECT "sometext" AS Value -- SUCCESS as “sometext” is treated as a literal(這個執行成功)

 

You can clearly see the difference in CREATE TABLE and SELECT query. Here the CREATE TABLE fails because “SELECT” is a reserved keyword and it is considered as a literal. The default behavior is ON in any database.

你能清楚看出CREATE TABLE和SELECT 查詢之間的不同,這裏CREATE TABLE失敗是因爲SELECT 是一個保留關鍵字,並且他也被當做是一個字符串。默認在任何數據庫上這個選項默認都是ON的(這個實踐中未必是這樣,這裏說的不對)。

SET ANSI_NULLS ON/OFF:

The ANSI_NULLS option specifies that how SQL Server handles the comparison operations with NULL values. When it is set to ON any comparison with NULL using = and <> will yield to false value. And it is the ISO defined standard behavior. So to do the comparison with NULL values we need to use IS NULL and IS NOT NULL. And when it is set to OFF any comparison with NULL using = and <> will work as usual i.e. NULL = NULL returns true and 1= NULL returns false.

ANSI_NULLS選項指明瞭SQL SERVER如何處理和NULL值的比對操作。

當這個選項被設置爲ON時,任何用“=”“<>”操作符和NULL值做比對,都會返回false值。這個行爲是ISO定義的標準行爲。所以如果我們想要是不是NULL,需要使用IS NULL或者IS NOT NULL進行。

當ANSI_NULLS選項被設置成OFF時,所有用=,<>操作符和NULL值做比較時,就和一般的情形一致,即:NULL=NULL返回true,而1=NULL返回false.

示例代碼如下:

SET ANSI_NULLS ON
IF NULL = NULL
 PRINT 'same'
ELSE
 PRINT 'different'
--result:  different

SET ANSI_NULLS ON
IF NULL IS NULL
 PRINT 'same'
ELSE
 PRINT 'different'
-- result: same
SET ANSI_NULLS OFF
IF NULL = NULL
 PRINT 'same'
ELSE
 PRINT 'different'
--result:  same (now NULL = NULL works as 1=1)

The default behavior is ON in any database. As per BOL 2008 this option will always be set to ON in the future releases of SQL Server and any explicit SET to OFF will result an error. So avoid explicitly setting this option in future development work.

在任何數據庫上這個選項默認爲ON(這裏說的未必正確,具體以實踐爲準),按照SQL SERVER2008的在線書籍(BOL =Book Online)這個選項將來會只允許被設置爲ON,如果有任何通過SET嘗試設置爲OFF的操作,都會導致一個錯誤。

所以,在未來的開發工作中要避免明確設置這個選項的值。

 

Why are these two options Special?

爲什麼這兩個選項是特別的?

These two SET options are special because whenever a stored procedure or a Trigger or a User Defined Function is created or modified with these options explicitly SET; SQL Server remembers those settings in the associated object metadata. And every time the object (stored procedure,Trigger..etc.) is executed SQL server uses the stored settings irrespective of what the current user session settings are. So the behavior of the stored procedure is not altered by the calling session settings and the usage of the SET option behavior inside the SP is always guaranteed.

這兩個選項會在存儲過程,觸發器,自定義函數中記錄這些選項的值;從而忽略數據庫會話中其他的設置值;

所以如果一個存儲過程,觸發器,或者函數如果定義了選項值,那麼即便在會話的其他地方設置了一個不同的值,那麼在

執行這些存儲過程,觸發器,函數的時候也不會使用這些不同值,依然會使用它們自身存儲的值。

You can get any procedure or trigger or function settings for these options from the sys..sql_modules metadata table.

你可以通過下面的語句查詢出某個過程,觸發器,或者函數存儲的兩個選項的值。

SELECT uses_ansi_nulls, uses_quoted_identifier
 FROM sys.sql_modules WHERE object_id = object_id('SampleProcedure')

And if you need to guarantee the behavior for other SET options like SET ARITHABORT inside the SP then you need to SET them inside the procedure. The scope of the options specified inside the procedure are only applicable until the procedure completes its execution.

然而,如果你想要保證其他的SET選項在你SP中的值,那麼只需要在這個SP的裏面設置這個選項就可以了,比如:ARITHABORT選項,一旦這個過程執行完了,這些選項就會恢復爲默認值。

Hope it helps.

– Ranjith

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章