一、存儲過程介紹
存儲過程是由流控制和SQL語句書寫的過程,這個過程經編譯和優化後存儲在數據庫服
務器中,應用程序使用時只要調用即可。在ORACLE中,若干個有聯繫的過程可以組合在一起構成程序包。
存儲過程是利用SQL
Server所提供的Transact-SQL語言所編寫的程序。Transact-SQL語言是SQL
Server提供專爲設計數據庫應用程序的語言,它是應用程序和SQL Server數據庫間的主要程序式設計界面。它好比Oracle數據庫
系
統中的Pro-SQL和Informix的數據庫系統結構中的Informix-
4GL語言。這類語言主要提供以下功能,讓用戶可以設計出符合引用需求的程序:
1)、變量說明
2)、ANSI兼容的SQL命令(如Select,Update….)
3)、一般流程控制命令(if…else…、while….)
4)、內部函數
*
存儲過程的能力大大增強了SQL語言的功能和靈活性。存儲過程可以用流控制語句編寫,有很強的靈活性,可以完成複雜的判斷和較複雜的 運算。
* 可保證數據的安全性和完整性。
# 通過存儲過程可以使沒有權限的用戶在控制之下間接地存取數據庫,從而保證數據的安全。
# 通過存儲過程可以使相關的動作在一起發生,從而可以維護數據庫的完整性。
*
在運行存儲過程前,數據庫已對其進行了語法和句法分析,並給出了優化執行方案。這種已經編譯好的過程可極大地改善SQL語句的性能。由於執行SQL語句的
大部分工作已經完成,所以存儲過程能以極快的速度執行。
* 可以降低網絡的通信量。
* 使體現企業規則的運算程序放入數據庫服務器中,以便:
# 集中控制。
#
當企業規則發生變化時在服務器中改變存儲過程即可,無須修改任何應用程序。企業規則的特點是要經常變化,如果把體現企業規則的運算程序放入應用程序中,則
當企業規則發生變化時,就需要修改應用程序工作量非常之大(修改、發行和安裝應用程序)。如果把體現企業規則的運算放入存儲過程中,則當企業規則發生變化
時,只要修改存儲過程就可以了,應用程序無須任何變化。
1)、系統存儲過程:以sp_開頭,用來進行系統的各項設定.取得信息.相關管理工作,
如 sp_help就是取得指定對象的相關信息
2)、擴展存儲過程以XP_開頭,用來調用操作系統提供的功能
exec master..xp_cmdshell 'ping 10.8.16.1'
3)、用戶自定義的存儲過程,這是我們所指的存儲過程
CREATE PROCEDURE [擁有者.]存儲過程名[;程序編號]
[(參數#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 ordered=@o_id
例子說明:
該例子是建立一個簡單的存儲過程order_tot_amt,這個存儲過程根據用戶輸入的定單
ID號碼(@o_id),由定單明細表
(orderdetails)中計算該定單銷售總額[單價(Unitprice)*數量(Quantity)],這一金額通過@p_tot這一參數輸出給
調用這一存儲過程的程序。
Create procedure procedue_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 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
&n bsp; print 'Fail'
go
數據庫存儲過程的實質就是部署在數據庫端的一組定義代碼以及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.....]
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爲輸出參數,用來承接我們所要的結果。
存儲過程具有以下特點:
1.具有立即訪問數據庫的能力;
2.是數據庫服務器端的執行代碼,在服務器執行操作時,減少網絡通訊,提高執行效率。
3.保證數據庫安全
,自動完成提前設定的作業。
1:調試麻煩,但是用 PL/SQL Developer 調試很方便!彌補這個缺點。
2:移植問題,數據庫端代碼當然是與數據庫相關的。但是如果是做工程型項目,基本不存在移植問
題。
3:重新編譯問題,因爲後端代碼是運行前編譯的,如果帶有引用關係的對象發生改變時,受影響的
存儲過程、包將需要重新編譯(不過也可以設置成運行時刻自動編譯)。
4:
如果在一個程序系統中大量的使用存儲過程,到程序交付使用的時候隨着用戶需求的增加會導致數據結構的變化,接着就是系統的相關問題了,最後如果用戶想維護
該系統可以說是很難很難、而且代價是空前的。維護起來更加麻煩!
(針對SQL2000/2OO5)
可以創建本地和全局臨時表。本地臨時表僅在當前會話中可見;全局臨時表在所有會話中都可見。
本地臨時表的名稱前面有一個編號符
(#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
語句完成後,將自動除去此表。