Понимание QUOTED_IDENTIFIER

Мы только столкнулись с проблемой, когда одна из наших хранимых процедур выкинула ошибку;

SELECT failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'

Я исправил его, модифицировав сохраненный процесс и установив котируемый идентификатор в положение ON. Дело в том, что я сделал это до вызова CREATE PROCEDURE. Например:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[InsertStuff]

Я бы подумал, что это повлияло на инструкцию CREATE PROCEDURE, но не повлияло бы на какое-либо действие с выполнением этой процедуры.

Наши скрипты развернуты как откат, так и создают скрипты и запускаются через sqlcmd. Я только что прочитал, что здесь (поиск для примера: Выполнение SQLCMD) и здесь что sqlcmd выполняется с указанным идентификатором. Я изменил наш script, включив ключ -I, чтобы проверить, устраняет ли это наши проблемы.

Теперь мои вопросы:

1) Выполняет ли оператор SET QUOTED_IDENTIFIER ON только инструкцию DDL CREATE PROCEDURE или влияет также на выполнение хранимой процедуры? Мой быстрый тест показывает последний.

2) Поскольку значение по умолчанию для этого переключателя включено, я предполагаю, что при установке переключателя -I моего запроса sqlcmd не будет никаких негативных последствий. Для всех целей и целей я буду считать, что это то же самое, что копировать содержимое script, а затем вставлять их в диспетчер запросов и выполнять выполнение. Пожалуйста, поправьте меня, если я ошибаюсь. Наше простое развертывание script выглядит следующим образом:

@echo off

SET dbodir=../Schema Objects/Schemas/dbo/Programmability/Stored Procedures/
SET tpmdir=../Schema Objects/Schemas/TPM/Programmability/Stored Procedures/

echo --- Starting dbo schema

for %%f in ("%dbodir%*.sql") do (echo Running %%f.... && @sqlcmd -I -U %1 -P %2 -S %3 -d %4 -i "%dbodir%%%f")

echo --- Completed dbo schema

echo --- Starting TPM schema

for %%g in ("%tpmdir%*.sql") do (echo Running %%g.... && @sqlcmd -I -U %1 -P %2 -S %3 -d %4 -i "%tpmdir%%%g")

echo --- Completed TPM schema

pause

Заранее спасибо

Изменить:

Кажется, что есть дополнительная дополнительная информация, чтобы определить, где хранятся параметры SET для сохраненных procs, и принятый ответ на это предоставляет некоторые сведения об общих правилах в отношении общего порядка приоритета, который применяется к параметрам SET. В комментариях к этому также указывается, что

"... Только настройки QUOTED_IDENTIFER и ANSI_NULLS фиксируются во время создания процедуры." "... SET QUOTED IDENTIFIER не может быть установлен во время выполнения внутри хранимой процедуры" (мой акцент).

Я чувствую, что отвечает на мой первый вопрос.

Любые участники второй части?

Ответ 1

Я сохранил следующую команду в текстовом файле, а затем выполнил ее с помощью SQLCMD:

SET QUOTED_IDENTIFIER ON
SET QUOTED_IDENTIFIER OFF

Проверка в профилировщике SQL, SQLCMD -i <filename> соединяется со следующими параметрами подключения в моей системе:

-- network protocol: LPC
set quoted_identifier on
...

однако следующая команда, выпущенная SQLCMD при ее подключении:

SET QUOTED_IDENTIFIER OFF SET TEXTSIZE 4096

а затем он запускает мой script.

Итак, ответ на вопрос 2) не работает. script с SQLCMD -i - это не то же самое, что и выполнение из SSMS (с параметрами подключения по умолчанию). Если для script требуется QUOTED_IDENTIFIER ON, тогда вам нужно явно установить его в начале, если вы собираетесь его выполнить таким образом.

Ответ 2

В поисках понимания QUOTED_IDENTIFIER я опубликую некоторое понимание здесь.

Укороченная версия

ANSI потребовала использовать кавычки вокруг идентификаторов (не вокруг строк). SQL Server поддерживает оба:

SQL Server изначально:

  • SELECT "Hello, world!" --quotation отметка
  • SELECT 'Hello, world!' --apostrophe
  • CREATE TABLE [The world most awful table name] ([Hello, world!] int)
  • SELECT [Hello, world!] FROM [The world most awful table name]

ANSI (т. SET QUOTED_IDENTIFIER ON):

  • SELECT "Hello, world!" Метка --quotation больше не действует в ANSI вокруг строк
  • SELECT 'Hello, world!' --apostrophe
  • CREATE TABLE "The world most awful table name" ("Hello, world!" int)
  • SELECT "Hello, world!" FROM "The world most awful table name"

Старые времена

Первоначально SQL Server позволял вам использовать кавычки ("...") и апострофы ('...') вокруг строк взаимозаменяемо (как это делает Javascript):

  • SELECT "Hello, world!" --quotation отметка
  • SELECT 'Hello, world!' --apostrophe

И если вам нужна таблица имен, представление, процедура, столбец и т.д. С чем-то, что иначе нарушало бы все правила именования объектов, вы можете заключить их в квадратные скобки ([, ]):

CREATE TABLE [The world most awful table name] ([Hello, world!] int)
SELECT [Hello, world!] FROM [The world most awful table name]

И все это работало и имело смысл.

Затем пришел ANSI

Затем появился ANSI, и у него появились другие идеи:

  • если у вас есть прикольное имя, заключите его в кавычки ("...")
  • используйте апостроф ('...') для строк
  • и мы даже не заботимся о ваших квадратных скобках

Это означает, что если вы хотите "заключить в кавычки" интересный столбец или имя таблицы, вы должны использовать кавычки:

SELECT "Hello, world!" FROM "The world most awful table name"

Если вы знали SQL Server, вы знали, что кавычки уже использовались для представления строк. Если вы слепо пытались выполнить этот ANSI-SQL, как если бы это был T-SQL: это чепуха, и SQL Server сказал вам следующее:

Msg 102, Level 15, State 1, Line 8
Incorrect syntax near 'The world most awful table name'.

Вы должны подписаться на новое поведение ANSI

Поэтому Microsoft добавила функцию, позволяющую вам подключиться к ANSI-варианту SQL.

оригинал

SELECT "Hello, world!" --valid
SELECT 'Hello, world!' --valid

SET QUOTED_IDENTIFIER ON

SELECT "Hello, world!" --INVALID
SELECT 'Hello, world!' --valid

SQL Server по-прежнему позволяет использовать [square brackets], вместо того, чтобы заставлять вас использовать "quotatio marks". Но с QUOTED_IDENTIFIER ON вы не можете использовать "double quote quotation mark around strings", вы должны использовать только 'the single quote apostrophe'.

Ответ 3

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:

Этот параметр определяет настройку ANSI NULL-сравнений. Когда это включено, любой запрос, который сравнивает значение с нулем, возвращает значение 0. Когда выкл., Любой запрос, который сравнивает значение с нулем, возвращает нулевое значение.

QUOTED IDENTIFIER ON/OFF:

В этом параметре задается параметр для использования двойной кавычки. Когда это включено, двойная кавычка используется как часть идентификатора SQL Server (имя объекта). Это может быть полезно в ситуациях, когда идентификаторы также являются зарезервированными словами SQL Server.

Ответ 4

О вашем вопросе № 1, причина указана в Соображения при использовании утверждений SET. В нем указано:

Сохраненные процедуры выполняются с настройками SET, указанными во время выполнения, за исключением SET ANSI_NULLS и SET QUOTED_IDENTIFIER. Хранимые процедуры, определяющие SET ANSI_NULLS или SET QUOTED_IDENTIFIER, используют настройку, указанную во время создания хранимой процедуры. Если используется внутри хранимой процедуры, любая настройка SET игнорируется.