存儲過程即為能完成特定功能的一組SQL語句集。如果需要對查出的多條數據進行操作的話,這里需要理解游標(CURSOR)的概念,對於oracle有for each row命令,可以不用游標。
游標可以理解為一個結果集,描述cursor的關鍵字有:
SCROLL關鍵字指明游標可以在任意方向上滾動
FORWARD_ONLY指明游標只能向前滾動。
READ ONLY指明在游標結果集中不允許進行數據修改。
UPDATE關鍵字指明游標的結果集可以修改。
GLOBAL關鍵字使得游標對於整個連接全局可見
LOCAL關鍵字指明游標是局部的,它只能在它所聲明的過程中使用。
等等。。。
一般結果集需要遍歷,如例,將一些表中的字段查出來,插入到另外一張表中:
例1:查詢表數據插入到另外一張表
CREATE PROCEDURE sp_insertIntoTest_hibernate AS DECLARE @projectid VARCHAR(20) DECLARE @projectcode VARCHAR(20) DECLARE @projectname VARCHAR(100) DECLARE @projectamount DECIMAL(16,2) DECLARE @remark VARCHAR(1000) DECLARE cs CURSOR FOR --定義游標的數據集 SELECT L.PROJECTID,P.CODE,L.PROJECTNAME,L.LEASINGAMOUNT, L.proInfoSummary FROM LAPROJECT L LEFT JOIN PARTY_CUSTOMER P ON P.ID=L.TENANTID WHERE (L.TENANTID<>'' AND L.TENANTID IS NOT NULL) ORDER BY L.PROJECTID BEGIN DELETE FROM test_hibernate OPEN cs --打開游標 FETCH NEXT FROM cs INTO @projectid,@projectcode,@projectname,@projectamount,@remark --從游標中取值賦給變量 WHILE @@FETCH_STATUS = 0 --fetch語句執行成功返回0,fetch語句執行失敗或者此行不在結果集中返回-1,被提取的行不存在則返回-2. BEGIN PRINT '====start insert====' INSERT INTO test_hibernate VALUES(@projectid,@projectcode,@projectname,@projectamount,@remark) PRINT '==== end insert====' FETCH NEXT FROM cs INTO @projectid,@projectcode,@projectname,@projectamount,@remark --繼續取下一行數據 END CLOSE cs --關閉游標 DEALLOCATE cs --刪除游標 END
這個sp起初運行的時候老是報游標已存在問題,時不時還報游標不存在,郁悶。后來修改了下存儲過程換了個游標名稱就好了,網上查了很多說是游標沒關閉沒釋放或者是關閉釋放位置不對等問題,自己實踐證明我的問題不是這樣的,至今搞不懂是啥原因造成的問題,可能是第一次寫sp的時候沒釋放,后面加上了釋放和刪除那兩句話吧。
例2:分頁查詢
CREATE PROCEDURE sp_getpermbal @pageSize INT, @page INT AS DECLARE @temp INT SET @temp=@pageSize*(@page-1) BEGIN SELECT TOP (SELECT @pageSize) * FROM LAPERMBAL WHERE projectid+contractid+grantid+convert(varchar(20),retsn)+convert(varchar(10),ratebtdt,120) NOT IN (SELECT TOP (SELECT @temp) projectid+contractid+grantid+convert(varchar(20),retsn)+convert(varchar(10),ratebtdt,120) FROM LAPERMBAL ORDER BY projectid,contractid,grantid,retsn,ratebtdt DESC) ORDER BY projectid,contractid,grantid,retsn,ratebtdt DESC END
這個查數據需要用到主鍵,而本例的表使用聯合主鍵,所以進行拼接來識別一條數據的唯一性。
二、觸發器(SQLServer)
觸發器都說是一種特殊的存儲過程,那我也就這么理解了,還挺有道理的、讓人比較容易接受的解釋。在數據庫的表數據有增、刪、改的操作時可自動觸發的存儲過程。
首先理解inserted和deleted兩張虛表,看了下oracle相關的內容,應該是用new和old兩張虛表,取值可用new.字段名,old.字段名。
新增操作新增的記錄存到系統建的虛表inserted中,deleted表無記錄;
刪除操作刪除的記錄存到系統建的虛表deleted中,inserted表無記錄;
修改操作(分解為先刪除再插入)刪除的記錄存到系統建的虛表deleted中,新增的記錄存到inserted表中。
然后就是觸發器類型,after觸發器和instead of 觸發器,這個不理解的可以百度,有很多比我解釋的更清楚的大神寫的文章。
理解完之后,記錄下相關語法:
新建觸發器:
例:更新test_hibernate表,則將被更新記錄的字段值置為“test success---”
CREATE TRIGGER test_trigger ON test_hibernate FOR UPDATE AS DECLARE @projectid VARCHAR(20),@projectcode VARCHAR(20) DECLARE cs CURSOR local FOR SELECT projectid,projectcode FROM deleted BEGIN OPEN cs FETCH NEXT FROM cs INTO @projectid,@projectcode WHILE @@FETCH_STATUS=0 BEGIN UPDATE test_hibernate SET remark='test success---' WHERE projectid=@projectid AND projectcode=@projectcode FETCH NEXT FROM cs INTO @projectid,@projectcode END CLOSE cs DEALLOCATE cs END GO
修改觸發器:
ALTER TRIGGER test_trigger ON test_hibernate FOR UPDATE AS
......
禁用、啟用觸發器:
ALTER TABLE test_hibernate DISABLE TRIGGER test_trigger ALTER TABLE test_hibernate ENABLE TRIGGER test_trigger ALTER TABLE test_hibernate DISABLE TRIGGER ALL ALTER TABLE test_hibernate ENABLE TRIGGER ALL
關於觸發器的內容,可以參考這位大哥的http://www.cnblogs.com/hoojo/archive/2011/07/20/2111316.html,個人覺得寫得簡單易懂。