Sql-Server

一個腳本中的多個 Set Quoted_identifier 採用最後一個?

  • June 17, 2021

我正在使用 SQL Server 2019,但發現了一個奇怪的行為。研究並沒有讓我更進一步。

有人可以解釋這種行為嗎?

SET QUOTED_IDENTIFIER ON; 
if ((256 & @@options) = 256) print '1- quoted_identifier is on' else print '1- quoted_identifier is off';
BEGIN TRY 
   if ((256 & @@options) = 256) print '2- quoted_identifier is on' else print '2- quoted_identifier is off';
END TRY 
BEGIN CATCH
   if ((256 & @@options) = 256) print '3- quoted_identifier is on' else print '3- quoted_identifier is off';
   -- SET QUOTED_IDENTIFIER OFF
   -- if ((256 & @@options) = 256) print '4- quoted_identifier is on' else print '4- quoted_identifier is off';
END CATCH

回報:

1- quoted_identifier is on
2- quoted_identifier is on

但以下程式碼:

SET QUOTED_IDENTIFIER ON; 
if ((256 & @@options) = 256) print '1- quoted_identifier is on' else print '1- quoted_identifier is off';
BEGIN TRY 
   if ((256 & @@options) = 256) print '2- quoted_identifier is on' else print '2- quoted_identifier is off';
END TRY 
BEGIN CATCH
   if ((256 & @@options) = 256) print '3- quoted_identifier is on' else print '3- quoted_identifier is off';
   SET QUOTED_IDENTIFIER OFF
   if ((256 & @@options) = 256) print '4- quoted_identifier is on' else print '4- quoted_identifier is off';
END CATCH

回報:

1- quoted_identifier is off
2- quoted_identifier is off

即使它沒有進入擷取!我肯定錯過了什麼。

我什至能夠將程式碼簡化為最簡單的:

SET QUOTED_IDENTIFIER ON; 
if ((256 & @@options) = 256) print '1- quoted_identifier is on' else print '1- quoted_identifier is off';
SET QUOTED_IDENTIFIER OFF
if ((256 & @@options) = 256) print '2- quoted_identifier is on' else print '2- quoted_identifier is off';

結果:

1- quoted_identifier is off
2- quoted_identifier is off

我有一些使用 的程式碼FOR XML,這要求我將帶引號的標識符設置為 ON,但無論 XML 部分成功還是失敗,我都需要將其設置回 OFF。你會怎麼做?

我的測試表明,如果我在SET QUOTED_IDENTIFIER中關閉 to CATCH,插入無法說明我引用的標識符沒有正確設置,儘管它設置在TRYto的開頭ON

Charlieface的回答似乎已經適當地解釋了您在使用時描述的行為的原因SET QUOTED_IDENTIFIER,所以如果您需要在 SP 中使用它,我將留下一個您可以使用的方法:

建議的解決方案

在另一個過程中隔離您的批處理的一部分,並從QUOTED_IDENTIFIER需要OFF這樣的過程中呼叫它:db<>fiddle - 在您的電腦上執行 2 個不同的會話,因為我無法使其在 dbfiddle 上正常執行。

這是設計使然:

對於頂級 ad-hoc 批處理解析開始使用會話的目前設置QUOTED_IDENTIFIER。在解析批處理時,任何出現的SET QUOTED_IDENTIFIER都會從那時起更改解析行為,並為會話保存該設置。所以在批處理解析並執行後,會話的QUOTED_IDENTIFER設置將根據SET QUOTED_IDENTIFIER批處理中最後一次出現的設置。

**因此, 的行為QUOTED_IDENTIFIER取決於批處理的解析,而不是執行。**解析批處理開始時的預設值來自目前的連接設置。

**@@OPTIONS僅向您顯示目前預設值,**如果解析了批處理,則將使用該預設值。這就是為什麼 SSMS 總是放在SET一個單獨的批次中。

的執行與SET的行為無關@@OPTIONS,除了更改以後批次的預設值。


您可以在 db-fiddle 中看到這一點

set QUOTED_IDENTIFIER  on;
create table "select"(i int);
drop table "select";
GO

set QUOTED_IDENTIFIER  off;
create table "select"(i int);
drop table "select";
--  Incorrect syntax near 'select'.
GO

set QUOTED_IDENTIFIER  off;
if (1=0)
begin
   set QUOTED_IDENTIFIER  on;
end
create table "select"(i int);
drop table "select";
GO

set QUOTED_IDENTIFIER  on;
if (1=0)
begin
   set QUOTED_IDENTIFIER  off;
end
create table "select"(i int);
drop table "select";
-- Incorrect syntax near 'select'.
GO

引用自:https://dba.stackexchange.com/questions/290663