2010-11-15 123 views
7

今天我遇到了一個有趣的問題。我正在修改一個存儲過程,並在最後輸入select語句。它只是暫時的,只是爲了處理數據。後來我很驚訝地發現,聲明得到保存並在SP運行時執行。存儲過程結束後的語句

SET ANSI_NULLS ON 
GO 

-- Comments usually go here and are saved as part of the SP 
ALTER PROCEDURE [dbo].[MySP] 
    @param INT 
AS 
BEGIN 
    --Your normal SQL statements here 
END 

--You can also add SQL statements here 
select * from LargeTable 

--You have access to the params 
select @param 

這是有道理的,一切都被保存,不只是裏面是什麼BEGIN/END,否則意見和SET ANSI_NULLS等就會消失。我有點困惑,從哪裏開始,所以我有幾個問題:

  1. SET ANSI_NULLS被保存爲SP的一部分。我已經確認每個SP都有自己的價值。 SQL Server如何知道將它保存爲SP的一部分,因爲它之前未被引用?它是否會對當前環境狀態進行全面掃描,然後當ALTER PROCEDURE運行時會保存狀態(可能只有非默認值)?
  2. 顯然BEGIN/END是可選的,沒有內在的意義。他們爲什麼甚至包括在內呢?他們給出了一個不存在的範圍的錯覺。在我看來,沒有BEGIN/END和GO在最後會是最有意義的。
+1

BEGIN/END用於作用域,如在IF/WHILE /等中包含多個語句。坦率地說,與PLSQL相比,TSQL非常殘酷 - 它在結構/組織方面比BEGIN/END更加結構化,並且使用分號來終止行。就像TSQL在WITH/CTE之前需要一個分號一樣,如果你在它之前聲明變量......:/任何具有C語言經驗的人都可以被賦予PLSQL並能夠讀取它。不能說,對於TSQL ... – 2010-11-15 20:40:56

+0

@OMG - 那麼在這種情況下它給出了什麼「範圍」?我能想象的唯一的事情是,如果你在BEGIN/END中聲明瞭一個變量,那麼它在外面是不可用的。爲什麼你會把SQL語句放在外面;你爲什麼不把所有的東西都放在外面,而不是BEGIN/END? – 2010-11-15 20:45:09

+1

這個例子是有效的,我沒有說它是智能的;) – 2010-11-15 20:47:42

回答

5

ANSI NULLS和引用標識符存儲爲存儲過程代碼的元數據屬性。您可以通過

select * from sys.sql_modules 

當程序被保存,這些屬性都設置爲無論他們是通過它的程序被保存在連接檢查這些設置。這可能導致令人不愉快的不一致,所以要謹慎。

至於BEGIN/END,就像@ bobs所說的 - 它們表示代碼塊,它們不表示存儲過程代碼的開始和結束。 (函數,是的,程序號)正如你所說,no BEGIN/END and a GO at the end would make the most sense是我多年來一直這樣做的方式。

從技術上講,SQL將(嘗試)將所有文件保存爲批處理作爲存儲過程的一部分 - 也就是您提交的所有文本,如GO語句(如果有)分解。如果您在臨時查詢之前插入了RETURN語句,它們將包含在代碼中,但從不運行。

+0

對於'sys.sql_modules'爲+1,並且該函數DO使用'BEGIN/END'。最後只有'GO'的問題是它不是由修改選項生成的,所以下次它不在那裏。但至少「BEGIN/END」也不存在。 – 2010-11-15 21:39:16

5

BEGIN...END定義了一段代碼。它沒有定義腳本或過程的開始和結束。但是,我同意這可能會讓人困惑。

SET QUOTED_IDENTIFIER和SET ANSI_NULLS設置已保存,但未保存其他設置。查看互操作性here瞭解更多信息。

+0

這回答我的第一個問題,謝謝:'數據庫引擎在創建或修改Transact-SQL過程時保存SET QUOTED_IDENTIFIER和SET ANSI_NULLS的設置...其他SET選項,例如SET ARITHABORT,SET ANSI_WARNINGS,或SET ANSI_PADDINGS不會在創建或修改過程時保存。如果過程的邏輯取決於特定的設置,請在過程的開始部分包含一條SET語句以保證適當的設置。# – 2010-11-15 20:47:28

1

包含一系列的Transact-SQL語句 從而可以 執行一組 Transact-SQL語句的。 BEGINEND是 控制流語言關鍵字。

SET ANSI_NULLSON,使用WHERE欄處SELECT聲明= NULL返回零,即使有在列名空值的行。 A SELECT語句使用WHERE column_name <>NULL即使在column_name中存在非空值時也會返回零行。

SET ANSI_NULLS爲OFF時,等於(=)和不等於(<>)的比較運算符不符合ISO標準。使用WHERE column_name = NULL的SELECT語句返回column_name中具有空值的行。 A SELECT使用WHERE列名的語句<>NULL返回列中具有非空值的行。此外,使用WHERE column_name <> XYZ_value的SELECT語句將返回非XYZ_value且不是NULL的所有行。

SET ANSI_NULLSON時,所有針對空值的比較都評估爲UNKNOWN。當SET ANSI_NULLSOFF時,如果數據值爲NULL,則所有數據與空值的比較計算結果爲TRUE。如果未指定SET ANSI_NULLS,則應用當前數據庫的ANSI_NULLS選項的設置。有關ANSI_NULLS數據庫選項的更多信息,請參閱ALTER DATABASE(Transact-SQL)和設置數據庫選項。

SET ANSI_NULLS ON僅當比較操作數中的一個是變量NULL或文字NULL時纔會影響比較。如果比較的兩邊都是列或複合表達式,則該設置不影響比較。

對於按預期的腳本工作,無論ANSI_NULLS數據庫選項或SET ANSI_NULLS的設置,使用中可能包含空值的比較NULLIS NOT NULL

SET ANSI_NULLS應設置爲ON以執行分佈式查詢。

當您在計算列或索引視圖上創建或更改索引時,SET ANSI_NULLS也必須爲ON。如果SET ANSI_NULLSOFF,則在有計算列或索引視圖索引的表上的任何CREATE,UPDATEINSERTDELETE語句將失敗。 SQL Server將返回一個列出所有違反所需值的SET選項的錯誤。此外,當您執行SELECT語句時,如果SET ANSI_NULLSOFF,SQL Server將忽略計算列或視圖上的索引值,並解析選擇操作,就好像表或視圖上沒有這樣的索引一樣。

+0

ANSI_NULLS的良好信息,但與問題無直接關係。我不知道最後一段的規則,學習更多東西總是很好。 – 2010-11-15 21:43:05