SQL Server Stored Procedure SET Options - sql-server

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

Related

SET QUOTED_IDENTIFIER ON within the stored procedure is not working

I am using FOR XML PATH in my stored procedure and so that I need to have QUOTED_IDENTIFIER set to ON. I have it as a first statement of my stored procedure.
SET QUOTED_IDENTIFIER ON;
This is working fine all the times except I restore my database first time.
Just after restoring the database, I checked sp_helptext <SPName> and the stored procedure seems fine.
However when I browse my stored procedure from the Object Explorer and click on "Modify", it shows this:
When I tried executing the stored procedure using EXEC <SP_Name> it throws an error
SELECT 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.
Can someone guide me why SQL Server is adding SET QUOTED_IDENTIFIER OFF on its own? How to get rid of it? or How can we overwrite it from within the stored procedure?
If I remove SET QUOTED_IDENTIFIER OFF from the top, re-execute/run it then it will work fine.
My problem is - We have automated process which runs migrations/create database on every build so I can not remove it manually all the times.
I also can not set it on the database level.
I checked the database setting for that and its set to false but that should not make any difference right? As I have it specifically SET To ON inside my stored procedure.
Thank you in advance.
The QUOTED_IDENTIFIER database setting is irrelevant. It's only a default, every client driver sets QUOTED_IDENTIFIER on connecting and overrides the database default.
The SET QUOTED_IDENTIFIER inside the stored procedure is irrelevant; remove it.
SET QUOTED_IDENTIFIER has no effect when it appears in the body of a
stored procedure as static Transact-SQL.
SET QUOTED_IDENTIFIER
The setting for QUOTED_IDENTIFIER which was in force for the batch creating the stored procedure will be stored in the catalog, and used by SSMS to script the stored procedure. It does not matter what the current session setting is, or the database default is, or what the SSMS query options are. If it was created with QUOTED_IDENTIFIER ON it will be scripted with QUOTED_IDENTIFIER ON. You can see the stored setting here in sys.sql_modules.
eg
select uses_quoted_identifier
from sys.sql_modules
where object_id = object_id('MyProc')
So,
However when I browse my stored procedure from the Object Explorer and click on "Modify", it [is scripted with QUOTED_IDENTIFER OFF].
If the setting in sys.sql_modules different than the setting in the generated script, that would be a bug in SSMS/SMO.
And this:
means that the stored procedure was created with QUOTED_IDENTIFIER OFF. As you see the session setting for the session invoking the stored procedure is irrelevant.
When a stored procedure is created, the SET QUOTED_IDENTIFIER and SET
ANSI_NULLS settings are captured and used for subsequent invocations
of that stored procedure.
SET QUOTED_IDENTIFIER
This stored procedure's setting also controls the QUOTED_IDENTIFIER setting for dynamic SQL inside the stored procedure. But inside dynamic SQL you can change the setting.
And so yes
My problem is - We have automated process which runs migrations/create database on every build
This process is broken, as it's creating your proc with QUOTED_IDENTIFIER OFF. If you can't fix it you can work around it by pushing your TSQL into a dynamic batch, and setting QUOTED_IDENTIFIER ON in the dynamic SQL. eg
set quoted_identifier off
go
create or alter procedure foo
as
begin
exec ('set quoted_identifier on; select * from "sys"."objects"')
end
go
exec foo --suceeds
Also you can make your stored procedure create script depend on QUOTED_IDENTIFIER ON so you can't possibly create it with QUOTED_IDENTIFIER OFF, eg
set quoted_identifier off
go
create or alter procedure foo
as
begin
select * from "sys"."objects"
end
fails with
Msg 102, Level 15, State 1, Procedure foo, Line 4 [Batch Start Line 2]
Incorrect syntax near 'sys'.
please test bellow statment:
USE MyDB
GO
SET QUOTED_IDENTIFIER on;
GO
EXISTS ....
BEGIN
EXEC ...
END

QUOTED IDENTIFIER error in SQL Server 2008 on SP execution

I have this error on executing stored procedure:
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.
Procedure is created with QUOTED_IDENTIFIER flag set to ON
IF EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'sp_procedure') AND TYPE IN (N'P', N'PC'))
BEGIN
DROP PROCEDURE [dbo].[sp_procedure]
END
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_procedure]
(
#param_1 XML
,#param_2 INT
)
AS
BEGIN
-- CODE
END
SELECT statement from sys.sql_modules shows that uses_quoted_identifiers somehow is set to 0.
I have already tried to execute following code. It run in one batch.
SET QUOTED_IDENTIFIER ON;
EXEC sp_procedure #param_1 = N'<?xml version="1.0" encoding="utf-16"?>
xmlns:xsd="http://www.w3.org/2001/XMLSchema" />', #param_2= 51326
But it does not help.
Each session is created with QUOTED_IDENTIFIER set to 1:
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
Any ideas what can it be?
UPD
Turned out that after running this specific script, there also run lots of other files. And one of them just recreated stored procedure with QUOTED_IDENTIFIER set to OFF.
Thank you for your help
Pleasure make sure the table and view definitions are also created with quoted identifier on.

SQL query taking too long to execute (SQL server 2008 R2)

I have a problem in my application while executing a SQL query. I attached SQL Profiler to see the problem.
A query like
SELECT abc_id
FROM abc_Master
WHERE abc_name = #abcName COLLATE SQL_Latin1_General_CP1_CS_AS
AND (status=''active'' OR status=''live'')
is taking 60.102 seconds to execute.
I have noticed an audit login log record above this query log in server profiler trace list.
-- network protocol: TCP/IP
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed
Is this causing the delay? why is the query taking 60 secs to execute?

Heterogeneous queries require the ANSI_NULLS and ANSI_WARNINGS options to be set for the connection. This ensures consistent query semantics

I have checked over the whole web and couldn't find a solution that seems to work for me..
I have recreated my stored procedure, making sure to have these lines as first lines:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_WARNINGS ON
GO
CREATE PROCEDURE test_insert
AS
....
BEGIN
...
END
I only get this error when i call my stored procedure from php. it works fine in sql server..
i really don't know what else i can do..please help me ;_;
Added this BEFORE your statement rather than at the start of the main query
$result = mssql_query("SET ANSI_NULLS ON;");
$result = mssql_query("SET ANSI_WARNINGS ON;");
This is an example that works...
Try it like this
create procedure dbo.access_update #O_SQL_Error_State int = NULL output
as
set ANSI_NULLS ON
SET ANSI_WARNINGS ON
....
....
GO
Its not often a better answer is on another forum - but according to this post, the SET commands must be before the CREATE PROCEDURE. Tested and works with SQL Server 2017.
For example:
SET ANSI_WARNINGS ON
SET ANSI_NULLS ON
GO
CREATE PROCEDURE dbo.access_update
#O_SQL_Error_State int = NULL OUTPUT
AS
...

How to set "SET XACT_ABORT ON " in a SQL Server transaction?

I want to set SET XACT_ABORT ON in a SQL Server 2008R2 stored procedure with a transaction, so do it in a creation script:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET XACT_ABORT ON
GO
CREATE PROCEDURE MyProc
AS
BEGIN TRAN
...
IF ##ERROR <> 0
BEGIN
GOTO Done
END
...
IF ##ERROR <> 0
BEGIN
GOTO Done
END
COMMIT TRAN
Done:
IF ##ERROR <> 0
BEGIN
ROLLBACK TRAN
END
GO
After successful creation, I check the transaction by clicking "Modify" stored procedure option and in a generated ALTER PROCEDURE script I don't see SET XACT_ABORT ON line:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE MyProc
AS
BEGIN TRAN
...
Where am I wrong or what is the trick? How to correctly define SET XACT_ABORT ON?
You normally set xact_abort as part of the body of the stored procedure:
CREATE PROCEDURE MyProc
AS
SET XACT_ABORT ON
BEGIN TRAN
....
There are two "special" settings that are remembered from the session that created the procedure. Explanation from MSDN:
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.
So when you create a stored procedure, SQL Server copies the QUOTED_IDENTIFIER option from the connection to the procedure definition. The goal is that someone else with a different QUOTED_IDENTIFIER setting still gets the behavior the author of the procedure intended.
The same is not true for XACT_ABORT.
You didn't mention whether or not you are using SQL Management Studio, but if you are and click "Modify" on an existing stored procedure (which I'm assuming is what you did) then MS just generates a boilerplate script based on the contents of the existing stored procedure.
You might consider defining your stored procedures in a separate script file that performs and ALTER PROCEDURE, plus whatever other options you want outside of the sproc (such as SET XACT_ABORT ON). That way you have more control and can just execute the script to update the sproc.

Resources