存儲(chǔ)過(guò)程是一組預(yù)先編譯好的sql語(yǔ)句。將他放在服務(wù)器上面,由用戶通過(guò)指定存儲(chǔ)過(guò)程的名字來(lái)執(zhí)行它。
存儲(chǔ)過(guò)程的優(yōu)點(diǎn):
封裝——可用于操作數(shù)據(jù)庫(kù)對(duì)象的方法,用戶只需要知道它的輸入輸出參數(shù)并理解其目的即可。
改善性能——已經(jīng)預(yù)先編譯
減少網(wǎng)絡(luò)流量——只返回最后的結(jié)果集
重要性——針對(duì)復(fù)雜邏輯,應(yīng)用已經(jīng)測(cè)試號(hào)的存儲(chǔ)過(guò)程,不容易發(fā)生錯(cuò)誤。
安全性——如果數(shù)據(jù)庫(kù)擁有者DBO或者系統(tǒng)管理員SA編譯并保存了存儲(chǔ)結(jié)構(gòu),存儲(chǔ)過(guò)程就有了對(duì)它使用的數(shù)據(jù)庫(kù)對(duì)象的所有訪問(wèn)權(quán)限。因此系統(tǒng)管理員可以向單獨(dú)的用于授予對(duì)數(shù)據(jù)對(duì)象的最小訪問(wèn)權(quán)限,而不是直接允許用戶使用數(shù)據(jù)庫(kù)對(duì)象。
這次項(xiàng)目開發(fā)中運(yùn)用了不少的存儲(chǔ)過(guò)程,中間遇到了一個(gè)小問(wèn)題,大家可以看看:
事情是這樣的:我想根據(jù)卡號(hào)、教師編號(hào)、教師姓名、聯(lián)系電話這四個(gè)條件查詢教師編號(hào),這四個(gè)條件可以不存在,可以只存在一個(gè),可以只存在兩個(gè),可以只存在三個(gè),可以存在四個(gè)。開始我寫的存儲(chǔ)過(guò)程是這樣的
- <span style="font-size:24px;">CREATE PROCEDURE [dbo].[procCardByMore]</span>
- @cardNo varchar (50),
- @TeacherID varchar(50),
- @Name varchar(50),
- @telephone varchar(50)
- AS
- DECLARE @sql varchar(1000)
- SET @sql='SELECT TeacherID as 教師編號(hào),Name as 教師姓名,GradeName as 所屬年級(jí),cardNo as 卡號(hào),cash as 卡內(nèi)余額,realName as 管理員,OpenTime as 開卡時(shí)間,state as 狀態(tài),telephone as 聯(lián)系電話 FROM view_CardDetail '
-
- IF(@cardNo <>'')
- BEGIN
- SET @sql=@sql+'and cardNo ='''+@cardNo+''''
- END
-
- IF(@TeacherID <>'')
- BEGIN
- SET @sql=@sql+'and TeacherID ='''+@TeacherID+''''
- END
-
- IF(@Name <>'')
- BEGIN
- SET @sql=@sql+'and Name ='''+@Name +''''
- END
-
- IF(@Name <>'')
- BEGIN
- SET @sql=@sql+'and telephone ='''+@telephone +''''
- END
-
- exec(@sql)
這里面假如卡號(hào)不為空的話,那么寫出來(lái)的sql語(yǔ)句是這樣的:
- SELECT TeacherID as 教師編號(hào),Name as 教師姓名,GradeName as 所屬年級(jí),cardNo as 卡號(hào),cash as 卡內(nèi)余額,realName as 管理員,OpenTime as 開卡時(shí)間,state as 狀態(tài),telephone as 聯(lián)系電話FROM view_CardDetail and cardNo ='@cardNo’
這句話顯然是錯(cuò)誤的,在查詢語(yǔ)句和條件的過(guò)渡的地方?jīng)]有where,而是突然來(lái)了個(gè)and。然而這個(gè)時(shí)候如果加上個(gè)必然條件那就完美了,接下來(lái)的存儲(chǔ)過(guò)程創(chuàng)建語(yǔ)句是這樣的:
- CREATE PROCEDURE [dbo].[procCardByMore]
- @cardNo varchar (50),
- @TeacherID varchar(50),
- @Name varchar(50),
- @telephone varchar(50)
- AS
- DECLARE @sql varchar(1000)
- SET @sql='SELECT TeacherID as 教師編號(hào),Name as 教師姓名,GradeName as 所屬年級(jí),cardNo as 卡號(hào),cash as 卡內(nèi)余額,realName as 管理員,OpenTime as 開卡時(shí)間,state as 狀態(tài),telephone as 聯(lián)系電話FROM view_CardDetail WHERE 1=1 '
-
- IF(@cardNo <>'')
- BEGIN
- SET @sql=@sql+'and cardNo ='''+@cardNo+''''
- END
-
- IF(@TeacherID <>'')
- BEGIN
- SET @sql=@sql+'and TeacherID ='''+@TeacherID+''''
- END
-
- IF(@Name <>'')
- BEGIN
- SET @sql=@sql+'and Name ='''+@Name +''''
- END
-
- IF(@Name <>'')
- BEGIN
- SET @sql=@sql+'and telephone ='''+@telephone +''''
- END
-
- exec(@sql)
這樣的話執(zhí)行出來(lái)的結(jié)果是這樣的:
- SELECT TeacherID as 教師編號(hào),Nameas 教師姓名,GradeName as 所屬年級(jí),cardNo as 卡號(hào),cashas 卡內(nèi)余額,realName as 管理員,OpenTime as 開卡時(shí)間,stateas 狀態(tài),telephone as 聯(lián)系電話FROM view_CardDetail WHERE 1=1and cardNo ='+@cardNo+'
必然條件在這里充當(dāng)了橋梁的作用,雖然我們沒(méi)有“1=1“的需求,但是它的存在卻恰好解決了兩者互不相容的尷尬局面。
受上面的啟發(fā),下面的情況是這樣解決的:
需要根據(jù)教師編號(hào)和起始日期查詢教師的消費(fèi)記錄情況,兩個(gè)條件的存在情況各自隨便。
存儲(chǔ)過(guò)程代碼如下:
- CREATE PROCEDURE [dbo].[procConsumeByMore]
- @TeacherID varchar(50),
- @TimeStart datetime,
- @TimeEnd datetime
- AS
- DECLARE @sql varchar(1000)
- SET @sql='SELECT TeacherID as 教師編號(hào),Name as 教師姓名,orderID as 訂單編號(hào),adultNum as 成人數(shù)量,childNum as 兒童數(shù)量,consumeCash as 消費(fèi)金額,consumeTime as 消費(fèi)時(shí)間,userID as 管理員編號(hào),realName as 管理員姓名FROM view_consumeDetail WHERE 1=1 '
-
-
- IF(@TeacherID <>'')
- BEGIN
- SET @sql=@sql+'and TeacherID ='''+@TeacherID+''''
- END
-
- IF( @TimeStart<>null and @TimeEnd<>null)
- BEGIN
- SET @sql=@sql+'and consumeTime between '''+@TimeStart +''' and '''+@TimeEnd+''''
- END
-
- exec(@sql)
這里當(dāng)@TimeStart和@TimeEnd為空的時(shí)候,空字符串不能轉(zhuǎn)換成日期類型,這時(shí)候假如兩個(gè)變量為空,我可以給他們賦一個(gè)完全的值:
- exec procConsumeByMore '', '1799-01-01','9999-12-29'
如上面的代碼就可以選擇出所有的消費(fèi)記錄了。
上面兩件事情中必然事件這個(gè)配角起了不可忽視的作用,然而必然事件卻不是我們?cè)诓樵冞^(guò)程中需要的條件。
生活中配角并不意味著無(wú)趣和呆板,配角一樣可以靈動(dòng),只是它把對(duì)別人的善意放在第一位,不把張揚(yáng)作為表達(dá)自己的方式。‘上善若水,水善利萬(wàn)物而不爭(zhēng)’,但是水又無(wú)處不在,其實(shí)就是這樣一種狀態(tài)。創(chuàng)造一個(gè)最好的配角,并不比創(chuàng)造一個(gè)主角容易。