1、創(chuàng)建臨時(shí)表空間
/* create temporary tablespace*/
create temporary tablespace student_temp
tempfile 'D:\oracle\product\10.2.0\oradata\Student\student_temp.dbf'
size 50m
autoextend on
next 50m maxsize 20480m
extent management local;
2、創(chuàng)建數(shù)據(jù)表空間
/* create data tablespace*/
create tablespace student_data
logging
datafile 'D:\oracle\product\10.2.0\oradata\Student\student_data.dbf'
size 50m
autoextend on
next 50m maxsize 20480m
extent management local;
3、創(chuàng)建用戶(hù)并分配權(quán)限
/* create user and distribute tablespace */
create user student identified by cxhuan
default tablespace student_data
temporary tablespace student_temp;
4、給用戶(hù)授權(quán)
/* authorize role to user */
grant connect,resource,dba to student;
用一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明Java處理事務(wù):
我們用銀行轉(zhuǎn)賬的時(shí)候可以簡(jiǎn)單的看成是兩步操作--將錢(qián)從A賬戶(hù)轉(zhuǎn)出和將錢(qián)轉(zhuǎn)到B賬戶(hù)。問(wèn)題來(lái)了,如果我從A賬戶(hù)轉(zhuǎn)出之后,突然無(wú)法連接數(shù)據(jù)庫(kù)了,這樣錢(qián)就不能轉(zhuǎn)到B賬戶(hù)了,可是A的錢(qián)已經(jīng)沒(méi)了。所以我們應(yīng)該把這兩步看成是一個(gè)整體,要么同時(shí)成功,要么什么都不做。這就是事務(wù)了。
Java中是如何處理事務(wù)的呢?
我們從java.sql.Connection說(shuō)起,Connection表示了一個(gè)和數(shù)據(jù)庫(kù)的鏈接,可以通過(guò)Connection來(lái)對(duì)數(shù)據(jù)庫(kù)操作。在通常情況是Connection的屬性是自動(dòng)提交的,也就是說(shuō)每次的操作真的更新了數(shù)據(jù)庫(kù),真的無(wú)法回退了。針對(duì)上述的例子,一旦A賬戶(hù)的錢(qián)轉(zhuǎn)出了,即對(duì)數(shù)據(jù)庫(kù)進(jìn)行了更新操作了,但是錢(qián)并沒(méi)有轉(zhuǎn)到B的賬戶(hù),這筆錢(qián)就白白“不見(jiàn)”了。這并不是我們希望的。
我們希望的是:看起來(lái)成功了,但是沒(méi)有真的操作數(shù)據(jù)庫(kù),知道我想讓他真的發(fā)生。可以通過(guò)Connection的setAutoCommit(false)讓Connection不自動(dòng)提交你的數(shù)據(jù),除非你真的想提交。那么如何讓操作真的發(fā)生呢?可以使用Connection的commit方法。如何讓操作回退呢?使用rollback方法。
例如:
try{
Connection conn = getConnection(); // 不管如何我們得到了鏈接
conn.setAutoCommit(false);
// A賬戶(hù)轉(zhuǎn)出
// B賬戶(hù)轉(zhuǎn)入
conn.commit(); // 成功的情況下,提交更新。
} catch(SQLException ex) {
conn.rollback(); // 失敗的情況下,回滾所有的操作
} finally {
conn.close();
}
這里有一點(diǎn)非常重要,事務(wù)是基于數(shù)據(jù)庫(kù)鏈接的。所以在但數(shù)據(jù)庫(kù)的情況下,事務(wù)操作很簡(jiǎn)單。
那么如果表分布在兩個(gè)不同的數(shù)據(jù)庫(kù)中呢?
例如訂單表在訂單庫(kù)中,庫(kù)存表在庫(kù)存庫(kù)中,那么我們?nèi)绾翁幚磉@樣的事務(wù)呢?
需要注意,提交也可以遇到錯(cuò)誤呀!
try{
Connection conn1 = getConnection1();
Connection conn2 = getConnection2();
// 基于conn1做更新操作
// 基于conn2做更新操作
try{
conn1.commit()
} catch(SQLExcetion ) {
conn1.rollback();
}
try {
conn2.commit();
} catch(SQLException ) {
conn2.rollbakc();
// 保證務(wù)必將剛才的更新還原回來(lái)。
}
} catch(SQLException ex) {
// 如果更新失敗,conn1.rollback
// 如果更新失敗,conn1.rollback && conn2.rollback
} finally {
conn1.close();
conn2.close();
}
看看上述的代碼就知道,其實(shí)操作非常的復(fù)雜,甚至:保證肯定還原剛才更新的賬戶(hù)根本無(wú)法保證。
在上述情況下的事務(wù)可以稱(chēng)之為分布式事務(wù),通過(guò)上述的代碼中事務(wù)同時(shí)提交處理的部分我們可以得出,要想處理分布式事務(wù),必須有獨(dú)立于數(shù)據(jù)庫(kù)的第三方的事務(wù)處理組件。
幸運(yùn)的是通常情況下,JavaEE兼容的應(yīng)用服務(wù)器,例如:Weblogic,Websphere,JBoss,Glassfish等都有這種分布式事務(wù)處理的組件。
如何使用應(yīng)用服務(wù)器的分布式事務(wù)管理器處理分布式事務(wù)?
以galssfish為例
1 建立對(duì)應(yīng)兩個(gè)數(shù)據(jù)庫(kù)的XA(javax.sql.XADataSource)類(lèi)型的數(shù)據(jù)源。
2 使用UserTransaction來(lái)保證分布式事務(wù)。
try{
Connection conn1 = datasource1.getConnection();
Connection conn2 = datasource2.getConnection();
UserTransaction ut = getUserTransaction();
ut.begin();
// A賬戶(hù)轉(zhuǎn)出
// B賬戶(hù)轉(zhuǎn)入
ut.commit(); // 成功的情況下,提交更新。
} catch(SQLException ex) {
ut.rollback(); // 失敗的情況下,回滾所有的操作
} finally {
conn.close();
}
如何獲取UserTransaction呢?可以使用如下方法
UserTransaction tx = (UserTransaction) ctx.lookup("jndi/UserTransaction");
存儲(chǔ)過(guò)程天天用,關(guān)于使用存儲(chǔ)過(guò)程的sql語(yǔ)句的爭(zhēng)論也一直在,個(gè)人覺(jué)得使用存儲(chǔ)過(guò)程要好于用sql語(yǔ)句,整理了一些說(shuō)明:
存儲(chǔ)過(guò)程是由一些SQL語(yǔ)句和控制語(yǔ)句組成的被封裝起來(lái)的過(guò)程,它駐留在數(shù)據(jù)庫(kù)中,可以被客戶(hù)應(yīng)用程序調(diào)用,也可以從另一個(gè)過(guò)程或觸發(fā)器調(diào)用。它的參數(shù)可以被傳遞和返回。與應(yīng)用程序中的函數(shù)過(guò)程類(lèi)似,存儲(chǔ)過(guò)程可以通過(guò)名字來(lái)調(diào)用,而且它們同樣有輸入?yún)?shù)和輸出參數(shù)。
根據(jù)返回值類(lèi)型的不同,我們可以將存儲(chǔ)過(guò)程分為三類(lèi):返回記錄集的存儲(chǔ)過(guò)程, 返回?cái)?shù)值的存儲(chǔ)過(guò)程(也可以稱(chēng)為標(biāo)量存儲(chǔ)過(guò)程),以及行為存儲(chǔ)過(guò)程。顧名思義,返回記錄集的存儲(chǔ)過(guò)程的執(zhí)行結(jié)果是一個(gè)記錄集,典型的例子是從數(shù)據(jù)庫(kù)中檢索出符合某一個(gè)或幾個(gè)條件的記錄;返回?cái)?shù)值的存儲(chǔ)過(guò)程執(zhí)行完以后返回一個(gè)值,例如在數(shù)據(jù)庫(kù)中執(zhí)行一個(gè)有返回值的函數(shù)或命令;最后,行為存儲(chǔ)過(guò)程僅僅是用來(lái)實(shí)現(xiàn)數(shù)據(jù)庫(kù)的某個(gè)功能,而沒(méi)有返回值,例如在數(shù)據(jù)庫(kù)中的更新和刪除操作。
使用存儲(chǔ)過(guò)程的好處
相對(duì)于直接使用SQL語(yǔ)句,在應(yīng)用程序中直接調(diào)用存儲(chǔ)過(guò)程有以下好處:
(1)減少網(wǎng)絡(luò)通信量。調(diào)用一個(gè)行數(shù)不多的存儲(chǔ)過(guò)程與直接調(diào)用SQL語(yǔ)句的網(wǎng)絡(luò)通信量可能不會(huì)有很大的差別,可是如果存儲(chǔ)過(guò)程包含上百行SQL語(yǔ)句,那么其性能絕對(duì)比一條一條的調(diào)用SQL語(yǔ)句要高得多。
(2)執(zhí)行速度更快。有兩個(gè)原因:首先,在存儲(chǔ)過(guò)程創(chuàng)建的時(shí)候,數(shù)據(jù)庫(kù)已經(jīng)對(duì)其進(jìn)行了一次解析和優(yōu)化。其次,存儲(chǔ)過(guò)程一旦執(zhí)行,在內(nèi)存中就會(huì)保留一份這個(gè)存儲(chǔ)過(guò)程,這樣下次再執(zhí)行同樣的存儲(chǔ)過(guò)程時(shí),可以從內(nèi)存中直接調(diào)用。
(3)更強(qiáng)的適應(yīng)性:由于存儲(chǔ)過(guò)程對(duì)數(shù)據(jù)庫(kù)的訪(fǎng)問(wèn)是通過(guò)存儲(chǔ)過(guò)程來(lái)進(jìn)行的,因此數(shù)據(jù)庫(kù)開(kāi)發(fā)人員可以在不改動(dòng)存儲(chǔ)過(guò)程接口的情況下對(duì)數(shù)據(jù)庫(kù)進(jìn)行任何改動(dòng),而這些改動(dòng)不會(huì)對(duì)應(yīng)用程序造成影響。
(4) 布式工作:應(yīng)用程序和數(shù)據(jù)庫(kù)的編碼工作可以分別獨(dú)立進(jìn)行,而不會(huì)相互壓制。
msdn上面相關(guān)的說(shuō)明
考慮使用存儲(chǔ)過(guò)程的理由
也許您曾經(jīng)在多處編寫(xiě)過(guò)使用 SqlCommand 對(duì)象的 T-SQL,但卻從未考慮過(guò)是否有一個(gè)比將它并入數(shù)據(jù)訪(fǎng)問(wèn)代碼更好的位置。由于應(yīng)用程序隨著時(shí)間的推移增添了一些功能,因此其內(nèi)部可能包含一些復(fù)雜的 T-SQL 過(guò)程代碼。存儲(chǔ)過(guò)程為封裝此代碼提供了一個(gè)替換位置。
大多數(shù)人可能對(duì)存儲(chǔ)過(guò)程已有所了解,但對(duì)于那些不了解存儲(chǔ)過(guò)程的人員而言,存儲(chǔ)過(guò)程是指一組作為單個(gè)代碼單元一起存儲(chǔ)于數(shù)據(jù)庫(kù)中的 T-SQL 語(yǔ)句。您可以使用輸入?yún)?shù)傳入運(yùn)行時(shí)信息,并取回作為結(jié)果集或輸出參數(shù)的數(shù)據(jù)。存儲(chǔ)過(guò)程在首次運(yùn)行時(shí)將被編譯。這將產(chǎn)生一個(gè)執(zhí)行計(jì)劃 - 實(shí)際上是 Microsoft® SQL Server™ 為在存儲(chǔ)過(guò)程中獲取由 T-SQL 指定的結(jié)果而必須采取的步驟的記錄。然后,執(zhí)行計(jì)劃在內(nèi)存中得到緩存,以備以后使用。這樣會(huì)改善存儲(chǔ)過(guò)程的性能,因?yàn)?SQL Server 無(wú)需為確定如何處理代碼而重新分析它,而只需引用緩存的計(jì)劃即可。這個(gè)緩存的計(jì)劃一直可用,直到 SQL Server 重新啟動(dòng),或直到它由于使用率較低而溢出內(nèi)存。
性能
緩存的執(zhí)行計(jì)劃曾使存儲(chǔ)過(guò)程較之查詢(xún)更有性能優(yōu)勢(shì)。但對(duì)于 SQL Server 的幾個(gè)最新版本,執(zhí)行計(jì)劃已針對(duì)所有 T-SQL 批處理進(jìn)行了緩存,而不管它們是否在存儲(chǔ)過(guò)程中。因此,基于此功能的性能已不再是存儲(chǔ)過(guò)程的賣(mài)點(diǎn)。任何使用靜態(tài)語(yǔ)法,且提交頻率足以阻止執(zhí)行計(jì)劃溢出內(nèi)存的 T-SQL 批處理將會(huì)獲得同樣的性能好處。“靜態(tài)”部分是關(guān)鍵;任何更改,即使像添加注釋這樣無(wú)關(guān)緊要的更改,也將導(dǎo)致無(wú)法與緩存的計(jì)劃相匹配,從而將無(wú)法重復(fù)使用計(jì)劃。
但是,當(dāng)存儲(chǔ)過(guò)程可以用于降低網(wǎng)絡(luò)流量時(shí),它們?nèi)匀荒軌蛱峁┬阅芎锰帯D恍柙诰W(wǎng)絡(luò)中發(fā)送 EXECUTE stored_proc_name 語(yǔ)句,而非整個(gè) T-SQL 例程,這可以在復(fù)雜操作中廣泛使用。設(shè)計(jì)良好的存儲(chǔ)過(guò)程可以將客戶(hù)端與服務(wù)器之間的許多往返過(guò)程簡(jiǎn)化為單個(gè)調(diào)用。
此外,使用存儲(chǔ)過(guò)程使您能夠增強(qiáng)對(duì)執(zhí)行計(jì)劃的重復(fù)使用,由此可以通過(guò)使用遠(yuǎn)程過(guò)程調(diào)用 (RPC) 處理服務(wù)器上的存儲(chǔ)過(guò)程而提高性能。使用 StoredProcedure 的 SqlCommand.CommandType 時(shí),存儲(chǔ)過(guò)程通過(guò) RPC 執(zhí)行。RPC 封裝參數(shù)和調(diào)用服務(wù)器端過(guò)程的方式使引擎能夠輕松地找到匹配的執(zhí)行計(jì)劃,并只需插入更新的參數(shù)值。
考慮使用存儲(chǔ)過(guò)程提高性能時(shí),最后要考慮是否要充分利用 T-SQL 的優(yōu)點(diǎn)。請(qǐng)考慮要如何處理數(shù)據(jù)。
• | 是否要使用基于集合的操作,或執(zhí)行 T-SQL 中完全支持的其他操作?那么存儲(chǔ)過(guò)程就是一個(gè)選擇,而內(nèi)聯(lián)查詢(xún)也可以使用。 |
• | 是否嘗試執(zhí)行基于行的操作,或復(fù)雜的字符串處理?那么可能要重新考慮在 T-SQL 中進(jìn)行這種處理,這不包括使用存儲(chǔ)過(guò)程,至少要到 Yukon 發(fā)布并且公共語(yǔ)言運(yùn)行庫(kù) (CLR) 集成可用后,才能使用存儲(chǔ)過(guò)程。 |
可維護(hù)性和抽象
要考慮的另一個(gè)潛在優(yōu)勢(shì)是可維護(hù)性。理想情況下,數(shù)據(jù)庫(kù)架構(gòu)從不更改,業(yè)務(wù)規(guī)則不被修改,但在現(xiàn)實(shí)環(huán)境中,情況則完全不同。既然情況如此,那么如果可以修改存儲(chǔ)過(guò)程以包括新 X、Y 和 Z 表(為支持新的銷(xiāo)售活動(dòng)而添加了這些表)中的數(shù)據(jù),而不是在應(yīng)用程序代碼中的某個(gè)位置更改此信息,則維護(hù)對(duì)您來(lái)說(shuō)可能比較容易。在存儲(chǔ)過(guò)程中更改此信息使得更新對(duì)應(yīng)用程序而言具有透明性 - 您仍然返回相同的銷(xiāo)售信息,即使存儲(chǔ)過(guò)程的內(nèi)部實(shí)現(xiàn)已經(jīng)更改。更新存儲(chǔ)過(guò)程通常比更改、測(cè)試以及重新部署程序集需要較少的時(shí)間和精力。
另外,通過(guò)抽象化實(shí)現(xiàn)并將此代碼保存在存儲(chǔ)過(guò)程中,任何需要訪(fǎng)問(wèn)數(shù)據(jù)的應(yīng)用程序均可以獲取一致的數(shù)據(jù)。您無(wú)需在多個(gè)位置維護(hù)相同的代碼,用戶(hù)便可獲取一致的信息。
在存儲(chǔ)過(guò)程中存儲(chǔ) T-SQL 的另一個(gè)可維護(hù)性?xún)?yōu)點(diǎn)是更好的版本控制。您可以對(duì)創(chuàng)建和修改存儲(chǔ)過(guò)程的腳本進(jìn)行版本控制,就像可以對(duì)任何其他源代碼模塊進(jìn)行版本控制一樣。通過(guò)使用 Microsoft Visual SourceSafe® 或某個(gè)其他源代碼控制工具,您可以輕松地恢復(fù)到或引用舊版本的存儲(chǔ)過(guò)程。
在使用存儲(chǔ)過(guò)程提高可維護(hù)性時(shí)應(yīng)值得注意的一點(diǎn)是,它們無(wú)法阻止您對(duì)架構(gòu)和規(guī)則進(jìn)行所有可能的更改。如果更改范圍大到需要對(duì)輸入存儲(chǔ)過(guò)程的參數(shù)進(jìn)行更改,或者要更改由其返回的數(shù)據(jù),則您仍需要更新程序集中的代碼以添加參數(shù)、更新 GetValue() 調(diào)用,等等。
要注意的另一個(gè)問(wèn)題是,由于存儲(chǔ)過(guò)程將應(yīng)用程序綁定到 SQL Server,因此使用存儲(chǔ)過(guò)程封裝業(yè)務(wù)邏輯將限制應(yīng)用程序的可移植性。如果應(yīng)用程序的可移植性在您的環(huán)境中非常重要,則將業(yè)務(wù)邏輯封裝在不特定于 RDBMS 的中間層中可能是一個(gè)更佳的選擇。
安全性
考慮使用存儲(chǔ)過(guò)程的最終原因是它們可用于增強(qiáng)安全性。
就管理用戶(hù)對(duì)信息的訪(fǎng)問(wèn)而言,通過(guò)向用戶(hù)授予對(duì)存儲(chǔ)過(guò)程(而不是基礎(chǔ)表)的訪(fǎng)問(wèn)權(quán)限,它們可以提供對(duì)特定數(shù)據(jù)的訪(fǎng)問(wèn)。您可以將存儲(chǔ)過(guò)程看成是 SQL Server 視圖(如果您對(duì)它們熟悉的話(huà)),除非存儲(chǔ)過(guò)程接受用戶(hù)的輸入以動(dòng)態(tài)更改顯示的數(shù)據(jù)。
存儲(chǔ)過(guò)程還可以幫助您解決代碼安全問(wèn)題。它們可以防止某些類(lèi)型的 SQL 插入攻擊 - 主要是一些使用運(yùn)算符(如 AND 或 OR)將命令附加到有效輸入?yún)?shù)值的攻擊。在應(yīng)用程序受到攻擊時(shí),存儲(chǔ)過(guò)程還可以隱藏業(yè)務(wù)規(guī)則的實(shí)現(xiàn)。這對(duì)于將此類(lèi)信息視為知識(shí)產(chǎn)權(quán)的公司非常重要。
另外,使用存儲(chǔ)過(guò)程使您可以使用 ADO.NET 中提供的 SqlParameter 類(lèi)指定存儲(chǔ)過(guò)程參數(shù)的數(shù)據(jù)類(lèi)型。這為驗(yàn)證用戶(hù)提供的值類(lèi)型(作為深層次防御性策略的一部分)提供了一個(gè)簡(jiǎn)單方法。在縮小可接受用戶(hù)輸入的范圍方面,參數(shù)在內(nèi)聯(lián)查詢(xún)中與在存儲(chǔ)過(guò)程中一樣有用。
使用存儲(chǔ)過(guò)程增強(qiáng)安全性時(shí)值得注意的是,糟糕的安全性或編碼做法仍然會(huì)使您受到攻擊。對(duì) SQL Server 角色創(chuàng)建和分配如果不加注意將導(dǎo)致人們?cè)L問(wèn)到不應(yīng)看到的數(shù)據(jù)。同時(shí),如果認(rèn)為使用存儲(chǔ)過(guò)程便可防止所有 SQL 插入代碼攻擊(例如,將數(shù)據(jù)操作語(yǔ)言 (DML) 附加到輸入?yún)?shù)),后果將是一樣的。
另外,無(wú)論 T-SQL 位于代碼還是位于存儲(chǔ)過(guò)程中,使用參數(shù)進(jìn)行數(shù)據(jù)類(lèi)型驗(yàn)證都不是萬(wàn)無(wú)一失的。所有用戶(hù)提供的數(shù)據(jù)(尤其是文本數(shù)據(jù))在傳遞到數(shù)據(jù)庫(kù)之前都應(yīng)受到附加的驗(yàn)證。
存儲(chǔ)過(guò)程對(duì)我是否適用?
或許適合吧。讓我們概括一下它們的優(yōu)點(diǎn):
• | 通過(guò)降低網(wǎng)絡(luò)流量提高性能 |
• | 提供單點(diǎn)維護(hù) |
• | 抽象化業(yè)務(wù)規(guī)則,以確保一致性和安全性 |
• | 通過(guò)將某些形式的攻擊降至最低,以增強(qiáng)安全性 |
• | 支持執(zhí)行計(jì)劃重復(fù)使用 |
如果您的環(huán)境允許利用存儲(chǔ)過(guò)程提供的好處(如上所述),強(qiáng)烈建議使用它們。對(duì)于改進(jìn)數(shù)據(jù)在環(huán)境中的處理方式而言,它們提供了一個(gè)很好的工具。另一方面,如果您的環(huán)境中存在可移植性、大量使用非 T-SQL 友好的進(jìn)程或者不穩(wěn)定的數(shù)據(jù)庫(kù)架構(gòu)等削弱這些優(yōu)點(diǎn)的因素,則您可能要考慮其他方法。
另一個(gè)要注意的事項(xiàng)是機(jī)構(gòu)內(nèi)部所擁有的 T-SQL 專(zhuān)業(yè)人員的數(shù)量。您有足夠的 T-SQL 知識(shí)嗎?您愿意學(xué)習(xí)嗎?或者,您有 DBA 或合適的人員幫您編寫(xiě)存儲(chǔ)過(guò)程嗎?掌握的 T-SQL 知識(shí)越多,存儲(chǔ)過(guò)程就會(huì)越好,維護(hù)它們就會(huì)越容易。例如,T-SQL 主要用于基于集合的操作,而不是基于行的操作。依賴(lài)于光標(biāo)(因?yàn)樗鼈兿蚰崾緮?shù)據(jù)集)將導(dǎo)致性能降低。如果您不太了解 T-SQL,請(qǐng)將本文作為一次學(xué)習(xí)機(jī)會(huì)。無(wú)論您將它用在何處,本文介紹的知識(shí)都將改善您的代碼。
因此,如果您認(rèn)為存儲(chǔ)過(guò)程會(huì)為應(yīng)用程序增添特殊的效果,請(qǐng)繼續(xù)閱讀本文。我們將回顧一些簡(jiǎn)化存儲(chǔ)過(guò)程使用的工具,并了解一些創(chuàng)建存儲(chǔ)過(guò)程的最佳做法。
注意事項(xiàng)
如果要開(kāi)始創(chuàng)建與應(yīng)用程序一起使用的存儲(chǔ)過(guò)程,應(yīng)記住下面這些提示,以便兩者正常運(yùn)行并良好地配合工作。
使用 SET NOCOUNT ON
默認(rèn)情況下,存儲(chǔ)過(guò)程將返回過(guò)程中每個(gè)語(yǔ)句影響的行數(shù)。如果不需要在應(yīng)用程序中使用該信息(大多數(shù)應(yīng)用程序并不需要),請(qǐng)?jiān)诖鎯?chǔ)過(guò)程中使用 SET NOCOUNT ON 語(yǔ)句以終止該行為。根據(jù)存儲(chǔ)過(guò)程中包含的影響行的語(yǔ)句的數(shù)量,這將刪除客戶(hù)端和服務(wù)器之間的一個(gè)或多個(gè)往返過(guò)程。盡管這不是大問(wèn)題,但它可以為高流量應(yīng)用程序的性能產(chǎn)生負(fù)面影響。
create procedure test_MyStoredProc @param1 intasset nocount on
不要使用 sp_ prefix
sp_ prefix 是為系統(tǒng)存儲(chǔ)過(guò)程保留的。數(shù)據(jù)庫(kù)引擎將始終首先在主數(shù)據(jù)庫(kù)中查找具有此前綴的存儲(chǔ)過(guò)程。這意味著當(dāng)引擎首先檢查主數(shù)據(jù)庫(kù),然后檢查存儲(chǔ)過(guò)程實(shí)際所在的數(shù)據(jù)庫(kù)時(shí),將需要較長(zhǎng)的時(shí)間才能完成檢查過(guò)程。而且,如果碰巧存在一個(gè)名稱(chēng)相同的系統(tǒng)存儲(chǔ)過(guò)程,則您的過(guò)程根本不會(huì)得到處理。
盡量少用可選參數(shù)
在頻繁使用可選參數(shù)之前,請(qǐng)仔細(xì)考慮。通過(guò)執(zhí)行額外的工作會(huì)很輕易地影響性能,而根據(jù)為任意指定執(zhí)行輸入的參數(shù)集合,這些工作時(shí)不需要的。您可以通過(guò)對(duì)每種可能的參數(shù)組合使用條件編碼來(lái)解決此問(wèn)題,但這相當(dāng)費(fèi)時(shí)并會(huì)增大出錯(cuò)的幾率。
在可能的情況下使用 OUTPUT 參數(shù)
通過(guò)使用 OUTPUT 參數(shù)返回標(biāo)量數(shù)據(jù),可以略微提高速度并節(jié)省少量的處理功率。在應(yīng)用程序需要返回單個(gè)值的情況下,請(qǐng)嘗試此方法,而不要將結(jié)果集具體化。在適當(dāng)?shù)那闆r下,也可以使用 OUTPUT 參數(shù)返回光標(biāo),但是我們將在后續(xù)文章中介紹光標(biāo)處理與基于集合的處理在理論上的分歧。
提供返回值
使用存儲(chǔ)過(guò)程的返回值,將處理狀態(tài)信息返回給進(jìn)行調(diào)用的應(yīng)用程序。在您的開(kāi)發(fā)組中,將一組返回值及其含義標(biāo)準(zhǔn)化,并一致地使用這些值。這會(huì)使得處理調(diào)用應(yīng)用程序中的錯(cuò)誤更加容易,并向最終用戶(hù)提供有關(guān)問(wèn)題的有用信息。
首先使用 DDL,然后使用 DML
將 DML 語(yǔ)句放在數(shù)據(jù)定義語(yǔ)言 (DDL) 語(yǔ)句之后執(zhí)行(此時(shí) DML 將引用 DDL 修改的任意對(duì)象)時(shí),SQL Server 將重新編譯存儲(chǔ)過(guò)程。出現(xiàn)這種情況,是由于為了給 DML 創(chuàng)建計(jì)劃,SQL Server 需要考慮由 DDL 對(duì)該對(duì)象所作的更改。如果留意存儲(chǔ)過(guò)程開(kāi)頭的所有 DDL,則它只需重新編譯一次。如果將 DDL 和 DML 語(yǔ)句混合使用,則將強(qiáng)制存儲(chǔ)過(guò)程多次進(jìn)行重新編譯,這將對(duì)性能造成負(fù)面影響。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="
xmlns:xsi="
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee <!-- 配置spring的監(jiān)聽(tīng)器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
<!-- 開(kāi)啟監(jiān)聽(tīng) -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- 配置OpenSessionInViewFilter,必須在struts2監(jiān)聽(tīng)之前 -->
<!--
<filter>
<filter-name>lazyLoadingFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>lazyLoadingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-->
<!-- 設(shè)置監(jiān)聽(tīng)加載上下文 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern> <!--注意:千萬(wàn)不能寫(xiě)成:*.action ,如果需要:*.action應(yīng)該配置在struts.xml中-->
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>