一.腳本基礎(chǔ)
1.USE語句
設(shè)置當(dāng)前數(shù)據(jù)庫。
2.聲明變量
語法:DECLARE @變量名 變量類型
在聲明變量后,給變量賦值之前,變量的值為NULL。
將系統(tǒng)函數(shù)賦給聲明的變量,這個(gè)方法可以使我們能更安全地使用值,該值只有人為地改變時(shí)它才變動(dòng)。如果直接使用系統(tǒng)函數(shù)本身,那么當(dāng)它發(fā)生變動(dòng)時(shí),有
時(shí)會(huì)無法確定其究竟為何,因?yàn)榇蠖鄶?shù)系統(tǒng)函數(shù)值是由系統(tǒng)確定的。這容易在你不預(yù)期的情況下導(dǎo)致系統(tǒng)改變了值,引起不可預(yù)期的后果。
(1).給變量賦值
SET:當(dāng)進(jìn)行變量賦值是,該值已經(jīng)知道是確切值或者是其他變量時(shí),使用SET。
SELECT:當(dāng)變量賦值基于一個(gè)查詢時(shí),使用SELECT。
(2).系統(tǒng)函數(shù)
SQL Server 2005中有30多個(gè)無參的系統(tǒng)函數(shù),其中一些最重要的如下:
@@ERROR: 返回當(dāng)前連接下,最后執(zhí)行的T-SQL語句的錯(cuò)誤代碼,如無錯(cuò)誤返回0。
@@FETCH_STATUS: 和FETCH語句配合使用。
@@IDENTITY: 返回最后一句運(yùn)行語句的、自動(dòng)生成的標(biāo)識值,作為最后INSERT或者SELECT INTO語句的結(jié)果。
@@ROWCOUNT: 返回最后一個(gè)語句影響的行數(shù)。
@@SERVERNAME: 返回腳本正在其上運(yùn)行的本地服務(wù)的名字。
@@TRANCOUNT: 返回活動(dòng)事務(wù)的數(shù)量,特別是針對當(dāng)前連接的事務(wù)的瓶頸程度。
二.批處理
(1).GO單獨(dú)占一行。在同一行上,T-SQL語句不能在GO語句之前。
(2).所有語句從腳本開始處或者上一個(gè)GO語句開始編譯,直到下一個(gè)GO語句或者腳本結(jié)束,將這段代碼編譯到一個(gè)執(zhí)行計(jì)劃中并相互獨(dú)立地送往服務(wù)器。前一
個(gè)執(zhí)行計(jì)劃中發(fā)生錯(cuò)誤,不會(huì)影響后一個(gè)執(zhí)行計(jì)劃。
(3).GO不是一個(gè)T-SQL命令,只是被編輯工具識別的命令。當(dāng)編輯工具碰到GO,它把GO看做一個(gè)結(jié)束批處理的標(biāo)記,將其打包,然后作為一個(gè)獨(dú)立單元發(fā)送到
服務(wù)器——不包括GO,服務(wù)器對于GO沒有任何概念。
1.批處理中的錯(cuò)誤
語法錯(cuò)誤,運(yùn)行時(shí)錯(cuò)誤。
2.何時(shí)使用批處理
(1).獨(dú)自成批處理的語句
有幾個(gè)命令必須獨(dú)自成批處理,它們包括:
CREATE DEFAULT
CREATE PROCEDURE
CREATE RULE
CREATE TRIGGER
CREATE VIEW
如果想將這些語句中的任何一條和其他語句組成單獨(dú)的一個(gè)腳本,那么需要采用一個(gè)GO語句將它們分別斷開,歸入各自的批處理中。
(2).使用批處理建立優(yōu)先級
使用批處理最可靠的例子是,當(dāng)需要考慮語句執(zhí)行的優(yōu)先順序時(shí),也就是說,需要一個(gè)任務(wù)在另一個(gè)任務(wù)開始前執(zhí)行。
例如:
CREATE DATABASE Test
復(fù)制代碼 代碼如下:
CREATE TABLE TestTable
(
col1 INT,
col2 INT
)
執(zhí)行語句,會(huì)發(fā)現(xiàn)生成的表沒有在Test數(shù)據(jù)庫中,而是在master數(shù)據(jù)庫中(如果當(dāng)前使用的數(shù)據(jù)庫是系統(tǒng)數(shù)據(jù)庫)。因?yàn)樵趫?zhí)行腳本的時(shí)候,使用的數(shù)據(jù)
庫是系統(tǒng)數(shù)據(jù)庫,該數(shù)據(jù)庫是當(dāng)前的,所以生成的表在系統(tǒng)數(shù)據(jù)庫中??雌饋?,應(yīng)該在創(chuàng)建表之前指定數(shù)據(jù)庫Test。然而,這樣仍然存在問題。解析器試圖校
驗(yàn)代碼,發(fā)現(xiàn)我們用USE命令引用的數(shù)據(jù)庫并不存在。原因在于創(chuàng)建數(shù)據(jù)庫的語句和創(chuàng)建表的語句寫在一個(gè)批處理中,在執(zhí)行該腳本之前,當(dāng)然數(shù)據(jù)庫還沒有
創(chuàng)建。根據(jù)批處理的要求,我們將創(chuàng)建數(shù)據(jù)庫和創(chuàng)建表的腳本用GO語句分為兩個(gè)獨(dú)立的批處理。正確代碼如下:
復(fù)制代碼 代碼如下:
CREATE DATABASE Test
GO
USE Test
CREATE TABLE TestTable
(
col1 INT,
col2 INT
)
三.動(dòng)態(tài)SQL:使用EXE命令生成代碼
語法:EXEC/EXECUTE ({字符串變量> | '字面值命令字符串>'})
1.EXEC的作用域
真正的調(diào)用EXEC語句的行,擁有同該EXEC語句正在運(yùn)行的批或過程中的其他代碼相同的作用域。但是作為EXEC語句結(jié)果而被執(zhí)行的代碼,被認(rèn)為是在它自
己的批中。
例如:
DECLARE @OutVar VARCHAR(50)
EXEC ('SELECT @OutVar = FirstName FROM Contact WHERE ContactID = 1')
這里系統(tǒng)會(huì)報(bào)錯(cuò),指出必須聲明變量@OutVar。因?yàn)镋XEC的語句獨(dú)自成為一個(gè)批處理,其中的變量不能和其外的作用域相溝通,只在這個(gè)批處理中有效。此
時(shí),@OutVar的值為NULL。正確的寫法如下:
EXEC ('DECLARE @OutVar VARCHAR(50)
SELECT @OutVar = FirstName FROM Contact WHERE ContactID = 1')
這里,我們看到兩中不同的作用域,這兩種作用域間不能相互溝通。如果不采用外部機(jī)制,比如一個(gè)臨時(shí)表,我們就沒有辦法實(shí)現(xiàn)在內(nèi)部作用域和外部作用域
之間傳遞信息。有一個(gè)例外的事情是可以在EXEC的區(qū)域內(nèi)部出現(xiàn),并且也能在EXEC執(zhí)行后被看到,這就是系統(tǒng)函數(shù)。因此,像@@ROWCOUNT這樣的變量仍然
能夠被使用。
2.安全上下文和EXEC
當(dāng)賦予某人權(quán)利運(yùn)行一個(gè)存儲(chǔ)過程,意味著他也能獲得權(quán)利去執(zhí)行存儲(chǔ)過程內(nèi)部的動(dòng)作。比如,有一個(gè)存儲(chǔ)過程用來列出去年內(nèi)所有的雇傭員工。其中有權(quán)限
執(zhí)行該存儲(chǔ)過程的人,才能夠執(zhí)行并返回結(jié)果——即使他沒有權(quán)限直接訪問人力資源的員工表。
這樣隱含權(quán)限對于EXEC語句是無效的。在默認(rèn)情況下,任何在一個(gè)EXEC語句內(nèi)部建立的參照,都將在當(dāng)前用戶的安全上下文中運(yùn)行。因此,我們有權(quán)利去訪
問一個(gè)叫spNewEmployee的存儲(chǔ)過程,但是卻沒有權(quán)利去訪問員工表。如果spNewEmployee通過一個(gè)簡單的SELECT語句獲得值,那么一切正常。但是如果
pNewEmployee使用EXEC語句去執(zhí)行一個(gè)SELECT語句,這個(gè)EXEC語句將失敗——因?yàn)闆]有權(quán)利訪問員工表。
3.用戶自定義函數(shù)和EXEC關(guān)聯(lián)
不能在同一個(gè)語句中同時(shí)運(yùn)行一個(gè)函數(shù)和EXEC語句。例如:
DECLARE @Num INT
SET @Num = 3
EXEC ('SELECT LEFT(LastName, ' + CAST(@Num AS VARCHAR) + ') AS FilingName FROM Contact')
這個(gè)語句會(huì)返回一個(gè)錯(cuò)誤消息,因?yàn)镃AST函數(shù)需要在EXEC所在行之前被解析。正確代碼如下:
DECLARE @Num INT
DECLARE @str VARCHAR(255)
SET @Num = 3
SET @str = 'SELECT LEFT(LastName, ' + CAST(@Num AS VARCHAR) + ') AS FilingName FROM Contact'
EXEC (@str)
這個(gè)例子工作正常,因?yàn)镋XEC的輸入值已經(jīng)是一個(gè)完整的字符串。
4.EXEC和用戶自定義函數(shù)
一般來說,不允許用戶自定義函數(shù)內(nèi)部使用EXEC去運(yùn)行動(dòng)態(tài)SQL,但是,使用EXEC運(yùn)行一個(gè)存儲(chǔ)過程,少數(shù)情況是合法的。