資料庫存儲過程設計
① 存儲過程的實例
資料庫存儲過程
資料庫存儲過程的實質就是部署在資料庫端的一組定義代碼以及sql。將常用的或很復雜的工作,預先用SQL語句寫好並用一個指定的名稱存儲起來,那麼以後要叫資料庫提供與已定義好的存儲過程的功能相同的服務時,只需調用execute,即可自動完成命令。
利用SQL的語言可以編寫對於資料庫訪問的存儲過程,其語法如下:
CREATE PROC[EDURE] procere_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(單位名稱) CREATEprocsearch_dwmc@dwidoldint,@dwmcresultvarchar(100)outputasdeclare@stopintdeclare@resultvarchar(80)declare@dwmcvarchar(80)declare@dwidintsetnocountonset@stop=1set@dwmc=""select@dwmc=dwmc,@dwid=convert(int,fjdid)fromjtdwwhereid=@dwidoldset@result=rtrim(@dwmc)if@dwid=0set@stop=0while(@stop=1)and(@dwid<>0)beginset@dwidold=@dwidselect@dwmc=dwmc,@dwid=convert(int,fjdid)fromjtdwwhereid=@dwidoldif@@rowcount=0set@dwmc=""elseset@result=@dwmc+@resultif(@dwid=0)or(@@rowcount=0)set@stop=0elsecontinueendset@dwmcresult=rtrim(@result)使用execpro-name[pram1pram2.....]SQL Server中存儲過程
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] procere procere_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 使用CALL 語句來實現對存儲過程的調用。
語法:
call procere_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 語句完成後,將自動除去此表。
② Java資料庫程序中的存儲過程設計
本文闡述了怎麼使用DBMS存儲過程 闡述了使用存儲過程的基本的和高級特性 比如返回ResultSet 本文假設你對DBMS和JDBC已經非常熟悉 也假設你能夠毫無障礙地閱讀其它語言寫成的代碼(即不是Java的語言) 但是 並不要求你有任何存儲過程的編程經歷
存儲過程是指保存在數據豎拿庫並在資料庫端執行的程序 你可以使用特殊的語法在Java類中調用存儲過程 在調用時 存儲過程的名稱及指定的參數通過JDBC連接發送給DBMS 執行存儲過程並通過連接(如果有)返回結果
使用存儲過程擁有和使用基於EJB或CORBA這樣的應用伺服器一樣的好處 區別是存儲過程可以從很多流行的DBMS中免費使用 而應用伺服器大都非常昂貴 這並不只是許可證費用的問題 使用應用伺服器所需要花費的管理 編寫代碼的費用 以及客戶程序所增加的復雜性 都可以通過DBMS中的存儲過程所整個地替代
你可以使用Java Python Perl或C編寫存儲過程 但是通常使用你的DBMS所指定的特定語言 Oracle使用PL/SQL PostgreSQL使用pl/pgsql DB 使用Proceral SQL 這些語言都非常相似 在它們之間移植存儲過程並不比在Sun的EJB規范不同實現版本之間移植Session Bean困難 並且 存儲過程是為嵌入SQL所設計 這使得它們比Java或C等語言更加友好地方式表達資料庫的機制
因為存儲過程運行在DBMS自身 這可以幫助減少應用程序中的等待時間 不是在Java代碼中執行 個或 個SQL語句 而只需要在伺服器端執行 個存儲過程 網路上的數據往返次數的減少可以戲劇性地優化性能
使用存儲過程
簡單的老的JDBC通過CallableStatement類支持存儲過程的調用 該類實際上是PreparedStatement的一個子類 假設我們有一個poets資料庫 資料庫中有一個設置詩人逝世年齡的存儲過程 下面是對老酒鬼Dylan Thomas(old soak Dylan Thomas 不指定是否有關典故跡灶 文化 請批評指正 譯注)進行調用的詳細代碼
try{int age = ;String poetName = dylan thomas ;CallableStatement proc = connection prepareCall( { call set_death_age(? ?) } );proc setString( poetName);proc setInt( age);cs execute();}catch (SQLException e){// }
傳給prepareCall方法的字串是存儲過程調用的書寫規范 它指定了存儲過程的名稱 ?代表了你需要指定的參數
和JDBC集成是存儲過程的一個很大的便利 為了從應用中調用存儲過程 不需要存根(stub)類或者配置文件 除了你的DBMS的JDBC驅動程序外什麼也不需要
當這段代碼執行時 資料庫的存儲過程就被調用 我們沒有去獲取結果 因為該存儲過程並不返回結果 執行成功或失敗將通過例外得知 失敗可能意味著調用存儲姿纖扮過程時的失敗(比如提供的一個參數的類型不正確) 或者一個應用程序的失敗(比如拋出一個例外指示在poets資料庫中並不存在 Dylan Thomas )
結合SQL操作與存儲過程
映射Java對象到SQL表中的行相當簡單 但是通常需要執行幾個SQL語句 可能是一個SELECT查找ID 然後一個INSERT插入指定ID的數據 在高度規格化(符合更高的範式 譯注)的資料庫模式中 可能需要多個表的更新 因此需要更多的語句 Java代碼會很快地膨脹 每一個語句的網路開銷也迅速增加
將這些SQL語句轉移到一個存儲過程中將大大簡化代碼 僅涉及一次網路調用 所有關聯的SQL操作都可以在資料庫內部發生 並且 存儲過程語言 例如PL/SQL 允許使用SQL語法 這比Java代碼更加自然 下面是我們早期的存儲過程 使用Oracle的PL/SQL語言編寫
create procere set_death_age(poet VARCHAR poet_age NUMBER)poet_id NUMBER;beginSELECT id INTO poet_id FROM poets WHERE name = poet;INSERT INTO deaths (mort_id age) VALUES (poet_id poet_age);end set_death_age;
很獨特?不 我打賭你一定期待看到一個poets表上的UPDATE 這也暗示了使用存儲過程實現是多麼容易的一件事情 set_death_age幾乎可以肯定是一個很爛的實現 我們應該在poets表中添加一列來存儲逝世年齡 Java代碼中並不關心資料庫模式是怎麼實現的 因為它僅調用存儲過程 我們以後可以改變資料庫模式以提高性能 但是我們不必修改我們代碼
下面是調用上面存儲過程的Java代碼
public static void setDeathAge(Poet dyingBard int age)throws SQLException{Connection con = null;CallableStatement proc = null;
try{con = connectionPool getConnection();proc = con prepareCall( { call set_death_age(? ?) } );proc setString( dyingBard getName());proc setInt( age);proc execute();}finally{try{proc close();}catch (SQLException e) {}con close();}}
為了確保可維護性 建議使用像這兒這樣的static方法 這也使得調用存儲過程的代碼集中在一個簡單的模版代碼中 如果你用到許多存儲過程 就會發現僅需要拷貝 粘貼就可以創建新的方法 因為代碼的模版化 甚至也可以通過腳本自動生產調用存儲過程的代碼
Functions
存儲過程可以有返回值 所以CallableStatement類有類似getResultSet這樣的方法來獲取返回值 當存儲過程返回一個值時 你必須使用registerOutParameter方法告訴JDBC驅動器該值的SQL類型是什麼 你也必須調整存儲過程調用來指示該過程返回一個值
下面接著上面的例子 這次我們查詢Dylan Thomas逝世時的年齡 這次的存儲過程使用PostgreSQL的pl/pgsql
create function snuffed_it_when (VARCHAR) returns integer declarepoet_id NUMBER;poet_age NUMBER;begin first get the id associated with the poet SELECT id INTO poet_id FROM poets WHERE name = $ ; get and return the age SELECT age INTO poet_age FROM deaths WHERE mort_id = poet_id;return age;end; language pl/pgsql ;
另外 注意pl/pgsql參數名通過Unix和DOS腳本的$n語法引用 同時 也注意嵌入的注釋 這是和Java代碼相比的另一個優越性 在Java中寫這樣的注釋當然是可以的 但是看起來很凌亂 並且和SQL語句脫節 必須嵌入到Java String中
下面是調用這個存儲過程的Java代碼
connection setAutoCommit(false);CallableStatement proc =connection prepareCall( { ? = call snuffed_it_when(?) } );proc registerOutParameter( Types INTEGER);proc setString( poetName);cs execute();int age = proc getInt( );
如果指定了錯誤的返回值類型會怎樣?那麼 當調用存儲過程時將拋出一個RuntimeException 正如你在ResultSet操作中使用了一個錯誤的類型所碰到的一樣
復雜的返回值
關於存儲過程的知識 很多人好像就熟悉我們所討論的這些 如果這是存儲過程的全部功能 那麼存儲過程就不是其它遠程執行機制的替換方案了 存儲過程的功能比這強大得多
當你執行一個SQL查詢時 DBMS創建一個叫做cursor(游標)的資料庫對象 用於在返回結果中迭代每一行 ResultSet是當前時間點的游標的一個表示 這就是為什麼沒有緩存或者特定資料庫的支持 你只能在ResultSet中向前移動
某些DBMS允許從存儲過程中返回遊標的一個引用 JDBC並不支持這個功能 但是Oracle PostgreSQL和DB 的JDBC驅動器都支持在ResultSet上打開到游標的指針(pointer)
設想列出所有沒有活到退休年齡的詩人 下面是完成這個功能的存儲過程 返回一個打開的游標 同樣也使用PostgreSQL的pl/pgsql語言
create procere list_early_deaths () return refcursor as declaretoesup refcursor;beginopen toesup forSELECT poets name deaths ageFROM poets deaths all entries in deaths are for poets but the table might bee generic WHERE poets id = deaths mort_idAND deaths age < ;return toesup;end; language plpgsql ;
下面是調用該存儲過程的Java方法 將結果輸出到PrintWriter
PrintWriter:
static void sendEarlyDeaths(PrintWriter out){Connection con = null;CallableStatement toesUp = null;try{con = ConnectionPool getConnection();
// PostgreSQL needs a transaction to do this con setAutoCommit(false);
// Setup the call CallableStatement toesUp= connection prepareCall( { ? = call list_early_deaths () } );toesUp registerOutParameter( Types OTHER);getResults execute();
ResultSet rs = (ResultSet) getResults getObject( );while (rs next()){String name = rs getString( );int age = rs getInt( );out println(name + was + age + years old );}rs close();}catch (SQLException e){// We should protect these calls toesUp close();con close();}}
因為JDBC並不直接支持從存儲過程中返回遊標 我們使用Types OTHER來指示存儲過程的返回類型 然後調用getObject()方法並對返回值進行強制類型轉換
這個調用存儲過程的Java方法是mapping的一個好例子 Mapping是對一個集上的操作進行抽象的方法 不是在這個過程上返回一個集 我們可以把操作傳送進去執行 本例中 操作就是把ResultSet列印到一個輸出流 這是一個值得舉例的很常用的例子 下面是調用同一個存儲過程的另外一個方法實現
public class ProcessPoetDeaths{public abstract void sendDeath(String name int age);}
static void mapEarlyDeaths(ProcessPoetDeaths mapper){Connection con = null;CallableStatement toesUp = null;try{con = ConnectionPool getConnection();con setAutoCommit(false);
CallableStatement toesUp= connection prepareCall( { ? = call list_early_deaths () } );toesUp registerOutParameter( Types OTHER);getResults execute();
ResultSet rs = (ResultSet) getResults getObject( );while (rs next()){String name = rs getString( );int age = rs getInt( );mapper sendDeath(name age);}rs close();}catch (SQLException e){// We should protect these calls toesUp close();con close();}}
這允許在ResultSet數據上執行任意的處理 而不需要改變或者復制獲取ResultSet的方法
static void sendEarlyDeaths(final PrintWriter out){ProcessPoetDeaths myMapper = new ProcessPoetDeaths(){public void sendDeath(String name int age){out println(name + was + age + years old );}};mapEarlyDeaths(myMapper);}
這個方法使用ProcessPoetDeaths的一個匿名實例調用mapEarlyDeaths 該實例擁有sendDeath方法的一個實現 和我們上面的例子一樣的方式把結果寫入到輸出流 當然 這個技巧並不是存儲過程特有的 但是和存儲過程中返回的ResultSet結合使用 是一個非常強大的工具
結論
存儲過程可以幫助你在代碼中分離邏輯 這基本上總是有益的 這個分離的好處有
快速創建應用 使用和應用一起改變和改善的資料庫模式
資料庫模式可以在以後改變而不影響Java對象 當我們完成應用後 可以重新設計更好的模式
存儲過程通過更好的SQL嵌入使得復雜的SQL更容易理解
編寫存儲過程比在Java中編寫嵌入的SQL擁有更好的工具——大部分編輯器都提供語法高亮!
存儲過程可以在任何SQL命令行中測試 這使得調試更加容易
並不是所有的資料庫都支持存儲過程 但是存在許多很棒的實現 包括免費/開源的和非免費的 所以移植並不是一個問題 Oracle PostgreSQL和DB 都有類似的存儲過程語言 並且有在線的社區很好地支持
存儲過程工具很多 有像TOAD或TORA這樣的編輯器 調試器和IDE 提供了編寫 維護PL/SQL或pl/pgsql的強大的環境
lishixin/Article/program/Java/hx/201311/25906
③ 如何創建存儲過程 (SQL Server Management Studio)
本主題介紹如何使用 SQL Server Management Studio 中的對象資源管理器創建 Transact-SQL 存儲過程,並提供一個在 AdventureWorks2008R2 資料庫中創建簡單存儲過程的示例。創建存儲過程在對象資源管理器中,連接到某個資料庫引擎實例,再展開該實例。展開「資料庫」、存儲過程所屬的資料庫以及「可編程性」。右鍵單擊「存儲過程」,再單擊「新建存儲過程」。在「查詢」菜單上,單擊「指定模板參數的值」。在「指定模板參數的值」對話框中,「值」列包含參數的建議值。接受這些值或將其替換為新值,再單擊「確定」。在查詢編輯器中,使用過程語句替換 SELECT 語句。若要測試語法,請在「查詢」菜單上,單擊「分析」。若要創建存儲過程,請在「查詢」菜單上,單擊「執行」。若要保存腳本,請在「文件」菜單上,單擊「保存」。接受該文件名或將其替換為新的名稱,再單擊「保存」。安全說明驗證所有用戶的輸入。驗證前請勿連接用戶輸入。絕對不要執行根據尚未驗證的用戶輸入構造的命令。有關詳細信息,請參閱SQL 注入。創建存儲過程的示例在對象資源管理器中,連接到某個資料庫引擎實例,再展開該實例。依次展開「資料庫」、AdventureWorks2008R2 資料庫和「可編程性」。右鍵單擊「存儲過程」,再單擊「新建存儲過程」。在「查詢」菜單上,單擊「指定模板參數的值」。在「指定模板參數的值」對話框中,輸入下列所示的參數值。參數值Author您的姓名Create Date今天的日期Description返回雇員數據。Procere_nameHumanResources.uspGetEmployees@Param1@LastName@Datatype_For_Param1nvarchar(50)Default_Value_For_Param1NULL@Param2@FirstName@Datatype_For_Param2nvarchar(50)Default_Value_For_Param2NULL單擊「確定」。在查詢編輯器中,使用以下語句替換 SELECT 語句: SELECT FirstName, LastName, JobTitle, Department FROM HumanResources.vEmployeeDepartment WHERE FirstName = @FirstName AND LastName = @LastName;若要測試語法,請在「查詢」菜單上,單擊「分析」。如果返回錯誤消息,則請將這些語句與上述信息進行比較,並視需要進行更正。若要創建存儲過程,請在「查詢」菜單上,單擊「執行」。若要保存腳本,請在「文件」菜單上,單擊「保存」。輸入新的文件名,再單擊「保存」。若要運行存儲過程,請在工具欄上單擊「新建查詢」。在查詢窗口中,輸入下列語句:USE AdventureWorks2008R2; GO EXECUTE HumanResources.uspGetEmployees @FirstName = N'Diane', @LastName = N'Margheim'; GO在「查詢」菜單上,單擊「執行」。請參閱任務如何在 SQL Server Management Studio 中使用模板如何修改存儲過程 (SQL Server Management Studio)如何刪除存儲過程 (SQL Server Management Studio)參考CREATE PROCEDURE (Transact-SQL)概念>創建存儲過程(資料庫引擎)其他資源存儲過程幫助主題
④ 資料庫存儲過程設計
--第一題use master
go
--創建資料庫
if(db_id('studentDB')) is not null
drop database [studentDB]
create database [studentDB]
go
use [studentDB]
go
--創建學生表
create table [student]
(
[studentId] int identity(1,1) primary key,
[stuName] varchar(50) not null
)
go
use [studentDB]
go
--創建課程表
create table [subject]
(
[subjectId] int identity(1,1) primary key,
[subjectName] varchar(50) not null
)
go
use [studentDB]
go
--創建成績表(選課表)
create table [score]
(
[studentId] int,
[subjectId] int,
[score] int
)
go
--添加外鍵約束
--學生ID
alter table [score]
add constraint FK_score_student
foreign key([studentId])
references [student] ([studentId])
go
--科目ID
alter table [score]
add constraint FK_score_subject
foreign key([subjectId])
references [subject] ([subjectId])
go
--插入測試數據
insert [student]
select '張三' union
select '李四' union
select '王五' union
select '高六' union
select '趙七'
go
insert [subject]
select '語文' union
select '數學' union
select '英語'
go
insert [score]
select 1,1,50 union
select 1,2,51 union
select 1,3,52 union
select 2,1,60 union
select 2,2,61 union
select 2,3,62 union
select 3,1,70 union
select 3,2,71 union
select 3,3,72 union
select 5,1,90 union
select 5,2,89 union
select 5,3,88
go
use [studentDB]
go
--創建返回學生選課情況的存儲過程
create procere [pro_GetStudentScore]
@stuName varchar(50)
as
select sco.[studentId],sub.[subjectName],sco.[score]
from [subject] sub,[score] sco
where sub.[subjectId]=sco.[subjectId]
and sco.[studentId]=(select [studentId] from [student] where [stuName] = @stuName)
go
exec [pro_GetStudentScore] '趙七'
--select * from [student]
--select * from [subject]
--select * from [score]
⑤ sql怎樣新建存儲過程
一:創建沒有參數的存儲過程:
CREATE PROCEDURE select_all
AS
BEGIN
SELECT * from T_login1
GO
二:創建帶參數的存儲過程:
CREATE PROCEDURE select_name
@id uniqueidentifier
AS
BEGIN
SELECT * from T_login1 where PSN0001A=@id
GO
(5)資料庫存儲過程設計擴展閱讀:
創建存儲過程的注意事項:
1、保持事務簡短,事務越短,越不可能造成阻塞。
2、在事務中盡量避免使用循環while和游標,以及避免採用訪問大量行的語句。
3、在啟動事務前完成所有的計算和查詢等操作,避免同一事務中交錯讀取和更新。可以使用表變數預先存儲數據。即存儲過程中查詢與更新使用兩個事務實現。
4、超時會讓事務不執行回滾,超時後如果客戶端關閉連接sqlserver自動回滾事務。如果不關閉,將造成數據丟失,而其他事務將在這個未關閉的連接上執行,造成資源鎖定,甚至伺服器停止響應。
⑥ 如何編寫存儲過程
//創建存儲過程
CREATE PROCEDURE userData(
IN id INT
)
BEGIN
SELECT * from userdata WHERE userflag = id;
END;
其中IN是傳進去的變數;
drop procere userData;//銷毀這個存儲過程。
call userData(2) //調用存儲過程。
(6)資料庫存儲過程設計擴展閱讀:
sql中的存儲過程及相關介紹:
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這兩個語句。
參考資料來源:網路-儲存過程
⑦ sqlserver
摘自:http://database.ctocio.com.cn/analysis/465/7709465.shtml
【IT專家網獨家】SQL Server用戶自定義函數和存儲過程有類似的功能,都可以創建捆綁SQL語句,存儲在server中供以後使用。這樣能夠極大地提高工作效率,通過以下的各種做法可以減少編程所需的時間:
重復使用編程代碼,減少編程開發時間。
隱藏SQL細節,把SQL繁瑣的工作留給資料庫開發人員,而程序開發員則集中處理高級編程語言。
維修集中化,可以在一個地方做業務上的邏輯修改,然後讓這些修改自動應用到所有相關程序中。
乍看之下,用戶自定義函數和存儲過程的功能似乎一摸一樣。但是,其實這兩者之間還有一些雖然細微但是很重要的差異:
存儲過程是使用EXEC命令獨立調用的,而用戶自定義函數是在另一個SQL語句中調用的。
l存儲程序是允許用戶和程序去使用存儲過程,而不是允許其存取表格,這樣能夠增強程序安全性。與標準的SQL Server相比,存儲程序限制用戶行動許可權方面更為細化。例如,如果你有一個貨存表格,每次賣出一個貨物收銀員都要對表格進行更新一次(從貨存中把該貨品減去一件)。你可以給收銀員設置許可權,允許其使用decrement_item存儲過程,而不是允許他們有任意修改或村表格的許可權。
函數必須始終返回一個值(一個標量值或一個表格)。而存儲過程可以返回一個標量值、一個表值或無需返回值。
總而言之,存儲程序對SQL Server開發員來說是最有價值的寶物之一,用於資料庫中,能夠大大的提高工作效率,增強安全性,絕對超值。
⑧ 資料庫存儲過程怎麼編寫
第一步:點擊資料庫下的「可編程性」,選擇「存儲過程」,點擊滑鼠右鍵,選擇「新建存儲過程」
第二步:在create PROCEDURE 後 輸入存儲過程的名字,緊跟著的就是定義存儲過程的參數,接下來就可以去編寫自己所需要組裝的存儲過程語句了
第三步: 編譯存儲過程,在工具欄上按下執行按鈕,如果沒有錯誤,就編寫成功了。
第四步:調用:在sqlserver的語句查詢框中,輸入exec 存儲過程名 參數,執行就可以了。
基本語法格式如下:中括弧帶的是可選項
create proc | procere pro_name
[{@參數數據類型} [=默認值] [output],
{@參數數據類型} [=默認值] [output],
....
]
as
begin
SQL_statements
--業務處理
end