Понимание QUOTED_IDENTIFIER - PullRequest
       6

Понимание QUOTED_IDENTIFIER

10 голосов
/ 20 сентября 2011

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

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 выполняется с идентификатором в кавычках с .Я изменил наш скрипт, чтобы включить ключ -I, чтобы посмотреть, исправит ли это наши проблемы.

Мои вопросы тогда:

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

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

@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 для хранимых процедур, и принятый ответ на них предоставляет некоторые подробности об общих правилах, касающихся общего порядка приоритета, который применяется к опциям SET.В комментариях к этому также говорится, что

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

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

Есть ли кто-нибудь для второй части?

Ответы [ 4 ]

9 голосов
/ 24 августа 2017

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

Короткая версия

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

SQL Server первоначально:

  • SELECT "Hello, world!" - кавычка
  • SELECT 'Hello, world!' - апостроф
  • CREATE TABLE [The world's most awful table name] ([Hello, world!] int)
  • SELECT [Hello, world!] FROM [The world's most awful table name]

ANSI (т. Е. SET QUOTED_IDENTIFIER ON):

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

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

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

  • SELECT "Hello, world!" -кавычка
  • SELECT 'Hello, world!' - апостроф

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

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

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

Затем появился ANSI

Затем появился ANSI и пришел к другим идеям:

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

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

SELECT "Hello, world!" FROM "The world's 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's most awful table name'.

Youдолжен подключиться к новому поведению 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 вы не можете использовать "double quote quotation mark around strings", вы должны использовать только 'the single quote apostrophe'.

2 голосов
/ 20 сентября 2011

Я сохранил следующую команду в текстовый файл, а затем выполнил ее с 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

, а затем запускает мой сценарий.

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

0 голосов
/ 24 января 2017

По поводу вашего вопроса # 1 причина указана в Замечания при использовании операторов SET . В нем говорится:

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

0 голосов
/ 24 ноября 2011
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.

...