2009 年 10 月 26 日
數(shù)據(jù)庫系統(tǒng)為用戶提供了多樣的編程接口,以適用于各種應(yīng)用需求。本文闡述了 DB2 中靜態(tài) SQL 和動態(tài) SQL 的區(qū)別和特點,給出兩種 SQL 在不同編程接口下的支持情況和典型應(yīng)用,并通過實際案例,向讀者介紹了選擇靜態(tài)或動態(tài) SQL 及編程接口的原則。
引言
SQL 語言作為標(biāo)準(zhǔn)的查詢語言,幾乎被所有的數(shù)據(jù)庫管理系統(tǒng) (DBMS) 所支持,并成為國際標(biāo)準(zhǔn)。標(biāo)準(zhǔn)的 SQL 語言一般包括三類,即 DDL (Data Definition Language, 數(shù)據(jù)描述語言 ) 、DML (Data Manipulation Language, 數(shù)據(jù)操縱語言 ) 和 DCL(Data Control Language,數(shù)據(jù)控制語言 )。通過這些標(biāo)準(zhǔn)的 SQL 語句,使得各種數(shù)據(jù)庫能以一種較為統(tǒng)一的方式被訪問。
DB2(本文以下專指 DB2 UDB for Linux, Unix 和 Windows 版本)允許用戶通過多種編程接口發(fā)送 SQL 語句到數(shù)據(jù)庫引擎,然后由引擎統(tǒng)一編譯并且運行。SQL 語句從編譯和運行的角度可以分為兩種,靜態(tài) SQL和 動態(tài) SQL,這兩種 SQL 在使用方式、運行機制和性能表現(xiàn)等方面各有特點 :
- 靜態(tài) SQL:靜態(tài) SQL 語句一般用于嵌入式 SQL 應(yīng)用中,在程序運行前,SQL 語句必須是確定的,例如 SQL 語句中涉及的列名和表名必須是存在的。靜態(tài) SQL 語句的編譯是在應(yīng)用程序運行前進行的,編譯的結(jié)果會存儲在數(shù)據(jù)庫內(nèi)部。而后程序運行時,數(shù)據(jù)庫將直接執(zhí)行編譯好的 SQL 語句,降低運行時的開銷。
- 動態(tài) SQL:動態(tài) SQL 語句是在應(yīng)用程序運行時被編譯和執(zhí)行的,例如,使用 DB2 的交互式工具 CLP 訪問數(shù)據(jù)庫時,用戶輸入的 SQL 語句是不確定的,因此 SQL 語句只能被動態(tài)地編譯。動態(tài) SQL 的應(yīng)用較多,常見的 CLI 和 JDBC 應(yīng)用程序都使用動態(tài) SQL。
表 1列舉了靜態(tài) SQL 和動態(tài) SQL 的比較結(jié)果。
表 1. 靜態(tài) SQL 和動態(tài) SQL 的比較
靜態(tài) SQL |
動態(tài) SQL |
SQL 語句直接嵌入到宿主編程語言,程序需要預(yù)編譯處理這些嵌入的 SQL 語句 |
SQL 語句一般作為宿主語言的變量出現(xiàn)。嵌入式動態(tài) SQL 應(yīng)用需要預(yù)編譯,非嵌入式 SQL 應(yīng)用則無需預(yù)編譯 |
SQL 語句在程序被編譯時已知,涉及的數(shù)據(jù)庫對象已存在 |
SQL 語句在程序被編譯時未知,涉及的數(shù)據(jù)庫對象可以是運行時才創(chuàng)建的 |
SQL 語句在程序運行前被編譯 |
SQL 語句在程序運行時被編譯 |
SQL 語句的編譯結(jié)果在 DB2 的目錄 (catalog) 中持久化保存 |
SQL 語句的編譯結(jié)果緩存在數(shù)據(jù)庫的內(nèi)存里 |
運行時僅讀取目錄 (catalog) |
運行時編譯 SQL 語句需對目錄 (catalog) 加鎖 |
SQL 語句的優(yōu)化是根據(jù)編譯時的數(shù)據(jù)庫統(tǒng)計信息進行的,不能完全反映運行時的情況 |
SQL 語句的優(yōu)化是根運行時的數(shù)據(jù)庫統(tǒng)計信息進行的 |
對 SQL 語句所訪問的數(shù)據(jù)對象的權(quán)限檢查是在綁定時進行的 |
對 SQL 語句所訪問的數(shù)據(jù)對象的權(quán)限檢查是在運行時進行的 |
權(quán)限控制的粒度是包(package,一組 SQL 語句的編譯結(jié)果),用戶僅需要訪問包的權(quán)限 |
權(quán)限控制的粒度是 SQL 語句,用戶需要具有訪問 SQL 語句中每個數(shù)據(jù)對象的權(quán)限 |
如果 SQL 語句中的對象被修改,如 DDL 執(zhí)行,整個包都需要重新綁定 |
當(dāng) SQL 語句中的對象被修改時,僅執(zhí)行過的語句在下次運行時需要重新編譯 |
根據(jù)編程方法的不同,DB2 的應(yīng)用程序開還可以分為嵌入式 SQL 編程和非嵌入式編程 :
- 嵌入式 SQL 編程將 SQL 語句嵌入到宿主語言 (host) 的程序中,例如 C/C++ 程序。因為宿主語言不識別 SQL 語句,先要對程序進行預(yù)編譯,把 SQL 語句轉(zhuǎn)變?yōu)閷?DB2 服務(wù)的調(diào)用,并重寫源代碼,最后再使用宿主語言的編譯器對應(yīng)用程序進行編譯。嵌入式 SQL 都需要被綁定到特定的數(shù)據(jù)庫中,可分為嵌入式靜態(tài) SQL 和嵌入式動態(tài) SQL。
- 非嵌入式應(yīng)用程序不需要預(yù)編譯,且方法較多,如 CLI、JDBC、ODBC、ADO.NET 等等,這些方法中都使用動態(tài) SQL。表 2列舉了常見的 DB2 編程接口。
表 2. DB2 的編程接口一覽
編程接口 |
靜態(tài) / 動態(tài) |
是否為嵌入式 |
嵌入式 SQL |
靜態(tài)和動態(tài) |
是 |
DB2 CLI |
動態(tài) |
否 |
SQLJ |
靜態(tài) |
是 |
JDBC |
動態(tài) |
否 |
ADO.NET,OLE DB |
動態(tài) |
否 |
Perl DBI |
動態(tài) |
否 |
PDO(PHP 數(shù)據(jù)對象 ) |
動態(tài) |
否 |
在下面的幾個章節(jié)中,我們將陸續(xù)從使用角度上描述靜態(tài)和動態(tài) SQL 在各種編程接口中的應(yīng)用,并運用一些實例來介紹在具體的場景中如何選擇。
靜態(tài) SQL 應(yīng)用
嵌入式靜態(tài) SQL
無論是嵌入式靜態(tài) SQL 還是嵌入式動態(tài) SQL,都需要先進行預(yù)編譯,并綁定到特定的數(shù)據(jù)庫。DB2 的嵌入式 SQL 應(yīng)用程序支持以下幾種語言:C,C++,COBOL,F(xiàn)ORTRAN 和 REXX?。
對嵌入式靜態(tài) SQL 而言,只能使用編譯時確定的 SQL 語句和訪問編譯時已經(jīng)存在的數(shù)據(jù)庫對象。清單 1是一個查詢表的例子,使用 C 語言 :
清單 1. 嵌入式靜態(tài) SQL 的 C 語言片斷
//test.sqc
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
sqlint32 t_seq = 0;
char t_name[64]={0};
EXEC SQL END DECLARE SECTION;
...
t_seq = 5;
EXEC SQL SELECT c_name INTO :t_name FROM test_tbl WHERE seq=:t_seq;
printf("c_name = %s \n", t_name);
|
使用下面的命令,對上述代碼進行預(yù)編譯和編譯:
清單 2. 嵌入式靜態(tài) SQL 的編譯命令
# 需要先連接數(shù)據(jù)庫
db2 connect to TESTDB
# 使用 PREP 命令對 sqc 源文件進行預(yù)編譯,這將生成 test.c 源文件
db2 PREP test.sqc
# 使用 C 編譯器對 test.c 進行編譯
xlC -q64 -I$DB2PATH/include -g -L$DB2PATH/lib -ldb2 -o test test.c
|
SQLJ
SQLJ 是應(yīng)用于靜態(tài) SQL 的 Java 編程接口。使用 SQLJ 編寫應(yīng)用程序和使用其他的語言接口相似,一個典型的 SQLJ 應(yīng)用程序主要包括以下幾個方面:
- 載入包含 SQLJ 和 JDBC 的 Java 包。
- 定義收發(fā)數(shù)據(jù)的載體變量。
- 連接至數(shù)據(jù)庫,運行相應(yīng)的 SQL 語句并且正確處理錯誤情況,最后從數(shù)據(jù)庫斷開。
清單 3是 SQLJ 中執(zhí)行 SELECT 語句的代碼片斷。
清單 3. 簡單的 SQLJ 程序片斷
// 載入相關(guān)包
import sqlj.runtime.*;
import java.sql.*;
// 連接至數(shù)據(jù)庫
Connection con0 = DriverManager.getConnection(url);
// 執(zhí)行相關(guān)的 SQL 語句
#sql [ctx] iter = {SELECT NAME FROM EMP};
// 得到結(jié)果
while (iter.next()) {
System.out.println(iter.LASTNAME());
}
|
在 SQLJ 應(yīng)用程序中,可以使用 ExecutionContext 類去控制和監(jiān)控 SQL 語句的執(zhí)行,如 清單 4所示。
清單 4. 在 SQLJ 使用 ExecutionContext
// 分配存儲執(zhí)行上下文的變量
ExecutionContext exeCtx=new ExecutionContext();
// 關(guān)聯(lián)變量和要執(zhí)行的語句
#sql [connCtx, exeCtx] {DELETE FROM EMP WHERE SALARY > 10000};
// 獲取結(jié)果
System.out.println("Deleted " + exeCtx.getUpdateCount() + " rows");
|
動態(tài) SQL 應(yīng)用
嵌入式動態(tài) SQL
與嵌入式靜態(tài) SQL 相同,嵌入式動態(tài) SQL 也需要預(yù)編譯。不同的是,嵌入式動態(tài) SQL 將 SQL 語句存放在宿主語言的字符型變量中,這樣的 SQL 語句在預(yù)編譯時是不被處理的,而是被當(dāng)作主機變量對待,直到程序運行時才被編譯執(zhí)行。
得益于動態(tài) SQL 的優(yōu)點,嵌入式動態(tài) SQL 可以處理運行時才確定的 SQL 語句,例如由程序運行時拼接的 SQL 語句。為了處理返回結(jié)果未知的 SELECT 語句,嵌入式動態(tài) SQL 使用 SQLDA(SQL descriptor area) 結(jié)構(gòu)和 DESCRIBE 語句獲取結(jié)果集的結(jié)構(gòu)和屬性。SQLDA 結(jié)構(gòu)如 圖 1所示。HEADER 描述整個結(jié)果集的信息,而每個 SQLVAR 結(jié)構(gòu)描述結(jié)果集中一個字段的信息。
圖 1. SQLDA 結(jié)構(gòu)
清單 5展示了如何使用 SQLDA 結(jié)構(gòu)和 DESCRIBE 語句處理 SELECT 語句。
清單 5. 使用 SQLDA 結(jié)構(gòu)和 DESCRIBE 語句的偽代碼
//test1.sqc
// 聲明兩個 SQLDA 指針,minsqlda 將是一個最小的 SQLDA 結(jié)構(gòu),用于 PREPARE 語句,
// 此時結(jié)果集的字段數(shù)量未知,所以只需一個最小的 SQLDA,即包含 HEADER 和一個 SQLVAR
struct sqlda * minsqlda = new sqlda;
struct sqlda * fulsqlda = NULL;
strcpy(hostVarStmt, "SELECT name FROM TEST_TBL");
// PREPARE 將填寫 minsqlda 的 header,sqldabc 為 SQLDA 總長度,sqln 為 SQLVAR 數(shù)量,即字段數(shù)量
EXEC SQL PREPARE STMT INTO :*minsqlda FROM :hostVarStmt;
// 根據(jù)從 minsqlda 中獲取的長度,分配完整的 SQLDA 結(jié)構(gòu) fulsqlda,其中將包括合適數(shù)量的 SQLVAR 結(jié)構(gòu)
fulsqlda = (struct sqlda *)malloc(SQLDASIZE(minsqlda->sqln));
// 使用 DESCRIBE 語句,獲取結(jié)果集中每個字段的描述信息,包括各字段的類型 (sqltype) 和長度 (sqllen)
EXEC SQL DESCRIBE STMT INTO :fulsqlda;
Loop
{
// 根據(jù)每個字段的長度,分配內(nèi)存,將地址存儲在對應(yīng) SQLVAR 的 sqldata 中
}
// 聲明游標(biāo)
EXEC SQL DECLARE c1 CURSOR FOR STMT;
EXEC SQL OPEN c1;
// 讀取記錄,記錄中每個字段的內(nèi)容將寫入 fulsqlda 中對應(yīng) SQLVAR 結(jié)構(gòu)的 sqldata 指向的內(nèi)存
EXEC SQL FETCH c1 USING DESCRIPTOR :*fulsqlda;
// 循環(huán)讀取所有記錄
while (sqlca.sqlcode != 100)
{
EXEC SQL FETCH c1 USING DESCRIPTOR :*fulsqlda;
}
EXEC SQL CLOSE c1;
|
DB2 CLI
DB2 CLI(Call Level Interface)基于微軟的 ODBC(Open Database Connectivity)標(biāo)準(zhǔn),同時也增加了 DB2 特有的功能。它允許開發(fā)人員使用 C/C++ 語言訪問 DB2 并通過函數(shù)調(diào)用將動態(tài) SQL 語句傳遞給 DB2。DB2 CLI 一方面在 ODBC 的環(huán)境中作為 ODBC 驅(qū)動被 ODBC 管理器加載,另一方面,應(yīng)用程序也可以直接使用 DB2 CLI API,此時具有更好的性能。清單 6展示了 CLI 如何執(zhí)行一個 DELETE 語句。
清單 6. CLI 應(yīng)用程序片斷
/* SQL statements to be executed */
SQLCHAR * stmt1 = (SQLCHAR *)"delete from test1 where col1 = 5";
/* directly execute statement 1 */
cliRC = SQLExecDirect(hstmt, stmt1, SQL_NTS);
|
對一個返回結(jié)果未知的 SELECT 查詢語句,需要使用相關(guān)的 CLI API 函數(shù)動態(tài)地獲取對結(jié)果集的描述,并取回數(shù)據(jù)。圖 2展示了這個處理過程。
圖 2. DB2 CLI 應(yīng)用程序處理 SELECT 語句流程
與嵌入式動態(tài) SQL 應(yīng)用相比,CLI 程序的靈活性更強。表 3列舉了 CLI 應(yīng)用程序和嵌入式動態(tài) SQL 應(yīng)用程序的比較。
表 3. CLI 應(yīng)用程序和嵌入式動態(tài) SQL 應(yīng)用程序的比較
CLI |
嵌入式動態(tài) SQL |
DB2 CLI 應(yīng)用程序使用 API 函數(shù)發(fā)送 SQL 語句,應(yīng)用程序的編譯、連接和運行獨立于特定數(shù)據(jù)庫,即無需預(yù)編譯,也不需要綁定到某個數(shù)據(jù)庫實例。 |
嵌入式動態(tài) SQL 應(yīng)用程序需要預(yù)編譯,并且需要綁定到特定的數(shù)據(jù)庫實例。 |
CLI 提供的滾動游標(biāo)(scroll cursor)支持前、后向移動一行或者多行記錄,而移動的起點可以是第一行、最后一行或者之前存儲的位置。 |
只支持順序前向讀取游標(biāo),并使用 FETCH 語句取得記錄。 |
可以獲取存儲過程調(diào)用返回的結(jié)果集。并支持多種 DB2 服務(wù)器。 |
可以獲取存儲過程的輸出型或輸入 - 輸出型參數(shù)的值,但不能獲取存儲過程返回的結(jié)果集。 |
只支持 C/C++ 語言。 |
支持 C/C++, FORTRAN、COBOL 和 Java(SQLJ)。 |
使用 CLI API 函數(shù) SQLDescribeCol()、SQLAttribute() 描述未知 SQL 語句結(jié)果集的信息,包括結(jié)果集字段長度、類型、精度等信息。 |
使用 SQLDA 結(jié)構(gòu)和 DESCRIBE 語句獲取未知 SQL 語句結(jié)果集的字段列表,包括類型、長度等信息。 |
JDBC
JDBC 是 Java 編程語言訪問關(guān)系型數(shù)據(jù)庫的工業(yè)標(biāo)準(zhǔn),類似于 ODBC,為訪問基于 SQL 的數(shù)據(jù)庫提供了一組調(diào)用級的 API。在 JDBC 規(guī)范中,存在 4 種類型的 JDBC 驅(qū)動,DB2 LUW V9.7 中支持 Type 2 和 Type 4 兩種類型。更多關(guān)于 JDBC 的信息可參考 DB2 UDB for Linux, UNIX 和 Windows 中的 Java 開發(fā)概述(參見 參考資源部分)。
JDBC 以 Java 包的形式提供了一組接口和類,用來連接數(shù)據(jù)庫和執(zhí)行 SQL 語句,這里的 SQL 語句也是動態(tài) SQL,無須預(yù)編譯和數(shù)據(jù)庫綁定。清單 7所示為 JDBC 程序片斷。
清單 7. JDBC 應(yīng)用程序片斷
try{
stmt = con.prepareCall("select * from table1");
stmt.execute();
rs = stmt.getResultSet();
while (rs!=null && rs.next()) {
System.out.println("output: = " + rs.getInt(1));
}
}catch(SQLException sqle) {
System.out.println("Error, SQLCODE = " + sqle.getSQLState());
con.rollback();
}
|
除了編程語言和運行基礎(chǔ)架構(gòu)的不同,JDBC 應(yīng)用和 CLI 應(yīng)用具有很多相似的特性,例如它們都支持后向游標(biāo),分布式事務(wù)等。
ADO.NET 和 OLE DB
ADO.NET 是 Microsoft .NET Framework 基礎(chǔ)類庫的一部分,提供了訪問關(guān)系型數(shù)據(jù)庫系統(tǒng)和其他數(shù)據(jù)源的能力。ADO.NET 主要包括兩個部分:DataSet 和 DataProvider。使用 ADO.NET,有三種 DataProvider 可以用來訪問 DB2:
- OLE DB .NET Data Provider 和 ODBC .NET Data Provider 是兩種橋接式 provider,它們將 ADO.NET 請求轉(zhuǎn)換為對 IBM OLE DB Provider 或 IBM ODBC Driver 的請求。
- DB2 .NET Data Provider 是訪問 DB2 時推薦使用的 .NET provider,由于沒有額外的 OLE DB 或 ODBC 層,它具有更好的性能。
OLE DB 是一種較早出現(xiàn)的數(shù)據(jù)訪問模型,它基于 Microsoft? 的 COM 技術(shù),提供了訪問不同信息源的統(tǒng)一方法。OLE DB 定義了 OLE DB 消費者和提供者,OLE DB 消費者可以通過 IBM OLE DB Provider for DB2 訪問 DB2 中的數(shù)據(jù)。使用 OLE DB 訪問 DB2 的應(yīng)用程序可能包括 Microsoft? Visual Studio C++ 應(yīng)用,Microsoft Visual Basic 應(yīng)用,ATL 應(yīng)用等。
其他應(yīng)用程序開發(fā)接口
Perl 程序員可以使用 Perl 數(shù)據(jù)庫接口 DBI 來訪問 DB2。IBM 提供的 DBI 驅(qū)動為 IBM?DB2?Database Driver for Perl DBI (the DBD::DB2 driver)。Perl DBI 同樣使用動態(tài) SQL,而且 Perl DBI 的接口與 CLI 和 JDBC 很相似,易于使用。
PHP 在 Web 應(yīng)用開發(fā)領(lǐng)域一直占據(jù)很大份額,IBM 提供了下面兩種 PHP 擴展以訪問 DB2 數(shù)據(jù)庫:
- ibm_db2,是一種過程化的應(yīng)用編程接口,與 PHP 應(yīng)用一起編譯,提供一系列的 PHP 函數(shù)來訪問數(shù)據(jù)庫。
- pdo_ibm,是 IBM 提供的 PHP Data Objects (PDO) 驅(qū)動。
此外,IBM 對 Python,Ruby on Rails 等編程語言都提供了相應(yīng)的 DB2 訪問支持。這些開發(fā)接口同樣都使用動態(tài) SQL。
應(yīng)用場景以及如何選擇
本節(jié)將結(jié)合幾個應(yīng)用場景來介紹如何選擇 DB2 編程接口以及靜態(tài) / 動態(tài) SQL。
場景 1
銀行中賬目統(tǒng)計系統(tǒng)比較穩(wěn)定,一般運行在一個特定的數(shù)據(jù)庫中,其目的是整合業(yè)務(wù)數(shù)據(jù)庫上數(shù)據(jù),并通過分析數(shù)據(jù)得到一些相關(guān)的統(tǒng)計信息。這樣的系統(tǒng)具有以下一些特點 :
- 穩(wěn)定,系統(tǒng)邏輯不會有什么變化,訪問固定的數(shù)據(jù)庫以及表。
- 定時運行,賬目統(tǒng)計信息通常需要在一段時間內(nèi)進行整合。
- 數(shù)據(jù)量比較大,對性能要求較高。
針對這些特點,建議使用主要由靜態(tài) SQL 語句組成的應(yīng)用程序,這樣該系統(tǒng)在建立的時候會被編譯,然后相關(guān)的編譯信息會被存儲到數(shù)據(jù)庫里,在以后的運行過程中避免重復(fù)編譯,同時,這種應(yīng)用由于結(jié)構(gòu)簡單使得其很容易維護。當(dāng)然,由于系統(tǒng)的數(shù)據(jù)變化較快,而且數(shù)據(jù)量很大,所以建議定時重新編譯程序,使得數(shù)據(jù)庫對每條 SQL 語句可以選擇最優(yōu)的運行方式。
場景 2
考慮電信運營商對用戶話單的計費場景,圖 3顯示了一個電信運行系統(tǒng)結(jié)構(gòu)圖。業(yè)務(wù)系統(tǒng)產(chǎn)生的各種話單會集中存放在一個關(guān)系型數(shù)據(jù)庫中,該數(shù)據(jù)庫可能位于大規(guī)模的高可靠性服務(wù)器。而計費程序則往往作為一個單獨的應(yīng)用部署在其他規(guī)模較小的 UNIX 服務(wù)器上,并作為守護程序或者批處理程序運行。另外,很多業(yè)務(wù)規(guī)則例如計費標(biāo)準(zhǔn)可能存放在單獨得小型數(shù)據(jù)庫系統(tǒng)中。
圖 3. 電信運營系統(tǒng)結(jié)構(gòu)示意圖
計費程序的工作主要包括:從話單數(shù)據(jù)庫讀新話單,從業(yè)務(wù)配置數(shù)據(jù)庫讀取計費標(biāo)準(zhǔn),計算話單的費用和優(yōu)惠,將計費完畢的話單寫回話單數(shù)據(jù)庫。
由于計費標(biāo)準(zhǔn)的選擇經(jīng)常和日期等變化的信息相關(guān),程序中會存在一些不固定的 SQL 語句,因此靜態(tài) SQL 應(yīng)用并不適用。另外,除了訪問結(jié)構(gòu)穩(wěn)定的話單數(shù)據(jù)庫,計費程序也需要訪問一些變化概率較大的小型數(shù)據(jù)庫,例如計費標(biāo)準(zhǔn)可能會因為運營商營銷策略的調(diào)整而發(fā)生變化。如果使用嵌入式 SQL,就必須將應(yīng)用程序和數(shù)據(jù)庫進行綁定,這將失去靈活性。最后,為了快速對大量的話單進行計費,計費程序?qū)π阅芤灿休^高要求,所以 CLI 應(yīng)用程序比 JDBC 應(yīng)用更適合計費程序。
場景 3
在基于 BS 結(jié)構(gòu)的電子商務(wù)應(yīng)用中,瀏覽器、應(yīng)用服務(wù)器(包括 Web 服務(wù)器)和數(shù)據(jù)庫構(gòu)成了系統(tǒng)的三個要素。數(shù)據(jù)庫為電子商務(wù)提供了事務(wù)管理、數(shù)據(jù)持久化、安全認證、聯(lián)機備份等各方面的支持,是電子商務(wù)系統(tǒng)中的關(guān)鍵部分。圖 4顯示了一個簡單的電子商務(wù)系統(tǒng)結(jié)構(gòu)示意圖。
圖 4. 簡單的電子商務(wù)系統(tǒng)結(jié)構(gòu)示意圖
在電子商務(wù)系統(tǒng)的實現(xiàn)中,數(shù)據(jù)庫訪問接口的選擇很大程度上依賴于所選擇的應(yīng)用集成方案。例如傳統(tǒng)的 J2EE 應(yīng)用中使用 JDBC 實現(xiàn)數(shù)據(jù)庫訪問。又如開源框架 STRUTS,SPRING 和 HIBERNATE,由 HIBERNATE 完成對 JDBC 的封裝,提供對數(shù)據(jù)庫的訪問能力?;?PHP 開發(fā)的 Web 應(yīng)用程序同樣非常流行,如果選擇 PHP 作為開發(fā)語言,那么使用 PDO(PHP Data Objects)和 IBM 提供的 pdo_ibm 驅(qū)動即可訪問 DB2 數(shù)據(jù)庫。對基于 .Net 框架開發(fā)的 Web 應(yīng)用而言,ADO.NET 則是最合適的數(shù)據(jù)庫訪問接口。
靜態(tài) SQL 和動態(tài) SQL 的選擇原則
在以下情況下,適合選用靜態(tài) SQL:
- 程序需要處理 SQL 語句頻率高,壓力較大
- SQL 語句較為簡單且已知不變
- SQL 語句訪問的數(shù)據(jù)庫對象變化很少
- 程序使用的 SQL 語句可以統(tǒng)一認證權(quán)限
- 同一條 SQL 語句重復(fù)執(zhí)行的次數(shù)很少
- 很少運行 RUNSTATS 更新統(tǒng)計信息
在以下情況下,更適合選用動態(tài) SQL:
- SQL 語句在應(yīng)用程序執(zhí)行時才生成
- SQL 語句訪問的對象在程序運行前不存在
- 希望 SQL 語句根據(jù)運行時的數(shù)據(jù)庫統(tǒng)計信息進行最好的優(yōu)化
- 在程序運行中可能更改 SQL 語句的編譯環(huán)境,如配置參數(shù)和特殊寄存器的值
- 程序運行時,同時有較多 DDL 語句執(zhí)行
- 選用特定的應(yīng)用程序框架,例如場景 3 中的電子商務(wù)案例
當(dāng)然,所有的原則都是經(jīng)驗性的,真正的選擇還取決于應(yīng)用的實際情況。在時間允許的情況下,對各種選擇進行比較測試也是可以考慮的方法。
|