存儲過程
存儲過程概念
(百度百科)
存儲過程(Stored Procedure)是在大型數據庫系統中,一組爲了完成特定功能的SQL 語句集,它存儲在數據庫中,一次編譯後永久有效,用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。存儲過程是數據庫中的一個重要對象。在數據量特別龐大的情況下利用存儲過程能達到倍速的效率提升。
存儲過程的作用
不使用存儲過程時,所有的數據處理都在客戶端完成;而使用存儲過程時,可以使數據處理在服務器端完成。
可以避免在網絡上傳輸大量無用的信息或原始數據,只需要傳輸調用存儲過程的指令和數據庫服務器返回的處理結果。
把完成某一數據庫處理的功能設計爲存儲過程,則可以在各個程序中反覆調用,從而減輕程序的編寫工作量。
也可以利用存儲程序間接實現一些安全控制功能。
創建和執行存儲過程
創建存儲過程的基本格式:
說明:
創建存儲過程通常是在數據庫設計和開發階段完成的。
存儲過程可以嵌套,即在一個存儲過程中可以調用另外一個存儲過程。
存儲過程一般用來完成數據查詢和數據處理操作;
在存儲過程中不可以使用創建數據庫對象的語句(如create table等各種create語句)。
執行存儲過程的格式:
修改存儲過程:
刪除存儲過程:
應用舉例
--例1:使用簡單過程。
--下面的存儲過程將從表中返回所有職工信息(姓名、倉庫號、工資、所在城市)。這個存儲過程不使用任何參數。
CREATE PROCEDURE uspGetAllEmp -- CREATE PROC uspGetAllEmp
AS
SELECT 姓名,倉庫.倉庫號,工資,城市 AS 所在城市
FROM 倉儲.倉庫 JOIN 基礎.職工 ON 倉庫.倉庫號=職工.倉庫號
--例2:使用帶有參數的簡單過程。
--下面的存儲過程只從表中返回指定城市的職工信息。該存儲過程需要提供精確匹配的參數值。
CREATE PROCEDURE uspGetEmp1
@city char(10)
AS
SELECT *
FROM 基礎.職工
WHERE 倉庫號 IN
(SELECT 倉庫號
FROM 倉儲.倉庫
WHERE 城市=@city)
--爲了得到“北京”的職工信息,可通過以下方式執行存儲過程uspGetEmp1:
EXECUTE uspGetEmp1 @city='北京'
EXECUTE uspGetEmp1 '北京'
--例3:使用帶有參數和返回值的簡單過程。
--下面的存儲過程查詢指定倉庫訂單金額大於指定值的訂單數,查詢結果通過RETURN語句返回:
CREATE PROCEDURE uspGetOrderNum
@whno char(6)='wh1',@sum money --默認值爲'wh1'
AS
DECLARE @count int
SELECT @count=COUNT(*)
FROM 訂貨.訂購單
WHERE 金額>=@sum AND 經手人 IN
(SELECT 職工號
FROM 基礎.職工
WHERE 倉庫號=@whno)
RETURN @count
--下面的語句調用存儲過程uspGetOrderNum查詢WH1倉庫金額大於1000的訂單數:
DECLARE @count int
EXECUTE @count= uspGetOrderNum 'WH1',1000
PRINT 'WH1倉庫金額在1000以上的訂單數是:'+STR(@count)
DECLARE @count int
EXECUTE @count= uspGetOrderNum @sum=1000,@whno='WH1'
PRINT 'WH1倉庫金額在1000以上的訂單數是:'+STR(@count)
--例4:使用帶有通配符參數的簡單過程。
--下面的uspGetSup存儲過程用於只從表中返回指定的一些供應商的信息(提供供應商名稱中的關鍵字)。此存儲過程通過參數的模式匹配完成查詢,如果未提供參數,則返回全部供應商信息。
CREATE PROCEDURE 訂貨.uspGetSup
@sname varchar(20)='%'
AS
SELECT * FROM 訂貨.供應商
WHERE 供應商名 LIKE @sname
--以下執行存儲過程的命令將返回供應商名稱中含有“北京”的供應商信息:
EXECUTE 訂貨.uspGetSup @sname='%北京%'
--以下執行存儲過程的命令將返回全部的供應商信息(沒有提供參數):
EXECUTE 訂貨.uspGetSup
--例5. 使用 OUTPUT 參數
--指定供應商所經手訂購單的數量和平均金額,一個參數傳入指定供應商名,一個參數傳出計算的平均金額,計算的訂單數量用RETURN語句返回
--drop proc uspGetAvg
create proc uspGetAvg
@sname char(20),@avg money output
as
declare @count int
select @count=count(*),@avg=avg(金額)
from 訂貨.訂購單
where 供貨方=
(select 供應商號
from 訂貨.供應商
where 供應商名=@sname)
return @count
--調用
declare @avgout money ,@countout int
exec @countout=uspGetAvg @sname='華通電子公司',@avg=@avgout output
print '華通電子公司的訂單數是:'+str(@countout)+',平均金額是:'+str(@avgout,6,2)
--1個輸入參數,2個輸出參數
create proc uspGetAvg2
@sname char(20),
@avg money output,
@count int output
as
select @count=count(*),@avg=avg(金額)
from 訂貨.訂購單
where 供貨方=
(select 供應商號
from 訂貨.供應商
where 供應商名=@sname)
declare @avgout money ,@countout int
exec uspGetAvg2 @sname='華通電子公司',@avg=@avgout output,@count=@countout output
print '華通電子公司的訂單數是:'+str(@countout)+',平均金額是:'+str(@avgout,6,2)
觸發器
觸發器的概念和用途
觸發器可以看作是一類特殊的存儲過程,它在滿足某個特定條件時自動觸發執行。觸發器和存儲過程同是提高數據庫服務器性能的有力工具。
觸發器是一種程序或是一種過程,它和存儲過程一樣是事先設計好存儲在數據庫中的,與存儲過程不同的是觸發器不需要專門調用或執行,觸發器是在某個特定條件發生時自動觸發執行的。
分爲DML(數據操作語言)觸發器、DDL(數據定義語言)觸發器和LOGIN觸發器
DML觸發器在執行數據操作語言(update、insert和delete)時觸發;
DDL觸發器在執行數據定義語言時觸發;
LOGIN觸發器在有用戶登錄時觸發。
DML觸發器也是一個數據庫對象,但DML觸發器依附於表(或視圖)。
DML觸發器分爲插入觸發器、刪除觸發器和更新觸發器三類
觸發器的三個要素:
定義觸發器的表(或視圖)
激活觸發器的數據操作語句
採取的動作
建立和刪除觸發器
建立:
刪除:
比較for觸發器和instead of觸發器的區別
--instead of不能插入表中
create trigger wh_trigger1
on 倉儲.倉庫
instead of insert
as
print 'instead of 觸發器'
--使用觸發器
insert into 倉儲.倉庫 values('WH8','杭州',450)
drop trigger wh_trigger1
--for可以把數據插入表中
create trigger wh_trigger1
on 倉儲.倉庫
for insert
as
print 'instead of 觸發器'
deleted表和inserted表
當DML觸發器激活時系統會自動產生兩個特殊的臨時表:deleted表和inserted表
當發生insert操作時新插入的記錄也存儲在inserted表
當發生deleted操作時被刪除的記錄也存儲在deleted表
當發生update操作時修改前的舊記錄也存儲在deleted表、修改後的新紀錄也存儲在inserted表
可以使用deleted表和inserted表判斷正在操作的記錄是否符合要求,從而檢查錯誤並採取相應的措施。
可以擴展表之間的參照完整性。
deleted表和inserted表只在觸發器內可用,一旦觸發器完成任務,這兩個系統產生的臨時表將自動刪除。
觸發器應用舉例
CREATE TRIGGER reminder1
ON 倉儲.庫存
FOR UPDATE
AS
DECLARE @amount int
SELECT @amount=數量 FROM inserted
IF @amount<5
RAISERROR ('庫存數量小於5',16,10)
UPDATE 倉儲.庫存 SET 數量=數量-3
where 倉庫號='WH1' AND 器件號='P3'