We just ran into a problem with one of our stored procs throwing an error;
SELECT failed because the following SET options have incorrect settings: \'QUOTED_
I saved the following command to a textfile, then executed it with SQLCMD:
SET QUOTED_IDENTIFIER ON
SET QUOTED_IDENTIFIER OFF
Checking in SQL profiler, SQLCMD -i <filename>
connects with the following connection options on my system:
-- network protocol: LPC
set quoted_identifier on
...
however the following command issued by SQLCMD when it connects:
SET QUOTED_IDENTIFIER OFF SET TEXTSIZE 4096
and then it runs my script.
So, the answer to 2) is no - running a script with SQLCMD -i
is not the same as executing from SSMS (with the default connections options). If a script requires QUOTED_IDENTIFIER ON
, then you need to explicitly set it at the start if you're going to execute it this way.
Looking for an understanding of QUOTED_IDENTIFIER
i will post some understanding here.
ANSI demanded that quotation marks be used around identifiers (not around strings). SQL Server supported both:
SQL Server originally:
SELECT "Hello, world!"
--quotation markSELECT 'Hello, world!'
--apostropheCREATE TABLE [The world's most awful table name] ([Hello, world!] int)
SELECT [Hello, world!] FROM [The world's most awful table name]
ANSI (i.e. SET QUOTED_IDENTIFIER ON
):
SELECT "Hello, world!"
--quotation mark no longer valid in ANSI around stringsSELECT 'Hello, world!'
--apostropheCREATE TABLE "The world's most awful table name" ("Hello, world!" int)
SELECT "Hello, world!" FROM "The world's most awful table name"
Originally, SQL Server allowed you to use quotation marks ("..."
) and apostrophes ('...'
) around strings interchangeably (like Javascript does):
SELECT "Hello, world!"
--quotation markSELECT 'Hello, world!'
--apostropheAnd if you wanted a name table, view, procedure, column etc with something that would otherwise violate all the rules of naming objects, you could wrap it in square brackets ([
, ]
):
CREATE TABLE [The world's most awful table name] ([Hello, world!] int)
SELECT [Hello, world!] FROM [The world's most awful table name]
And that all worked, and made sense.
Then ANSI came along and had other ideas:
"..."
)'...'
) for stringsWhich means that if you wanted to "quote" a funky column or table name you must use quotation marks:
SELECT "Hello, world!" FROM "The world's most awful table name"
If you knew SQL Server, you knew that quotation marks were already being used to represent strings. If you blindly tried to execute that ANSI-SQL as though it were T-SQL: it's nonsense, and SQL Server told you so:
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near 'The world's most awful table name'.
So Microsoft added a feature to let you opt-in to the ANSI flavor of SQL.
Original
SELECT "Hello, world!" --valid
SELECT 'Hello, world!' --valid
SET QUOTED_IDENTIFIER ON
SELECT "Hello, world!" --INVALID
SELECT 'Hello, world!' --valid
SQL Server still lets you use [square brackets]
, rather than forcing you to use "quotatio marks"
. But with QUOTED_IDENTIFIER ON, you cannot use "double quote quotation mark around strings"
, you must only use 'the single quote apostrophe'
.
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
--SQL PROCEDURE, SQL FUNCTIONS, SQL OBJECTGO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
ANSI NULL ON/OFF:
This option specifies the setting for ANSI NULL comparisons. When this is on, any query that compares a value with a null returns a 0. When off, any query that compares a value with a null returns a null value.
QUOTED IDENTIFIER ON/OFF:
This options specifies the setting for usage of double quotation. When this is on, double quotation mark is used as part of the SQL Server identifier (object name). This can be useful in situations in which identifiers are also SQL Server reserved words.
About your question #1, the reason is stated in Considerations When You Use the SET Statements. It states:
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.