SQLServer存儲過程和觸發器學習記錄及簡單例子


 一、存儲過程

  存儲過程即為能完成特定功能的一組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,個人覺得寫得簡單易懂。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM