存儲過程

存儲過程

完成特定功能的SQL語句集
計算機用語,是一組為了完成特定功能的SQL語句集,是利用SQL Server所提供的Transact-SQL語言所編寫的程序。經編譯後存儲在數據庫中。存儲過程是數據庫中的一個重要對象,用戶通過指定存儲過程的名字并給出參數(如果該存儲過程帶有參數)來執行它。存儲過程是由流控制和SQL語句書寫的過程,這個過程經編譯和優化後存儲在數據庫服務器中,存儲過程可由應用程序通過一個調用來執行,而且允許用戶聲明變量。同時,存儲過程可以接收和輸出參數、返回執行存儲過程的狀态值,也可以嵌套調用。[1]
    中文名:存儲過程 外文名: 别名: 英文名:Stored Procedure 類型:計算機操作的一種

簡介

sql語句執行的時候要先編譯,然後執行。存儲過程就是編譯好了的一些sql語句。用的時候直接就可以用了,所以效率會高。

基本信息

概述

在大型數據庫系統中,存儲過程和觸發器具有很重要的作用。無論是存儲過程還是觸發器,都是SQL 語句和流程控制語句的集合。就本質而言,觸發器也是一種存儲過程。存儲過程在運算時生成執行方式,所以,以後對其再運行時其執行速度很快。SQL Server 2005 不僅提供了用戶自定義存儲過程的功能,而且也提供了許多可作為工具使用的系統存儲過程。

格式

CREATE PROCEDURE [擁有者.]存儲過程名[;程序編号] sql中的存儲過程及相關介紹

[(參數#1,…參數#1024)]

[WITH{RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTION}]

[FOR REPLICATION]

AS 程序行

其中存儲過程名不能超過128個字。每個存儲過程中最多設定1024個參數

(SQL Server 7.0以上版本),參數的使用方法如下:

@參數名數據類型[VARYING] [=内定值] [OUTPUT]

每個參數名前要有一個“@”符号,每一個存儲過程的參數僅為該程序内部使用,參數的類型除了IMAGE外,其他SQL Server所支持的數據類型都可使用。

[=内定值]相當于我們在建立數據庫時設定一個字段的默認值,這裡是為這個參數設定默認值。[OUTPUT]是用來指定該參數是既有輸入又有輸出值的,也就是在調用了這個存儲過程時,如果所指定的參數值是我們需要輸入的參數,同時也需要在結果中輸出的,則該項必須為OUTPUT,而如果隻是做輸出參數用,可以用CURSOR,同時在使用該參數時,必須指定VARYING和OUTPUT這兩個語句。

例子:

CREATE PROCEDURE order_tot_amt

@o_id int,

@p_tot int output

AS

SELECT @p_tot = sum(Unitprice*Quantity)

FROM orderdetails

WHERE orderid = @o_id

GO

例子說明:

該例子是建立一個簡單的存儲過程order_tot_amt,這個存儲過程根據用戶輸入的定單ID号碼(@o_id),由訂單明細表 (orderdetails)中計算該定單銷售總額[單價(Unitprice)*數量(Quantity)],這一金額通過@p_tot這一參數輸出給調用這一存儲過程的程序。

功能

這類語言主要提供以下功能,讓用戶可以設計出符合引用需求的程序:

1)、變量說明

2)、ANSI(美國國家标準化組織)兼容的SQL命令(如Select,Update….)

3)、一般流程控制命令(if…else…、while….)

4)、内部函數

種類

1系統存儲過程

以sp_開頭,用來進行系統的各項設定.取得信息.相關管理工作。

2本地存儲過程

用戶創建的存儲過程是由用戶創建并完成某一特定功能的存儲過程,事實上一般所說的存儲過程就是指本地存儲過程。

3臨時存儲過程

分為兩種存儲過程:

一是本地臨時存儲過程,以井字号(#)作為其名稱的第一個字符,則該存儲過程将成為一個存放在tempdb數據庫中的本地臨時存儲過程,且隻有創建它的用戶才能執行它;

二是全局臨時存儲過程,以兩個井字号(##)号開始,則該存儲過程将成為一個存儲在tempdb數據庫中的全局臨時存儲過程,全局臨時存儲過程一旦創建,以後連接到服務器的任意用戶都可以執行它,而且不需要特定的權限。

4遠程存儲過程

在SQL Server2005中,遠程存儲過程(Remote Stored Procedures)是位于遠程服務器上的存儲過程,通常可以使用分布式查詢和EXECUTE命令執行一個遠程存儲過程。

5擴展存儲過程

擴展存儲過程(Extended Stored Procedures)是用戶可以使用外部程序語言編寫的存儲過程,而且擴展存儲過程的名稱通常以xp_開頭。

基本語法

創建存儲過程

create procedure sp_name

@[參數名] [類型],@[參數名] [類型]

as

begin

.........

end

以上格式還可以簡寫成:

create proc sp_name

@[參數名] [類型],@[參數名] [類型]

as

begin

.........

end

/*注:“sp_name”為需要創建的存儲過程的名字,該名字不可以以阿拉伯數字開頭*/

調用存儲過程

1.基本語法:exec sp_name [參數名]

删除存儲過程

1.基本語法:drop procedure sp_name

2.注意事項:不能在一個存儲過程中删除另一個存儲過程,隻能調用另一個存儲過程

其他常用命令

1.show procedure status

顯示數據庫中所有存儲的存儲過程基本信息,包括所屬數據庫,存儲過程名稱,創建時間等

2.show create procedure sp_name

顯示某一個mysql存儲過程的詳細信息

3、exec sp_helptext sp_name

顯示你這個sp_name這個對象創建文本

存儲過程的優點

存儲過程是由流控制和SQL語句書寫的過程,這個過程經編譯和優化後存儲在數據庫服務器中,使用時隻要調用即可。在ORACLE中,若幹個 有聯系的過程可以組合在一起構成程序包

使用存儲過程有以下的優點:

* 存儲過程的能力大大增強了SQL語言的功能和靈活性。存儲過程可以用流控制語句編寫,有很強的靈活性,可以完成複雜的判斷和較複雜的 運算。

 * 可保證數據的安全性和完整性。

 # 通過存儲過程可以使沒有權限的用戶在控制之下間接地存取數據庫,從而保證數據的安全。

# 通過存儲過程可以使相關的動作在一起發生,從而可以維護數據庫的完整性。

 * 再運行存儲過程前,數據庫已對其進行了語法和句法分析,并給出了優化執行方案。這種已經編譯好的過程可極大地改善SQL語句的性能。 由于執行SQL語句的大部分工作已經完成,所以存儲過程能以極快的速度執行。

* 可以降低網絡的通信量。

* 使體現企業規則的運算程序放入數據庫服務器中,以便:

 # 集中控制。

 # 當企業規則發生變化時在服務器中改變存儲過程即可,無須修改任何應用程序。企業規則的特點是要經常變化,如果把體現企業規則的運 算程序放入應用程序中,則當企業規則發生變化時,就需要修改應用程序工作量非常之大(修改、發行和安裝應用程序)。如果把體現企業規則的 運算放入存儲過程中,則當企業規則發生變化時,隻要修改存儲過程就可以了,應用程序無須任何變化。

存儲過程的建立

在SqlServer的企業管理器中建立存儲過程:

(1)打開企業管理器Enterprisemanager

(2)選擇服務器組(SQLServerGroup)、服務器、數據庫(Database)以及相就的數據庫,鼠标右擊對應數據庫下的StoredProcdures項,在彈出的菜單中選擇NewStoredProcedure,在StoredProceduresProperties中輸入建立存儲過程的語句。下面是一個例子:

Create PROCEDURE proctest

@mycola Char(10),

@mycolb Char(10),

@mycolc text  

AS

Insert into chatdata( mycola,mycolb,mycolc ) values ( @mycola,@mycolb,@mycolc )

在SqlServer的文檔中它的語法為:

Create PROC[EDURE] procedure_name [;number][{@parameterdata_type}[VARYING][=default][OUTPUT]] [,...n]

[WITH {RECOMPILE|ENCRYPTION|RECOMPILE,ENCRYPTION}] [FORREPLICATION]

AS

sql_statement[...n]

如果你對Sql語法不熟悉,可以使用CheckSyntax來檢查語法。在上例中,表示建立存儲過程名為mycola,帶3個參數的存儲過過程,其中第一個參數mycola數據類型為char,寬度10;第2個參數數據類型為char,寬度為10,第3個參數數據類型為text,在這裡使用的是SqlServer的數據類型。

觸發器

概念及作用

觸發器是一種特殊類型的存儲過程,它不同于我們前面介紹過的存儲過程。觸發器主要是通過事件進行觸發而被執行的,而存儲過程可以通過存儲過程名字而被直接調用。當對某一表進行諸如Update、 Insert、 Delete 這些操作時,SQL Server 就會自動執行觸發器所定義的SQL 語句,從而确保對數據的處理必須符合由這些SQL 語句所定義的規則。

觸發器的主要作用就是其能夠實現由主鍵和外鍵所不能保證的複雜的參照完整性和數據的一緻性。除此之外,觸發器還有其它許多不同的功能:

(1) 強化約束(Enforce restriction)。

觸發器能夠實現比CHECK 語句更為複雜的約束。

(2) 跟蹤變化Auditing changes。

觸發器可以偵測數據庫内的操作,從而不允許數據庫中未經許可的指定更新和變化。

(3) 級聯運行(Cascaded operation)。

觸發器可以偵測數據庫内的操作,并自動地級聯影響整個數據庫的各項内容。例如,某個表上的觸發器中包含有對另外一個表的數據操作(如删除,更新,插入)而該操作又導緻該表上觸發器被觸發。

(4) 存儲過程的調用(Stored procedure invocation)。

為了響應數據庫更新,觸發器可以調用一個或多個存儲過程,甚至可以通過外部過程的調用而在DBMS(數據庫管理系統)本身之外進行操作。

由此可見,觸發器可以解決高級形式的業務規則或複雜行為限制以及實現定制記錄等一些方面的問題。例如,觸發器能夠找出某一表在數據修改前後狀态發生的差異,并根據這種差異執行一定的處理。此外一個表的同一類型(Insert、 Update、 Delete)的多個觸發器能夠對同一種數據操作采取多種不同的處理。

總體而言,觸發器性能通常比較低。當運行觸發器時,系統處理的大部分時間花費在參照其它表的這一處理上,因為這些表既不在内存中也不在數據庫設備上,而删除表和插入表總是位于内存中。可見觸發器所參照的其它表的位置決定了操作要花費的時間長短。

觸發器種類

SQL Server 2000 支持兩種類型的觸發器:AFTER 觸發器和INSTEAD OF 觸發器。其中AFTER觸發器即為SQL Server 2000 版本以前所介紹的觸發器。該類型觸發器要求隻有執行某一操作(Insert Update Delete) 之後,觸發器才被觸發,且隻能在表上定義。可以為針對表的同一操作定義多個觸發器。對于AFTER觸發器,可以定義哪一個觸發器被最先觸發,哪一個被最後觸發,通常使用系統過程sp_settriggerorder 來完成此任務。

INSTEAD OF觸發器表示并不執行其所定義的操作(Insert、 Update、 Delete),而僅是執行觸發器本身。既可在表上定義INSTEAD OF觸發器,也可以在視圖上定義INSTEAD OF 觸發器,但對同一操作隻能定義一個INSTEAD OF 觸發器。

常用格式

Create procedure procedure_name

[@parameter data_type][output]

[with]{recompile|encryption}

as

sql_statement

解釋:

output:表示此參數是可傳回的

with {recompile|encryption}

recompile:表示每次執行此存儲過程時都重新編譯一次

encryption:所創建的存儲過程的内容會被加密

如:

表book的内容如下

編号 書名 價格

001 C語言入門 $30

002 PowerBuilder報表開發 $52

實例1:查詢表Book的内容的存儲過程

create proc query_book

as

select * from book

go

exec query_book

實例2:

加入一筆記錄到表book,并查詢此表中所有書籍的總金額

Create proc insert_book

@param1 char(10),@param2 varchar(20),@param3 money,@param4 money output

with encryption ---------加密

as

insert into book(編号,書名,價格) Values(@param1,@param2,@param3)

select @param4=sum(價格) from book

go

執行例子:

declare @total_price money

exec insert_book '003','Delphi 控件開發指南',$100,@total_price

print '總金額為'+convert(varchar,@total_price)

go

存儲過程的3種傳回值:

1)、以Return傳回整數

2)、以output格式傳回參數

3)、Recordset

傳回值的區别:

output和return都可在批次程式中用變量接收,而recordset則傳回到執行批次的客戶端中。

實例3:

設有兩個表為Product,Order_,其表内容如下:

Product

産品編号 産品名稱 客戶訂數

001 鋼筆 30

002 毛筆 50

003 鉛筆 100

Order_

産品編号 客戶名 客戶訂金

001 南山區 $30

002 羅湖區 $50

003 寶安區 $4

請實現按編号為連接條件,将兩個表連接成一個臨時表,該表隻含編号.産品名.客戶名.訂金.總金額,

總金額=訂金*訂數,臨時表放在存儲過程中

代碼如下:

Create proc temp_sale

as

select a.産品編号,a.産品名稱,b.客戶名,b.客戶訂金,a.客戶訂數* b.客戶訂金 as總金額

into #temptable from Product a inner join Order_ b on a.産品編号=b.産品編号-----此處要用别名

if @@error=0

print 'Good'

else

print 'Fail'

go

優缺點

優點

①重複使用。存儲過程可以重複使用,從而可以減少數據庫開發人員的工作量。

②提高性能。存儲過程在創建的時候在進行了編譯,将來使用的時候不再重新翻譯。一般的SQL語句每執行一次就需要編譯一次,所以使用存儲過程提高了效率。

③減少網絡流量。存儲過程位于服務器上,調用的時候隻需要傳遞存儲過程的名稱以及參數就可以了,因此降低了網絡傳輸的數據量。

④安全性。參數化的存儲過程可以防止SQL注入式攻擊,而且可以将Grant、Deny以及Revoke權限應用于存儲過程。

簡單講:

1.存儲過程隻在創造時進行編譯,以後每次執行存儲過程都不需再重新編譯,而一般SQL語句每執行一次就編譯一次,所以使用存儲過程可提高數據庫執行速度。

2.當對數據庫進行複雜操作時(如對多個表進行Update,Insert,Query,Delete時),可将此複雜操作用存儲過程封裝起來與數據庫提供的事務處理結合一起使用。

3.存儲過程可以重複使用,可減少數據庫開發人員的工作量

4.安全性高,可設定隻有某些用戶才具有對指定存儲過程的使用權

有一點需要注意的是,一些網上盛傳的所謂的存儲過程要比sql語句執行更快的說法,實際上是個誤解,并沒有根據,包括微軟内部的人也不認可這一點,所以不能作為正式的優點,希望大家能夠認識到這一點。

缺點

1:調試麻煩,但是用 PL/SQL Developer 調試很方便!彌補這個缺點。

2:移植問題,數據庫端代碼當然是與數據庫相關的。但是如果是做工程型項目,基本不存在移植問題。

3:重新編譯問題,因為後端代碼是運行前編譯的,如果帶有引用關系的對象發生改變時,受影響的存儲過程、包将需要重新編譯(不過也可以設置成運行時刻自動編譯)。

4: 如果在一個程序系統中大量的使用存儲過程,到程序交付使用的時候随着用戶需求的增加會導緻數據結構的變化,接着就是系統的相關問題了,最後如果用戶想維護該系統可以說是很難很難、而且代價是空前的,維護起來更麻煩。

實例

數據庫存儲過程

數據庫存儲過程的實質就是部署在數據庫端的一組定義代碼以及SQL。将常用的或很複雜的工作,預先用SQL語句寫好并用一個指定的名稱存儲起來,那麼以後要叫數據庫提供與已定義好的存儲過程的功能相同的服務時,隻需調用execute,即可自動完成命令。

利用SQL的語言可以編寫對于數據庫訪問的存儲過程,其語法如下:

CREATE PROC[EDURE] procedure_name [;number]

[{@parameter data_type} ][VARYING] [= default] [OUTPUT]]

[,...n]

[WITH{RECOMPILE| ENCRYPTION| RECOMPILE, ENCRYPTION}]

[FOR REPLICATION]

AS

sql_statement [...n]

[ ]内的内容是可選項,而()内的内容是必選項,

例:若用戶想建立一個删除表tmp中的記錄的存儲過程Select_delete可寫為:

Create Proc select_del As

Delete tmp

例:用戶想查詢tmp表中某年的數據的存儲過程

create proc select_query @year int as

select * from tmp where year=@year

在這裡@year是存儲過程的參數

例:該存儲過程是從某結點n開始找到最上層的父親結點,這種經常用到的過程可以由存儲過程來擔當,在網頁中重複使用達到共享。

空:表示該結點為頂層結點

fjdid(父結點編号)

結點n 非空:表示該結點的父親結點号

dwmc(單位名稱)

CREATE proc search_dwmc @dwidold int,@dwmcresult varchar(100) output

as

declare @stop int

declare @result varchar(80)

declare @dwmc varchar(80)

declare @dwid int

set nocount on

set @stop=1

set @dwmc=""

select @dwmc=dwmc,@dwid=convert(int,fjdid) from jtdw where id=@dwidold

set @result=rtrim(@dwmc)

if @dwid=0

set @stop=0

while (@stop=1) and (@dwid<>0)

begin

set @dwidold=@dwid

select @dwmc=dwmc,@dwid=convert(int,fjdid) from jtdw where id=@dwidold

if @@rowcount=0

set @dwmc=""

else

set @result=@dwmc+@result

if (@dwid=0) or (@@rowcount=0)

set @stop=0

else

continue

end

set @dwmcresult=rtrim(@result)

使用exec pro-name [pram1 pram2.....]、

SQLServer中存儲過程

sql語句執行的時候要先編譯,然後執行。存儲過程就是編譯好了的一些sql語句。用的時候直接就可以用了。

在SQL Server的查詢分析器中,輸入以下代碼:

declare @tot_amt int

execute order_tot_amt 1,@tot_amt output

select @tot_amt

以上代碼是執行order_tot_amt這一存儲過程,以計算出定單編号為1的定單銷售金額,我們定義@tot_amt為輸出參數,用來承接我們所要的結果。

Oracle中的存儲過程

1.創建過程

與其它的數據庫系統一樣,Oracle的存儲過程是用PL/SQL語言編寫的能完成一定處理功能的存儲在數據庫字典中的程序。

語法:

create [or replace] procedure procedure_name

[ (argment [ { in| in out }] type,

argment [ { in | out | in out } ] type

{ is | as }

<類型.變量的說明>

(注:不用 declare語句 )

Begin

<執行部分>

exception

<可選的異常處理說明>

end;

1.1 這裡的IN表示向存儲過程傳遞參數,OUT表示從存儲過程返回參數。而IN OUT 表示傳遞參數和返回參數;

1.2 在存儲過程内的參數隻能指定參數類型;不能指定長度;

1.3 在AS或IS 後聲明要用到的變量名稱和變量類型及長度;

1.4 在AS或IS 後聲明變量不要加declare 語句。

2.使用過程

存儲過程建立完成後,隻要通過授權,用戶就可以在SQLPLUS 、Oracle開發工具或第三方開發工具來調用運行。Oracle 使用EXECUTE 語句來實現對存儲過程的調用。

語法:

EXEC[UTE] procedure_name( parameter1, parameter2…);

3.開發過程

如今的幾大數據庫廠商提供的編寫存儲過程的工具都沒有統一,雖然它們的編寫風格有些相似,但由于沒有标準,所以各家的開發調試過程也不一樣。下面編寫PL/SQL存儲過程、函數、包及觸發器的步驟如下:

3.1 編輯存儲過程源碼使用文字編輯處理軟件編輯存儲過程源碼,要用類似WORD文字處理軟件進行編輯時,要将源碼存為文本格式。

3.2 對存儲過程程序進行解釋在SQLPLUS或用調試工具将 存儲過程程序進行解釋;

在SQL>下調試,可用start 或get 等Oracle命令來啟動解釋。如:

SQL>start c:stat1.sql

如果使用調試工具,可直接編輯和點擊相應的按鈕即可生成存儲過程。

3.3 調試源碼直到正确我們不能保證所寫的存儲過程達到一次就正确。所以這裡的調試是每個程序員必須進行的工作之一。在SQLPLUS下來調試主要用的方法是:

1.使用 SHOW ERROR命令來提示源碼的錯誤位置;

2.使用 USER_ERRORS數據字典來查看各存儲過程的錯誤位置。

3.4 授權執行權給相關的用戶或角色如果調試正确的存儲過程沒有進行授權,那就隻有建立者本人才可以運行。所以作為應用系統的一部分的存儲過程也必須進行授權才能達到要求。 在SQLPLUS下可以用GRANT命令來進行存儲過程的運行授權。

語法:

GRANT system_privilege | role TO user | role | PUBLIC

[WITH ADMIN OPTION]

GRANT object_privilege | ALL column ON schema.object

TO user | role | PUBLIC WITH GRANT OPTION

其中

system_privilege: 系統權限

role: 角色名

user: 被授權的用戶名

object_privilege: 所授予的權限名字,可以是

ALTER

DELETE

EXECUTE

INDEX

INSERT

REFERENCES

SELECT

UPDATE

Column: 列名

schema: 模式名

object: 對象名

4.數據字典

USER_SOURCE 用戶的存儲過程、函數的源代碼字典

DBA_SOURCE 整個系統所有用戶的存儲過程、函數的源代碼字典

ALL_SOURCE 當前用戶能使用的存儲過程(包括其她用戶授權)、函數的源代碼字典

USER_ERRORS 用戶的存儲過程、函數的源代碼存在錯誤的信息字典

臨時表

(針對SQL2000/2005)

可以創建本地和全局臨時表。本地臨時表僅在當前會話中可見;全局臨時表在所有會話中都可見。

本地臨時表的名稱前面有一個編号符 (#table_name),而全局臨時表的名稱前面有兩個編号符 (##table_name)。

SQL 語句使用 CREATE TABLE 語句中為 table_name 指定的名稱引用臨時表:

CREATE TABLE #MyTempTable (cola INT PRIMARY KEY)

INSERT INTO #MyTempTable VALUES (1)

如果本地臨時表由存儲過程創建或由多個用戶同時執行的應用程序創建,則 SQL Server 必須能夠區分由不同用戶創建的表。為此,SQL Server 在内部為每個本地臨時表的表名追加一個數字後綴。存儲在 tempdb 數據庫的 sysobjects 表中的臨時表,其全名由 CREATE TABLE 語句中指定的表名和系統生成的數字後綴組成。為了允許追加後綴,為本地臨時表指定的表名 table_name 不能超過 116 個字符。

除非使用 DROP TABLE 語句顯式除去臨時表,否則臨時表将在退出其作用域時由系統自動除去:

當存儲過程完成時,将自動除去在存儲過程中創建的本地臨時表。由創建表的存儲過程執行的所有嵌套存儲過程都可以引用此表。但調用創建此表的存儲過程的進程無法引用此表。

所有其它本地臨時表在當前會話結束時自動除去。

全局臨時表在創建此表的會話結束且其它任務停止對其引用時自動除去。任務與表之間的關聯隻在單個 Transact-SQL 語句的生存周期内保持。換言之,當創建全局臨時表的會話結束時,最後一條引用此表的 Transact-SQL 語句完成後,将自動除去此表。

上一篇:彩虹旗

下一篇:多線程

相關詞條

相關搜索

其它詞條