I've seen many questions regarding the ANSI related settings,
and read some docs that state some features (like indexes on computed
columns and indexed views) can become worthless depending on
ANSI settings on or off...
So, what the recommended values for those:
ANSI_Padding
ANSI_NULLS
ANSI_WARNINGS
Concat_NULL_YELDS_NULL
QUOTED_IDENTIFIER
ARITHABORT
NUMERIC_ROUNDABORT
I would like guidelines regarding those.
For indexed views and indexed or persisted computed columns the following SET OPTIONS are all prescribed
SET options Required value
--------------------- -------------
ANSI_NULLS ON
ANSI_PADDING ON
ANSI_WARNINGS* ON
ARITHABORT ON
CONCAT_NULL_YIELDS_NULL ON
NUMERIC_ROUNDABORT OFF
QUOTED_IDENTIFIER ON
In SQL Server 2005 setting ANSI_WARNINGS to ON implicitly sets ARITHABORT to ON unless the database compatibility level is set to 80 or earlier (when it needs to be set explicitly).
Despite this it does make sense to be consistent in the ARITHABORT setting as this is used as a plan cache key and inconsistency can lead to duplicated plans wasting valuable plan cache space. You can see this from the query below.
SET ARITHABORT OFF
GO
SELECT * FROM master..spt_values WHERE number= -10 /*plan_cache_test*/
GO
SET ARITHABORT ON
GO
SELECT * FROM master..spt_values WHERE number= -10 /*plan_cache_test*/
GO
SELECT *
FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
CROSS APPLY sys.dm_exec_query_plan(plan_handle)
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
WHERE attribute = 'set_options' AND text LIKE '%plan_cache_test%'
AND text NOT LIKE '%this_query%'
Even without the indexed view / persisted column requirements the OFF settings are deprecated for the following optionsANSI_PADDING,ANSI_NULLS,CONCAT_NULL_YIELDS_NULL and XQuery and XML data modification statements requires that QUOTED_IDENTIFIER be ON.
Related
We are using MS SQL server 10.0, and running the DBCC options in two different user accounts, we get two different results. One has language us_english other as british. Where is the information stored on the server, is it possible to change it?
textsize 2147483647
language us_english
dateformat mdy
datefirst 7
lock_timeout -1
quoted_identifier SET
arithabort SET
ansi_null_dflt_on SET
ansi_warnings SET
ansi_padding SET
ansi_nulls SET
concat_null_yields_null SET
isolation level read committed snapshot
In a word, yes. This setting is set on the login that the connection is using and changes all sorts of subtle behavior. Dates are especially affected (first day of the week etc).
To view the default language settings for all logins run the following:
SELECT name, sp.default_language_name FROM master.sys.server_principals AS sp
That will show you the differences.
If you want to change the default language of a login use the following syntax:
ALTER LOGIN LoginName WITH DEFAULT_LANGUAGE = us_english
It looks like the default language for some users is different. You can change the default language for a user with the following syntax:
ALTER USER UserName WITH DEFAULT_LANGUAGE = us_english;
For more info see here.
if I have SET ANSI_WARNINGS OFF in one stored procedure to get rid of a warning, it only takes effects of that stored procedure and has no impact on other ones, which means in other stored procedures, the ANSI_WARNINGS is still on.
What if I want to turn it off for all stored procedures?
Why it is default on? How could I know that?
Do other settings(e.g., NOCOUNT) in sql server work the same way?
Thanks a lot.
It will be great if anybody can share articles about common characteristics of these settings with me.
It's possibly worth point out that not only does it NOT affect other stored procedures, it only affects statements following the SET operation
e.g. run this and you will see that the option is turned off then on and then off again.
CREATE TABLE test
(
intvalue int NULL
)
INSERT INTO test VALUES (1)
INSERT INTO test VALUES (NULL)
SET ANSI_WARNINGS OFF
SELECT COUNT(intvalue) FROM test
-- (1 row(s) affected)
SET ANSI_WARNINGS ON
SELECT COUNT(intvalue) FROM test
-- (1 row(s) affected)
-- Warning: Null value is eliminated by an aggregate or other SET operation.
SET ANSI_WARNINGS OFF
SELECT COUNT(intvalue) FROM test
-- (1 row(s) affected)
DROP TABLE test
From BOL:
SQL Server includes the ANSI_WARNINGS database option. This is
equivalent to SET ANSI_WARNINGS. When SET ANSI_WARNINGS is ON, errors
or warnings are raised in divide-by-zero, string too large for
database column, and other similar errors. When SET ANSI_WARNINGS is
OFF, these errors and warnings are not raised. The default value in
the model database for SET ANSI_WARNINGS is OFF. If not specified, the
setting of ANSI_WARNINGS applies. If SET ANSI_WARNINGS is OFF, SQL
Server uses the value of the is_ansi_warnings_on column in the
sys.databases catalog view.
You can read about it in BOL (F1 in Management Studio) or on MSDN http://msdn.microsoft.com/en-us/library/ms190368.aspx
NOCOUNT works the same.
I have a problem with my script SQL, please help me.
Ex:
I have a insert statments:
INSERT INTO CUSTOMER (Code, Date) VALUES (1, GETDATE());
When I execute this insert, retuns the follow message:
"Msg 1934, Level 16, State 1, Server
HENRIQUE-PC, Line 5 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 notificatio ns
and/or XML data type methods and/or
spatial index operations.".
Now, when I used SET QUOTED_IDENTIFIER ON, my insert is executed with success.
Ex:
SET QUOTED_IDENTIFIER OFF
GO
INSERT INTO CUSTOMER (Code, Date) VALUES (1, GETDATE());
SET QUOTED_IDENTIFIER ON
GO
(1 row(s) affected)
What relationship betwhen GETDATE() and QUOTED IDENTIFIER?
Why I need to use QUOTED IDENTIFIER in this case?
I believe it is because of getdate. Why?
Thanks.
Henrique Melicio
Henrique,
The reason you're getting that error is not related to GETDATE(), it has to do with indexes on columns from your CUSTOMER table. This bit from SQL Server 2008's SET Statements (Transact-SQL) document explains the issue in more detail:
When you are creating and manipulating
indexes on computed columns or indexed
views, the SET options ARITHABORT,
CONCAT_NULL_YIELDS_NULL,
QUOTED_IDENTIFIER, ANSI_NULLS,
ANSI_PADDING, and ANSI_WARNINGS must
be set to ON. The option
NUMERIC_ROUNDABORT must be set to OFF.
If any one of these options is not set
to the required values, INSERT,
UPDATE, DELETE, DBCC CHECKDB and DBCC
CHECKTABLE actions on indexed views or
tables with indexes on computed
columns will fail. SQL Server will
raise an error listing all the options
that are incorrectly set. Also, SQL
Server will process SELECT statements
on these tables or indexed views as if
the indexes on computed columns or on
the views do not exist.
What are the best SET Options to issue before stored procedure creation?
for example
SET QUOTED_IDENTIFIER OFF
SET ANSI_NULLS ON
CREATE PROCEDURE HelloWorld
AS
--also, should any be issued within the procedure body?
PRINT 'hello world!'
RETURN 0
GO
By best, I mean the most preferred settings.
For stored procedure creation specifically, then only two are important at parse time
SET ANSI_NULLS
SET QUOTED_IDENTIFIER
And they should be ON to work with newer SQL Server functionality that only works these being ON
Stored procedures execute with the SET settings specified at execute time except for SET ANSI_NULLS and SET QUOTED_IDENTIFIER. Stored procedures specifying SET ANSI_NULLS or SET QUOTED_IDENTIFIER use the setting specified at stored procedure creation time. If used inside a stored procedure, any SET setting is ignored.
Ref: http://msdn.microsoft.com/en-us/library/ms190356.aspx
To set both at the same time and others as well, use
SET ANSI_DEFAULTS ON
When enabled (ON), this option enables the following ISO settings:
SET ANSI_NULLS
SET CURSOR_CLOSE_ON_COMMIT
SET ANSI_NULL_DFLT_ON
SET IMPLICIT_TRANSACTIONS
SET ANSI_PADDING
SET QUOTED_IDENTIFIER
SET ANSI_WARNINGS
For completeness, set these other three at the connection level which allows things like INDEXED VIEWs to work correctly
SET ARITHABORT ON
SET CONCAT_NULL_YIELDS_NULL ON
SET NUMERIC_ROUNDABORT OFF
Transaction Isolation Level (often Read committed - to ensure no dirty reads). And unless you're interested in the number of rows affected; set nocount on
I typically don't bother setting any before the proc. In the proc Itypically use SET NOCOUNT ON and if it is just a select SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
If I right click on a table in SQL Server Management Studio and select 'Script table as > Create to > New Query Editor Window' the code that appears contains:
SET ANSI_PADDING ON
.... create the table ...
SET ANSI_PADDING OFF
So, I guess, whether ANSI_Padding is on or off affects the whole database and it is turned on to create a table and then turned off again?
What happens if you create a table with ANSI_Padding off? How can you turn it on for that table?
SET ANSI_PADDING Controls the way
the column stores values shorter than
the defined size of the column, and
the way the column stores values that
have trailing blanks in char, varchar,
binary, and varbinary data.
In a future version of MicrosoftSQL Server ANSI_PADDING will
always be ON and any applications that
explicitly set the option to OFF will
produce an error. Avoid using this
feature in new development work, and
plan to modify applications that
currently use this feature.
This setting affects only the definition of new columns. After the column is created, SQL Server stores the values based on the setting when the column was created. Existing columns are not affected by a later change to this setting.
So, I guess, whether ANSI_Padding is on or off affects the whole database and it is turned on to create a table and then turned off again?
no, the SET option only affects the context of your connection, if 2 connections come in and one has ANSI_PADDING OFF and the other one ON they don't affect the other connection. However....the table created in one connection will have the behavior that the setting did to it.
read more here http://msdn.microsoft.com/en-us/library/ms190356.aspx
So if connection 1 comes in with set ansi_nulls off
then select * from bla where col = null will work
this however won't work for connection 2 if it comes with with the default ansi_nulls setting (ON)
you can see what you settings are by either executing dbcc useroptions or if you are on 2005 and up
SELECT SPID,VALUE,ANSI_SETTING
FROM (
SELECT ##SPID AS SPID,
CASE quoted_identifier
WHEN 1 THEN 'SET' ELSE 'OFF' END QUOTED_IDENTIFIER,
CASE arithabort
WHEN 1 THEN 'SET' ELSE 'OFF' END ARITHABORT,
CASE ansi_null_dflt_on
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_NULL_DFLT_ON,
CASE ansi_defaults
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_DEFAULTS ,
CASE ansi_warnings
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_WARNINGS,
CASE ansi_padding
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_PADDING,
CASE ansi_nulls
WHEN 1 THEN 'SET' ELSE 'OFF' END ANSI_NULLS,
CASE concat_null_yields_null
WHEN 1 THEN 'SET' ELSE 'OFF' END CONCAT_NULL_YIELDS_NULL
FROM sys.dm_exec_sessions
WHERE session_id = ##SPID ) P
UNPIVOT (VALUE FOR ANSI_SETTING IN(
QUOTED_IDENTIFIER,ARITHABORT,ANSI_NULL_DFLT_ON,
ANSI_DEFAULTS,ANSI_WARNINGS,
ANSI_PADDING,ANSI_NULLS,CONCAT_NULL_YIELDS_NULL
)
) AS unpvt