第05章 關(guān)系數(shù)據(jù)庫(kù)編程基礎(chǔ)_第1頁(yè)
第05章 關(guān)系數(shù)據(jù)庫(kù)編程基礎(chǔ)_第2頁(yè)
第05章 關(guān)系數(shù)據(jù)庫(kù)編程基礎(chǔ)_第3頁(yè)
第05章 關(guān)系數(shù)據(jù)庫(kù)編程基礎(chǔ)_第4頁(yè)
第05章 關(guān)系數(shù)據(jù)庫(kù)編程基礎(chǔ)_第5頁(yè)
已閱讀5頁(yè),還剩124頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第5章關(guān)系數(shù)據(jù)庫(kù)編程基礎(chǔ)本章要點(diǎn)嵌入式SQL的實(shí)現(xiàn)方式、使用規(guī)定及使用技術(shù)面向?qū)ο髴?yīng)用程序訪問數(shù)據(jù)庫(kù)的常用接口ODBCJDBCADO.NETSQLServer的存儲(chǔ)過程SQLServer的觸發(fā)器5.1應(yīng)用程序訪問數(shù)據(jù)庫(kù)SQL語(yǔ)言提供了兩種不同的使用方式0201交互式SQL嵌入式SQL在終端交互方式下直接運(yùn)行將SQL語(yǔ)句嵌入到其他程序設(shè)計(jì)語(yǔ)言程序的源代碼中SQL語(yǔ)言提供了兩種不同的使用方式嵌入SQL語(yǔ)句的高級(jí)語(yǔ)言稱為主語(yǔ)言或宿主語(yǔ)言。將SQL語(yǔ)言嵌入到某種高級(jí)語(yǔ)言中使用,利用高級(jí)語(yǔ)言的過程性結(jié)構(gòu)彌補(bǔ)SQL語(yǔ)言在實(shí)現(xiàn)復(fù)雜應(yīng)用方面的不足。SQL語(yǔ)句負(fù)責(zé)對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的提取及操作,它所提取的數(shù)據(jù)提交給程序,程序中其他語(yǔ)句負(fù)責(zé)數(shù)據(jù)的處理和傳遞。嵌入式SQL:通常采用專用的SQL預(yù)編譯程序?qū)⑶度氲腟QL語(yǔ)句轉(zhuǎn)換為能被程序設(shè)計(jì)語(yǔ)言的編譯器識(shí)別的函數(shù)調(diào)用,然后程序設(shè)計(jì)語(yǔ)言的編譯器將源代碼編譯為可執(zhí)行程序。應(yīng)用程序編程接口(API):通過API的調(diào)用,可以將SQL語(yǔ)句傳遞到DBMS,并用API調(diào)用返回結(jié)果。這種方法不需要專用的SQL預(yù)編譯程序。應(yīng)用程序可以通過嵌入式SQL或應(yīng)用程序編程接口(API)實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的訪問。5.1.1嵌入式SQLSQL語(yǔ)言是基于關(guān)系數(shù)據(jù)模型的語(yǔ)言,而高級(jí)語(yǔ)言是基于整數(shù)、實(shí)數(shù)、字符、數(shù)組等數(shù)據(jù)類型的語(yǔ)言,因此兩者之間有很大差別。例如,SQL語(yǔ)句不能直接使用指針、數(shù)組等數(shù)據(jù)結(jié)構(gòu),而高級(jí)語(yǔ)言一般不能直接進(jìn)行集合運(yùn)算。為了能在宿主語(yǔ)言的程序中嵌入SQL語(yǔ)句,嵌入式SQL必須解決一些問題如何將嵌有SQL的宿主語(yǔ)言程序編譯成可執(zhí)行碼宿主語(yǔ)言和數(shù)據(jù)庫(kù)管理系統(tǒng)之間如何傳遞數(shù)據(jù)和信息如何協(xié)調(diào)SQL的集合處理方式與宿主語(yǔ)言的單記錄處理方式等。5.1.1嵌入式SQL雖然在程序設(shè)計(jì)的環(huán)境下,SQL語(yǔ)句要做某些必要的擴(kuò)充,但嵌入式SQL和交互式SQL的大部分語(yǔ)法是相同的。1.在宿主語(yǔ)言中標(biāo)識(shí)SQL語(yǔ)句在嵌入式SQL中,為了使預(yù)處理程序能夠區(qū)分SQL語(yǔ)句與主語(yǔ)言語(yǔ)句,所有SQL語(yǔ)句都必須加前綴“EXECSQL”和SQL語(yǔ)句的結(jié)束標(biāo)志。ESQL/C的SQL語(yǔ)句結(jié)束標(biāo)志是分號(hào),一般格式如下:

EXECSQL<SQL語(yǔ)句>;連接到SQLServer在ESQL/C中,連接到SQLServer使用CONNECTTO語(yǔ)句,語(yǔ)法如下:

CONNECTTO<服務(wù)器名>.<數(shù)據(jù)庫(kù)名><連接的名稱>USER<登錄名>.<登錄密碼>使用另外一個(gè)連接:SETCONNECTION<連接的名稱>關(guān)閉與數(shù)據(jù)的連接用DISCONNECT語(yǔ)句,語(yǔ)法如下DISCONNECT<連接的名稱>|ALL|CURRENT連接到SQLServer【例5.1】連接服務(wù)器myServer上數(shù)據(jù)庫(kù)名為SaleProduct和test的SQLServer數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)登錄名為sa,密碼為123456,然后分別關(guān)閉它們。EXECSQLCONNECTTOmyServer.SaleProductAScon1USERsa.123456;EXECSQLCONNECTTOmyServer.testAScon2USERsa.123456;EXECSQLDISCONNECTcon1EXECSQLDISCONNECTcon2【例5.2】建立基本表Customer。EXECSQLCREATETABLECustomer(custIDvarchar(5)PRIMARYKEY,custNamevarchar(20)NOTNULLUNIQUE,custCityVARCHAR(10),custPhoneVARCHAR(13));【例5.3】刪除基本表Customer。EXECSQLDROPTABLECustomer;2.數(shù)據(jù)庫(kù)工作單元與宿主程序工作單元之間的通信主變量:在嵌入式SQL語(yǔ)句中引用宿主語(yǔ)言說(shuō)明的程序變量。SQL與C之間數(shù)據(jù)的傳送可以通過主變量實(shí)現(xiàn)。在SQL語(yǔ)句中引用主變量時(shí),為了區(qū)別數(shù)據(jù)庫(kù)變量,主變量前須加“:”。在宿主語(yǔ)言語(yǔ)句中,主變量可與其它變量一樣使用,不須加冒號(hào)。2.數(shù)據(jù)庫(kù)工作單元與宿主程序工作單元之間的通信程序中的主變量都應(yīng)在程序說(shuō)明部分使用DECLARE語(yǔ)句加以聲明。一般在BEGINDECLARESECTION和ENDDECLARESECTION之間聲明主變量。需要注意的是,在ESQL/C中關(guān)鍵字和SQL語(yǔ)句都是不區(qū)分大小寫的,但是對(duì)于宿主變量的大小寫敏感?!纠?.4】在商品銷售管理數(shù)據(jù)庫(kù)SaleProduct中,查詢903號(hào)客戶的名稱和電話號(hào)碼,分別將其存儲(chǔ)到宿主變量xCustName,xCustPhone中。EXECSQLBEGINDECLARESECTION;/*說(shuō)明語(yǔ)句開頭*/charxCustID[5];charxCustName[20];charxCustCity[10];charxCustPhone[13];EXECSQLENDDECLARESECTION;/*說(shuō)明語(yǔ)句結(jié)束*/EXECSQLSELECTcustName,custPhoneINTO:xCustName,:xCustPhone

FROMCustomerWHEREcustID='903';【例5.5】在商品銷售管理數(shù)據(jù)庫(kù)SaleProduct中,向Customer表插入一個(gè)元組,元組的各分量值分別來(lái)自宿主變量xCustID、xCustName、xCustPhone。EXECSQLINSERTINTOCustomer(custID,custName,custPhone)VALUES(:xCustID,:xCustName,:xCustPhone);SQL通信區(qū)(SQLCA)SQL語(yǔ)句執(zhí)行后,數(shù)據(jù)庫(kù)管理系統(tǒng)需要反饋給應(yīng)用程序一些狀態(tài)信息,包括描述系統(tǒng)當(dāng)前工作狀態(tài)和運(yùn)行環(huán)境的各種數(shù)據(jù)。這些信息被送到SQL通信區(qū)(SQLCA)。SQLCA是一個(gè)含有錯(cuò)誤變量和狀態(tài)指示符的數(shù)據(jù)結(jié)構(gòu),使用語(yǔ)句EXECSQLINCLUDESQLCA加以定義,它是全局變量。SQLCA.SQLCODE:它是一個(gè)整數(shù),用于DBMS向應(yīng)用程序報(bào)告SQL語(yǔ)句的執(zhí)行情況。SQLCODE>0,表示SQL已執(zhí)行,但有異常SQLCODE<0,表示SQL沒有執(zhí)行,有錯(cuò)誤SQLCODE=0,表示執(zhí)行成功,無(wú)異常3.SQL的集合處理方式與宿主語(yǔ)言單記錄處理方式之間的轉(zhuǎn)換嵌入式SQL引入游標(biāo)機(jī)制,把集合操作轉(zhuǎn)換成單記錄方式。游標(biāo)是系統(tǒng)為用戶開設(shè)的一個(gè)數(shù)據(jù)緩沖區(qū),存放SQL語(yǔ)句的執(zhí)行結(jié)果。每個(gè)游標(biāo)區(qū)都有一個(gè)名字,用戶可以通過游標(biāo)逐一獲取記錄,并將其賦給主變量,交由主語(yǔ)言進(jìn)一步處理。3.SQL的集合處理方式與宿主語(yǔ)言單記錄處理方式之間的轉(zhuǎn)換游標(biāo)分為靜態(tài)游標(biāo)和動(dòng)態(tài)游標(biāo)靜態(tài)游標(biāo)包含完整的SQL語(yǔ)句靜態(tài)游標(biāo)可以包含宿主變量,當(dāng)打開它時(shí),宿主變量就被讀到SQL語(yǔ)句中,形成一個(gè)完整的SQL語(yǔ)句。動(dòng)態(tài)游標(biāo)則需要在運(yùn)行時(shí)指定參數(shù)。動(dòng)態(tài)游標(biāo)中的參數(shù)用?標(biāo)記符來(lái)指定,當(dāng)打開游標(biāo)時(shí),根據(jù)提供的?標(biāo)記符代碼的數(shù)據(jù)來(lái)構(gòu)造SQL語(yǔ)句。3.SQL的集合處理方式與宿主語(yǔ)言單記錄處理方式之間的轉(zhuǎn)換在使用游標(biāo)之前必須要定義游標(biāo),定義游標(biāo)語(yǔ)法如下:

DECLARE<游標(biāo)名稱>CURSORFOR<SELECT語(yǔ)句>

執(zhí)行定義游標(biāo)語(yǔ)句時(shí),不會(huì)執(zhí)行其中的SELECT語(yǔ)句。打開游標(biāo)使用OPEN語(yǔ)句,此時(shí)執(zhí)行游標(biāo)定義中的SELECT語(yǔ)句,同時(shí)游標(biāo)緩沖區(qū)中含有SELECT語(yǔ)句執(zhí)行后返回的所有記錄,游標(biāo)處于活動(dòng)狀態(tài),其指針指向游標(biāo)區(qū)第一行記錄之前。3.SQL的集合處理方式與宿主語(yǔ)言單記錄處理方式之間的轉(zhuǎn)換使用FETCH語(yǔ)句推進(jìn)游標(biāo)。FETCH語(yǔ)句使游標(biāo)指針向前推進(jìn)一行,并把當(dāng)前記錄讀出,放到指定的宿主變量中。FETCH語(yǔ)句常置于主語(yǔ)言程序的循環(huán)結(jié)構(gòu)中,利用循環(huán)逐一處理游標(biāo)中的多條記錄。對(duì)于打開的游標(biāo),可以用UPDATE語(yǔ)句來(lái)更新當(dāng)前記錄,DELETE語(yǔ)句來(lái)刪除當(dāng)前記錄。此時(shí),使用子句“WHERECURRENTOF<游標(biāo)名>”獲取當(dāng)前記錄。3.SQL的集合處理方式與宿主語(yǔ)言單記錄處理方式之間的轉(zhuǎn)換游標(biāo)使用完后,用CLOSE語(yǔ)句來(lái)關(guān)閉它。關(guān)閉游標(biāo),使它不再和原來(lái)的查詢結(jié)果相聯(lián)系,同時(shí)釋放游標(biāo)占用的資源。【例5.6】在商品銷售管理數(shù)據(jù)庫(kù)SaleProduct中,返回Customer表中的所有記錄,并輸出這些信息到屏幕上。EXECSQLDECLAREC1CURSORFORSELECTcustID,custName,custCity,custPhoneFROMCustomer;EXECSQLOPENC1;while(SQLCODE==0){EXECSQLFETCHC1INTO:xCustID,:xCustName,:xCustCity,:xCustPhone;printf("%s,%s,%s,%s",xCustID,xCustName,xCustCity,xCustPhone);}EXECSQLCLOSEC1;

/*關(guān)閉游標(biāo)*/【例5.7】在商品銷售管理數(shù)據(jù)庫(kù)SaleProduct中,定義一個(gè)動(dòng)態(tài)游標(biāo),查詢名稱為“張松林”的客戶,返回其客戶編號(hào)。EXECSQLBEGINDECLARESECTION;CHARSQLCommand[]="SELECTcustIDFROMCustomerWHEREcustName=?";CHARxCustName[]="張松林";CHARxCustID[5];EXECSQLENDDECLARESECTION;EXECSQLDECLAREC2CURSORFORSELECT_STATEMENT;EXECSQLPREPARESELECT_STATEMENTFROM:SQLCommand;EXECSQLOPENC2USING:xCustName;EXECSQLFETCHC2INTO:xCustSID;EXECSQLCLOSEC2;

嵌入式SQL有兩種主要的形式0201靜態(tài)的SQL動(dòng)態(tài)的SQL

編寫程序時(shí)要定義完整的SQL語(yǔ)句,語(yǔ)句中主變量的個(gè)數(shù)與數(shù)據(jù)類型在預(yù)編譯時(shí)都是確定的,只有主變量的值是程序運(yùn)行過程中動(dòng)態(tài)輸入的。

SQL語(yǔ)句可以被應(yīng)用程序在運(yùn)行時(shí)構(gòu)造。需要在運(yùn)行時(shí)指定條件變量,在程序運(yùn)行過程中臨時(shí)“組裝”SQL語(yǔ)句。在預(yù)編譯時(shí)SQL語(yǔ)句的正文、主變量個(gè)數(shù)、主變量的數(shù)據(jù)類型、SQL語(yǔ)句中引用的數(shù)據(jù)庫(kù)對(duì)象(列、索引、基本表、視圖等)等信息可以不確定。5.1.4動(dòng)態(tài)SQL語(yǔ)句ESQL/C提供了處理在編譯時(shí)未知的SQL語(yǔ)句的手段。動(dòng)態(tài)SQL中使用參數(shù)代替了宿主變量,這些參數(shù)可以嵌入在SQL語(yǔ)句中,并且在以后被值替換。5.1.4動(dòng)態(tài)SQL語(yǔ)句動(dòng)態(tài)SQL語(yǔ)句的說(shuō)明與執(zhí)行分為兩步。第一步,使用PREPARE語(yǔ)句準(zhǔn)備SQL,并且在必要時(shí)建立一個(gè)程序計(jì)劃;

PREPARE語(yǔ)句將一字符串解釋成一組SQL語(yǔ)句,并賦給它一個(gè)語(yǔ)句標(biāo)識(shí)符,以后的動(dòng)態(tài)管理語(yǔ)句通過語(yǔ)句標(biāo)識(shí)來(lái)引用這組SQL語(yǔ)句。第二步,用EXECUTE語(yǔ)句或定義游標(biāo)來(lái)執(zhí)行被預(yù)備好的SQL語(yǔ)句。5.1.4動(dòng)態(tài)SQL語(yǔ)句PREPARE語(yǔ)句的一般形式為:

PREPARE<語(yǔ)句標(biāo)識(shí)名>FROM<SQL語(yǔ)句>;或

PREPARE<語(yǔ)句標(biāo)識(shí)名>FROM:<宿主變量>;EXECUTE語(yǔ)句的功能是運(yùn)行與其語(yǔ)句標(biāo)識(shí)符對(duì)應(yīng)的事先準(zhǔn)備好的SQL語(yǔ)句,其一般形式為:EXECUTE<被預(yù)備好的語(yǔ)句標(biāo)識(shí)名>[USING<宿主變量列表>];【例5.8】構(gòu)造一個(gè)動(dòng)態(tài)SQL語(yǔ)句,插入一條記錄到Customer表。EXECSQLBEGINDECLARESECTIONCHARstmtcomm[]="INSERTINTOCustomer(custID,custName)values(?,?)";CHARxCustID[5];CHARxCustName[20];EXECSQLENDDECLARESECTION/*提示用戶輸入數(shù)據(jù)*/printf("輸入客戶編號(hào):");scanf("%s",xCustID);printf("輸入客戶名稱:");scanf("%s",xCustName);EXECSQLPREPAREstmtFROM:stmtcomm;EXECSQLEXECUTEstmtUSING:xCustID,:xCustName;5.1.2DAO和OLEDB第四代開發(fā)工具或語(yǔ)言一般都是面向?qū)ο蟮?,通常借助于?shù)據(jù)庫(kù)操作組件或?qū)ο髠鬟fSQL命令來(lái)操作數(shù)據(jù)庫(kù)。DAO(DataAccessObject,數(shù)據(jù)訪問對(duì)象)是一種應(yīng)用程序編程接口,是微軟的第一個(gè)面向?qū)ο蟮臄?shù)據(jù)庫(kù)接口。DAO體現(xiàn)了面向?qū)ο蟮乃枷?,它將?shù)據(jù)的值作為屬性,數(shù)據(jù)的查詢作為方法,數(shù)據(jù)值的變化作為事件,完全封裝在DAO對(duì)象中。它提供了完成管理關(guān)系數(shù)據(jù)庫(kù)所需的全部操作的屬性和方法,包括創(chuàng)建數(shù)據(jù)庫(kù),定義表、字段和索引,建立表間的關(guān)系,更新和查詢數(shù)據(jù)庫(kù)等工具。5.1.2DAO和OLEDB隨著數(shù)據(jù)源日益復(fù)雜化,應(yīng)用程序很可能需要從不同的數(shù)據(jù)源取得數(shù)據(jù),加以處理,再把處理過的數(shù)據(jù)輸出到另外一個(gè)數(shù)據(jù)源中。標(biāo)準(zhǔn)的關(guān)系型數(shù)據(jù)庫(kù)中的數(shù)據(jù)郵件數(shù)據(jù)Excel文件Web上的文本或圖形5.1.2DAO和OLEDBMicrosoft為了讓應(yīng)用程序能夠以統(tǒng)一的方式存取各種不同的數(shù)據(jù)源,在1997年提出了UDA(UniversalDataAccess)架構(gòu)。UDA以COM技術(shù)為核心,協(xié)助程序員存取企業(yè)中各類不同的數(shù)據(jù)源。UDA以O(shè)LEDB(ObjectLinkandEmbedDataBase,對(duì)象鏈接和嵌入數(shù)據(jù)庫(kù))做為技術(shù)的骨架。OLEDB是目前應(yīng)用更為廣泛的一種數(shù)據(jù)技術(shù)標(biāo)準(zhǔn)接口,定義了統(tǒng)一的COM接口做為存取各類異質(zhì)數(shù)據(jù)源的標(biāo)準(zhǔn),并且封裝在一組COM對(duì)象之中。5.1.2DAO和OLEDBOLEDB將傳統(tǒng)的數(shù)據(jù)庫(kù)系統(tǒng)劃分為多個(gè)邏輯組件,這些組件之間相對(duì)獨(dú)立又相互通信。這種組件模型中主要是由三個(gè)部分組合而成。數(shù)據(jù)提供者(DataProviders)是通過OLEDB提供數(shù)據(jù)存儲(chǔ)的軟件組件,例如文本文件、主機(jī)上的數(shù)據(jù)庫(kù),電子郵件存儲(chǔ),都可以是數(shù)據(jù)提供者。有的文檔把這些軟件組件的開發(fā)商也稱為數(shù)據(jù)提供者。數(shù)據(jù)使用者(DataConsumers)是指任何需要訪問數(shù)據(jù)的系統(tǒng)程序或應(yīng)用程序,除了典型的數(shù)據(jù)庫(kù)應(yīng)用程序之外,還包括需要訪問各種數(shù)據(jù)源的開發(fā)工具或語(yǔ)言。數(shù)據(jù)服務(wù)組件(ServiceComponents)可以執(zhí)行數(shù)據(jù)提供者以及數(shù)據(jù)使用者之間數(shù)據(jù)傳遞的工作,例如,數(shù)據(jù)使用者要向數(shù)據(jù)提供者要求數(shù)據(jù)時(shí),是通過OLEDB服務(wù)組件的查詢處理器執(zhí)行查詢的工作,而查詢到的結(jié)果則由游標(biāo)引擎(CursorEngine)來(lái)管理。5.1.2DAO和OLEDB雖然OLEDB允許程序員存取各類數(shù)據(jù),是一個(gè)非常良好的架構(gòu),但是由于OLEDB太底層化,而且在使用上非常復(fù)雜,對(duì)程序員的技能要求較高。為了解決這個(gè)問題,Microsoft以COM技術(shù)封裝OLEDB為ADO對(duì)象,極大簡(jiǎn)化了程序員數(shù)據(jù)存取的工作,使其獲得了更為廣泛的使用。5.1.3ODBC1992年Microsoft和Sybase、Digital共同制定了ODBC(OpenDatabaseConnectivity,開放數(shù)據(jù)庫(kù)互連)接口標(biāo)準(zhǔn),以單一的ODBCAPI來(lái)存取各種不同的關(guān)系數(shù)據(jù)庫(kù)。ODBC它建立了一組規(guī)范,并提供了一組對(duì)數(shù)據(jù)庫(kù)訪問的標(biāo)準(zhǔn)API。這些API獨(dú)立于不同廠商的DBMS,也獨(dú)立于具體的編程語(yǔ)言,利用SQL語(yǔ)言來(lái)完成其大部分任務(wù)。一個(gè)基于ODBC的應(yīng)用程序?qū)?shù)據(jù)庫(kù)的操作不依賴任何DBMS,所有的數(shù)據(jù)庫(kù)操作由對(duì)應(yīng)DBMS的ODBC驅(qū)動(dòng)程序完成,其最大的優(yōu)點(diǎn)就是能以統(tǒng)一的方式處理所有的數(shù)據(jù)庫(kù)。5.1.3ODBC要訪問一個(gè)數(shù)據(jù)庫(kù),首先必須用ODBC管理器注冊(cè)一個(gè)ODBC數(shù)據(jù)源,管理器根據(jù)這個(gè)數(shù)據(jù)源提供的數(shù)據(jù)庫(kù)位置、數(shù)據(jù)庫(kù)類型及ODBC驅(qū)動(dòng)程序等信息,建立起ODBC與具體數(shù)據(jù)庫(kù)的聯(lián)系。這樣,只要應(yīng)用程序?qū)?shù)據(jù)源名稱提供給ODBC,ODBC就能建立起與相應(yīng)數(shù)據(jù)庫(kù)的連接。目前,ODBC已經(jīng)是一個(gè)穩(wěn)定并且執(zhí)行效率良好的數(shù)據(jù)存取引擎。ODBC僅支持關(guān)系數(shù)據(jù)庫(kù),以及傳統(tǒng)的數(shù)據(jù)庫(kù)數(shù)據(jù)類型,并且只以C/C++語(yǔ)言API形式提供服務(wù)。5.1.3ODBC【例5.9】有SQLServer數(shù)據(jù)源,服務(wù)器名為Server1,數(shù)據(jù)庫(kù)名為SaleProduct,采用SQLServer方式身份驗(yàn)證,登錄名為sa,密碼為123456。在C#程序中利用ODBC實(shí)現(xiàn)連接數(shù)據(jù)庫(kù),并在窗口中列出全部客戶的信息。本例設(shè)置ODBC數(shù)據(jù)源名稱為L(zhǎng)inkToSaleProduct。窗口名稱為FormListCustomer,客戶的信息利用dataGridView控件顯示,控件名稱為dataGridViewListCustomer。程序的主要代碼privatevoidFormListCustomer_Load(objectsender,EventArgse){stringstrConn="DSN=LinkToSaleProduct;UID=sa;PWD=123456;";//創(chuàng)建ODBC連接對(duì)象:

OdbcConnectioncon=newOdbcConnection(strConn);DataTabledt=newDataTable();con.Open();//發(fā)送一條SQL語(yǔ)句并執(zhí)行:

OdbcDataAdapterodbcda=newOdbcDataAdapter("SELECTcustID,custName,custCity,custPhoneFROMCustomer;",con);DataSetds=newDataSet();//處理結(jié)果集:

odbcda.Fill(ds);this.dataGridViewListCustomer.DataSource=ds.Tables[0].DefaultView;}運(yùn)行結(jié)果5.1.4JDBCJDBC(JavaDataBaseConnectivity,Java數(shù)據(jù)庫(kù)連接)是一個(gè)面向?qū)ο蟮膽?yīng)用程序接口(API),由一組用Java語(yǔ)言編寫的類和接口組成,通過它可訪問各類關(guān)系數(shù)據(jù)庫(kù)。JDBC是Java核心類庫(kù)的一部分。JDBC與ODBC類似,JDBCAPI中定義了一些Java類分別用來(lái)表示與數(shù)據(jù)庫(kù)的連接(Connections)、SQL語(yǔ)句(SQLStatements)、結(jié)果集(ResultSets)以及其它的數(shù)據(jù)庫(kù)對(duì)象,使得Java程序能方便地與數(shù)據(jù)庫(kù)交互并處理所得的結(jié)果。使用JDBC,所有Java程序都能通過SQL語(yǔ)句或數(shù)據(jù)庫(kù)中的存儲(chǔ)過程來(lái)存取數(shù)據(jù)庫(kù)。5.1.4JDBC要通過JDBC來(lái)存取某一特定的數(shù)據(jù)庫(kù),必須有相應(yīng)的JDBC驅(qū)動(dòng)程序,它通常由生產(chǎn)數(shù)據(jù)庫(kù)的廠家提供,是連接JDBCAPI與具體數(shù)據(jù)庫(kù)之間的橋梁。通常,Java程序首先使用JDBCAPI來(lái)與JDBCDriverManager交互,由JDBCDriverManager載入指定的JDBCdrivers,以后就可以通過JDBCAPI來(lái)操縱數(shù)據(jù)庫(kù)。5.1.4JDBC【例5.10】有SQLServer數(shù)據(jù)源,服務(wù)器名為Server1,數(shù)據(jù)庫(kù)名為SaleProduct,采用SQLServer方式身份驗(yàn)證,登錄名為sa,密碼為123456。在Java程序中利用JDBC實(shí)現(xiàn)連接數(shù)據(jù)庫(kù),并在窗口中列出全部客戶的信息。本例JFrame窗口的類名稱為Customer_List,客戶的信息利用JTable控件顯示,控件名稱為jTable1。程序由兩個(gè)類文件組成,DBConnection類用于實(shí)現(xiàn)與數(shù)據(jù)庫(kù)的連接,Customer_List類用于實(shí)現(xiàn)數(shù)據(jù)的查詢和窗口顯示。5.1.4JDBCpublicclassDBConnection{publicstaticConnectiongetConnection()throwsSQLException{try{Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");}catch(ClassNotFoundExceptionex){ex.printStackTrace();returnnull;}StringconnectionUrl="jdbc:sqlserver://localhost:1433;"+"databaseName=SaleProduct;user=sa;password=123456;";Connectioncon=DriverManager.getConnection(connectionUrl);returncon;}}}catch(SQLExceptionex1){}}}

//其余代碼略}5.1.4JDBCpublicclassCustomer_Listextendsjavax.swing.JFrame{DefaultTableModeldm=null;Connectionconn=null;StringBuffersBuf=newStringBuffer();publicCustomer_List(){initComponents();dm=(DefaultTableModel)this.jTable1.getModel();dm.setRowCount(0);try{

//創(chuàng)建JDBC連接對(duì)象:

conn=DBConnection.getConnection();

//發(fā)送一條SQL語(yǔ)句并執(zhí)行:

PreparedStatementpStat=conn.prepareStatement("SELECTcustID,custName,custCity,custPhoneFROMCustomerORDERBYcustCity;");ResultSetrs=pStat.executeQuery();

5.1.4JDBC//處理結(jié)果集:

while(rs.next()){Vectorvc=newVector();vc.add(rs.getString("custID"));vc.add(rs.getString("custName"));vc.add(rs.getString("custCity"));vc.add(rs.getString("custPhone"));dm.addRow(vc);}}catch(SQLExceptionex){ex.printStackTrace();}finally{try{if(conn!=null){conn.close();conn=null;}}catch(SQLExceptionex1){}}}//其余代碼略}運(yùn)行結(jié)果5.1.5ADO和ADO.NETADO(ActiveXDataObjects,ActiveX數(shù)據(jù)對(duì)象)是Microsoft提出的一種面向?qū)ο蟮膽?yīng)用程序接口(API)是一個(gè)用于存取數(shù)據(jù)源的COM組件,用以實(shí)現(xiàn)訪問關(guān)系或非關(guān)系數(shù)據(jù)庫(kù)中的數(shù)據(jù)。ADO是對(duì)當(dāng)前微軟所支持的數(shù)據(jù)庫(kù)進(jìn)行操作的最有效和最簡(jiǎn)單直接的方法之一。一般的方法是利用ADOConnection對(duì)象創(chuàng)建一個(gè)到達(dá)某個(gè)數(shù)據(jù)源的開放連接,通過此連接可以對(duì)一個(gè)數(shù)據(jù)庫(kù)進(jìn)行訪問和操作。ADO是應(yīng)用程序和數(shù)據(jù)底層的一個(gè)中間層,ADO對(duì)象通過OLEDB間接取得數(shù)據(jù)庫(kù)中的數(shù)據(jù)。5.1.5ADO和ADO.NETADO.NET也是一種數(shù)據(jù)訪問技術(shù),使得應(yīng)用程序可以連接到數(shù)據(jù)存儲(chǔ),并以各種方式操作存儲(chǔ)在其中的數(shù)據(jù)。該技術(shù)基于.NETFramework,與.NETFramework類庫(kù)的其余部分高度集成,是在.NET編程環(huán)境中優(yōu)先使用的數(shù)據(jù)訪問接口。ADO.NET在.NETFramework中提供最直接的數(shù)據(jù)訪問方法。ADO.NET軟件棧包含兩個(gè)主要部分:提供者和服務(wù)。傳統(tǒng)ADO與ADO.NET存在很大的區(qū)別。5.1.5ADO和ADO.NET在有連接模式下ADO.NET的數(shù)據(jù)庫(kù)訪問通常包括以下步驟:(1)通過數(shù)據(jù)庫(kù)連接類(Connection)連接到數(shù)據(jù)庫(kù),如SQLServer服務(wù)器、Access數(shù)據(jù)庫(kù)文件等。(2)通過數(shù)據(jù)庫(kù)命令類(Command)在數(shù)據(jù)庫(kù)上執(zhí)行SQL語(yǔ)句,包括更新(Update)、插入(Insert)、刪除(Delete)、查詢(Select)等。Command表示一個(gè)能被數(shù)據(jù)提供者處理的命令,可以返回一個(gè)Recordset記錄集或執(zhí)行一個(gè)查詢動(dòng)作。(3)如果是查詢語(yǔ)句,還可以通過數(shù)據(jù)讀取器類(DataReader)進(jìn)行只讀向前讀取數(shù)據(jù)記錄。(4)數(shù)據(jù)庫(kù)操作完成后通過連接類(Connection)關(guān)閉數(shù)據(jù)庫(kù)連接。5.1.5ADO和ADO.NET【例5.11】有SQLServer數(shù)據(jù)源,服務(wù)器名為Server1,數(shù)據(jù)庫(kù)名為SaleProduct,采用SQLServer方式身份驗(yàn)證,登錄名為sa,密碼為123456。在C#程序中利用ADO實(shí)現(xiàn)連接數(shù)據(jù)庫(kù),并在窗口中實(shí)現(xiàn)新客戶的添加。本例窗口名稱為FormInsertCustomer,客戶的信息利用TextBox控件輸入,控件名稱分別為txtCustID、txtCustName、txtCustCity、txtCustPhone實(shí)現(xiàn)添加新紀(jì)錄的主要代碼stringstrConn="DataSource=Server1;InitialCatalog=SaleProduct;uid=sa;pwd=123456";//創(chuàng)建JDBC連接對(duì)象:SqlConnectioncon=newSqlConnection(strConn);con.Open();try{//發(fā)送一條SQL語(yǔ)句并執(zhí)行:StringBuilderstrSQL=newStringBuilder();strSQL.Append("INSERTINTOCustomer(custID,custName,custCity,custPhone)");strSQL.Append("VALUES('"+this.txtCustID.Text.Trim().ToString()+"','"+this.txtCustName.Text.Trim().ToString()+"',");strSQL.Append("'"+this.txtCustCity.Text.Trim().ToString()+"','"+this.txtCustPhone.Text.Trim().ToString()+"')");

實(shí)現(xiàn)添加新紀(jì)錄的主要代碼(續(xù))using(SqlCommandcmd=newSqlCommand(strSQL.ToString(),con)){cmd.ExecuteNonQuery();MessageBox.Show("信息增加成功!");}strSQL.Remove(0,strSQL.Length);}catch(Exceptionex){MessageBox.Show("錯(cuò)誤:"+ex.Message,"錯(cuò)誤提示",MessageBoxButtons.OKCancel,MessageBoxIcon.Error);}finally{if(con.State==ConnectionState.Open){con.Close();con.Dispose();}}運(yùn)行結(jié)果5.2存儲(chǔ)過程5.2.1基本概念存儲(chǔ)過程通常用來(lái)執(zhí)行管理任務(wù)或應(yīng)用復(fù)雜的業(yè)務(wù)規(guī)則,由SQL語(yǔ)句和過程控制語(yǔ)句組成。存儲(chǔ)過程存儲(chǔ)在數(shù)據(jù)庫(kù)服務(wù)器上,是獨(dú)立于數(shù)據(jù)表之外的數(shù)據(jù)庫(kù)對(duì)象。存儲(chǔ)過程通常在第一次執(zhí)行時(shí)進(jìn)行編譯,編譯好的代碼保存在高速緩存中以便供用戶調(diào)用,只需編譯一次,可多次執(zhí)行。存儲(chǔ)過程------------------------單個(gè)SQL語(yǔ)句SQL語(yǔ)句塊SQL語(yǔ)句與邏輯控制語(yǔ)句可以包含存儲(chǔ)過程同其它編程語(yǔ)言中的過程或函數(shù)相似,有一個(gè)作為標(biāo)識(shí)的過程名,包含執(zhí)行數(shù)據(jù)庫(kù)操作的編程語(yǔ)句,可接收輸入?yún)?shù)并以輸出參數(shù)的形式將多個(gè)值返回至調(diào)用過程或批處理。存儲(chǔ)過程的分類(1)系統(tǒng)存儲(chǔ)過程系統(tǒng)存儲(chǔ)過程由系統(tǒng)定義,其名稱以“sp_”為前綴,主要用于從系統(tǒng)表中獲取信息,如列出服務(wù)器上的所有數(shù)據(jù)庫(kù)、查看某個(gè)表的所有信息、添加或修改登錄帳戶的密碼等。這些存儲(chǔ)過程為用戶管理數(shù)據(jù)庫(kù)、獲取系統(tǒng)信息、查看系統(tǒng)對(duì)象提供了很大的幫助。在SQLServer中,當(dāng)創(chuàng)建一個(gè)新數(shù)據(jù)庫(kù)時(shí),會(huì)在新數(shù)據(jù)庫(kù)中自動(dòng)創(chuàng)建一些系統(tǒng)存儲(chǔ)過程。在使用以sp_開頭的系統(tǒng)存儲(chǔ)過程時(shí),SQLServer首先在當(dāng)前數(shù)據(jù)庫(kù)中尋找,如果沒有找到,則再到master數(shù)據(jù)庫(kù)中查找并執(zhí)行。存儲(chǔ)過程的分類(2)用戶自定義存儲(chǔ)過程用戶自定義存儲(chǔ)過程類似編程語(yǔ)言中的用戶自定義函數(shù),是由用戶在自己的數(shù)據(jù)庫(kù)中創(chuàng)建,并能完成某一特定功能的存儲(chǔ)過程。本節(jié)主要介紹用戶自定義存儲(chǔ)過程。存儲(chǔ)過程的分類(3)擴(kuò)展存儲(chǔ)過程擴(kuò)展存儲(chǔ)過程是指SQLServer的實(shí)例動(dòng)態(tài)加載和運(yùn)行的動(dòng)態(tài)鏈接庫(kù)DLL,這些DLL通常是使用外部程序語(yǔ)言編寫的。擴(kuò)展存儲(chǔ)過程的名稱以“xp_”為前綴。擴(kuò)展存儲(chǔ)過程主要用于獲取系統(tǒng)信息,如系統(tǒng)上可用的磁盤空間、查看某個(gè)目錄下所有子目錄的結(jié)構(gòu)、獲取某個(gè)文件的屬性等。存儲(chǔ)過程的分類(4)臨時(shí)存儲(chǔ)過程臨時(shí)存儲(chǔ)過程的名稱以“#”和“##”為前綴,“#”表示本地臨時(shí)存儲(chǔ)過程,“##”表示全局臨時(shí)存儲(chǔ)過程,它們存儲(chǔ)在tempdb數(shù)據(jù)庫(kù)中。存儲(chǔ)過程的分類(5)遠(yuǎn)程存儲(chǔ)過程遠(yuǎn)程存儲(chǔ)過程是在遠(yuǎn)程服務(wù)器的數(shù)據(jù)庫(kù)中創(chuàng)建和存儲(chǔ)的過程。這些存儲(chǔ)過程可被各種服務(wù)器訪問,向具有相應(yīng)許可權(quán)限的用戶提供服務(wù)。遠(yuǎn)程存儲(chǔ)過程不參與事務(wù)處理。例如,如果執(zhí)行對(duì)遠(yuǎn)程SQLServer實(shí)例進(jìn)行更改的遠(yuǎn)程存儲(chǔ)過程,則不能回滾這些更改。通??梢允褂梅植际讲樵兒虴XECUTE命令執(zhí)行一個(gè)遠(yuǎn)程存儲(chǔ)過程。存儲(chǔ)過程的優(yōu)點(diǎn)

改善SQL語(yǔ)句的執(zhí)行性能

減少網(wǎng)絡(luò)流量

增強(qiáng)SQL語(yǔ)言的功能和靈活性

提高系統(tǒng)的安全性

提高開發(fā)效率和應(yīng)用程序的可維護(hù)性把過多的業(yè)務(wù)寫入存儲(chǔ)過程也是不合適的SQL語(yǔ)言的處理功能相對(duì)簡(jiǎn)單,不利于調(diào)試復(fù)雜功能的程序,當(dāng)存儲(chǔ)過程太多時(shí)維護(hù)會(huì)比較困難。存儲(chǔ)過程會(huì)給服務(wù)器帶來(lái)額外的壓力,其移植性也較差,在升級(jí)到不同的數(shù)據(jù)庫(kù)時(shí)比較困難。在實(shí)際運(yùn)用中把經(jīng)常用到的查詢動(dòng)作編寫成一個(gè)存儲(chǔ)過程,并利用參數(shù)實(shí)現(xiàn)動(dòng)態(tài)查詢過程來(lái)響應(yīng)客戶的要求;實(shí)現(xiàn)在服務(wù)器端進(jìn)行批量數(shù)據(jù)處理等操作;利用系統(tǒng)為用戶定義的管理級(jí)別存儲(chǔ)過程實(shí)現(xiàn)數(shù)據(jù)的管理、配置和監(jiān)控等。5.2.2Transact-SQL基本語(yǔ)法Transact-SQL(以下簡(jiǎn)稱T-SQL)是SQLServer附帶的語(yǔ)言,用于創(chuàng)建和管理數(shù)據(jù)庫(kù)對(duì)象,以及插入、刪除、修改、查詢數(shù)據(jù)。它是對(duì)SQL標(biāo)準(zhǔn)語(yǔ)言的擴(kuò)展。1.變量的聲明和賦值在SQLServer中,聲明變量的語(yǔ)法形式是:

DECLARE<變量名><數(shù)據(jù)類型>[=value][,...n]變量名必須以“@”字符開頭,變量名必須符合標(biāo)識(shí)符規(guī)則。數(shù)據(jù)類型可以是由系統(tǒng)提供的或用戶定義的數(shù)據(jù)類型,但是變量不能是text、ntext或image數(shù)據(jù)類型。可以一次僅僅聲明一個(gè)變量,也可以一次聲明多個(gè)變量。1.變量的聲明和賦值為變量賦值的語(yǔ)法形式是:

SET<變量名>=常量表達(dá)式使用SET不能將查詢得到的值賦給變量,如果要將查詢得到的值賦給變量,需要使用SELECT設(shè)置變量值?!纠?.12】聲明兩個(gè)變量,并為其賦值。

DECLARE@teacher_idchar(4),@order_datedatetime

SET@teacher_id='0541'

SET@order_date='1/01/2010'

【例5.13】聲明一個(gè)變量,并使用查詢結(jié)果為其賦值。

DECLARE@testnumeric(10,2);

SELECT@test=(SELECTMAX(pdPrice)FROMProduct)

PRINT@test

2.控制流語(yǔ)句(1)定義語(yǔ)句塊

使用控制流關(guān)鍵字BEGIN和END,可以將一組T-SQL語(yǔ)句定義為語(yǔ)句塊,語(yǔ)法格式為:

BEGIN

sql_statement[...n]

END

2.控制流語(yǔ)句(2)條件控制語(yǔ)句

條件控制語(yǔ)句的語(yǔ)法格式為:

IF<條件表達(dá)式>

{sql_statement|statement_block}

[ELSE

{sql_statement|statement_block}](3)循環(huán)控制語(yǔ)句循環(huán)控制語(yǔ)句的語(yǔ)法格式為:

WHILE<條件表達(dá)式>{sql_statement|statement_block|BREAK|CONTINUE}BREAK語(yǔ)句的作用是結(jié)束WHILE循環(huán),將執(zhí)行出現(xiàn)循環(huán)結(jié)束的標(biāo)記(或END關(guān)鍵字)后面的語(yǔ)句。CONTINUE語(yǔ)句的作用是忽略CONTINUE關(guān)鍵字后面的任何語(yǔ)句,使WHILE循環(huán)重新開始執(zhí)行。3.USE語(yǔ)句USE語(yǔ)句用于設(shè)置當(dāng)前數(shù)據(jù)庫(kù)?!纠?.14】將當(dāng)前數(shù)據(jù)庫(kù)設(shè)置為SaleProduct。USESaleProductGO4.GO語(yǔ)句SQLServer應(yīng)用程序可以將多個(gè)T-SQL語(yǔ)句作為一個(gè)批處理發(fā)送到SQLServer的實(shí)例來(lái)執(zhí)行,該批中的語(yǔ)句被編譯成一個(gè)執(zhí)行計(jì)劃。SQLServer實(shí)用工具將GO解釋為應(yīng)該向SQLServer實(shí)例發(fā)送當(dāng)前批T-SQL語(yǔ)句的信號(hào)。當(dāng)前批語(yǔ)句由上一個(gè)GO命令后輸入的所有語(yǔ)句組成,如果是第一條GO命令,則由會(huì)話或腳本開始后輸入的所有語(yǔ)句組成。GO不是T-SQL語(yǔ)句,它是sqlcmd和osql實(shí)用工具以及SQLServerManagementStudio代碼編輯器識(shí)別的命令。GO命令和T-SQL語(yǔ)句不能在同一行中。4.GO語(yǔ)句語(yǔ)法格式:

GO[count]

其中count為正整數(shù),指定GO之前的批處理執(zhí)行的次數(shù)。需要注意的是,用戶必須遵守使用批處理的規(guī)則。例如,在同一批處理中,創(chuàng)建數(shù)據(jù)庫(kù)之后不能直接使用其新建的數(shù)據(jù)庫(kù);局部變量的作用域限制在一個(gè)批處理中,不可在GO命令后引用。5.注釋單行注釋可以使用注釋符“--”多行注釋可以使用注釋符“/*…*/”5.2.3創(chuàng)建和執(zhí)行存儲(chǔ)過程數(shù)據(jù)庫(kù)的所有者可以創(chuàng)建存儲(chǔ)過程,也可以授權(quán)其他用戶創(chuàng)建存儲(chǔ)過程。注意:不能將CREATEPROCEDURE語(yǔ)句與其它SQL語(yǔ)句組合到單個(gè)批處理中。通常創(chuàng)建存儲(chǔ)過程時(shí),應(yīng)指定所有輸入?yún)?shù)所有向調(diào)用過程或批處理返回的輸出參數(shù)執(zhí)行數(shù)據(jù)庫(kù)操作的編程語(yǔ)句返回至調(diào)用過程或批處理以表明成功或失敗的狀態(tài)值。1.不帶參數(shù)的存儲(chǔ)過程使用CREATEPROCEDURE語(yǔ)句創(chuàng)建不帶參數(shù)的存儲(chǔ)過程,語(yǔ)法格式如下:

CREATEPROCEDURE<存儲(chǔ)過程名>[WITH{RECOMPILE|ENCRYPTION|RECOMPILE,ENCRYPTION}]ASsql_statement[...n]

1.不帶參數(shù)的存儲(chǔ)過程說(shuō)明存儲(chǔ)過程的名稱必須符合標(biāo)識(shí)符規(guī)則,且對(duì)于數(shù)據(jù)庫(kù)及其所有者必須唯一;RECOMPILE選項(xiàng)用于指定SQLServer不緩存該過程的計(jì)劃,該過程將在運(yùn)行時(shí)重新編譯;ENCRYPTION選項(xiàng)用于指定SQLServer將CREATEPROCEDURE語(yǔ)句的原始文本轉(zhuǎn)換為加密格式,可防止將存儲(chǔ)過程作為SQLServer復(fù)制的一部分發(fā)布;sql_statement[...n]是指構(gòu)成過程主體的一個(gè)或多個(gè)T-SQL語(yǔ)句,可以使用可選的BEGIN和END關(guān)鍵字將這些語(yǔ)句括起來(lái)。1.不帶參數(shù)的存儲(chǔ)過程對(duì)存儲(chǔ)在服務(wù)器上的存儲(chǔ)過程,可以使用EXECUTE命令執(zhí)行它,其語(yǔ)法格式如下:

EXECUTE<存儲(chǔ)過程名>

【例5.15】在商品銷售管理數(shù)據(jù)庫(kù)SaleProduct中,創(chuàng)建一個(gè)存儲(chǔ)過程up_TopOrders,要求查詢總金額排名前5位和后5位的訂單號(hào)、訂單總金額和這些訂單的客戶名稱、所在城市。CREATEPROCEDUREup_TopOrdersASBEGINSELECTTOP5Orders.orderID,orderAmount,Orders.custID,custName,custCityFROMCustomer,OrdersWHERECustomer.custID=Orders.custIDORDERBYorderAmountDESC;SELECTTOP5Orders.orderID,orderAmount,Orders.custID,custName,custCityFROMdbo.Customer,OrdersWHERECustomer.custID=Orders.custIDORDERBYorderAmountASC;END【例5.16】在SQLServerManagementStudio中執(zhí)行存儲(chǔ)過程up_TopOrders。USESaleProductGOEXECUTEup_TopOrdersGO2.帶參數(shù)的存儲(chǔ)過程使用CREATEPROCEDURE語(yǔ)句創(chuàng)建帶參數(shù)的存儲(chǔ)過程,語(yǔ)法格式如下:

CREATEPROCEDURE<存儲(chǔ)過程名>[{<參數(shù)名稱><數(shù)據(jù)類型>}[=default][OUTPUT]][,...n][WITH{RECOMPILE|ENCRYPTION|RECOMPILE,ENCRYPTION}]ASsql_statement[...n]2.帶參數(shù)的存儲(chǔ)過程說(shuō)明可以聲明一個(gè)或多個(gè)參數(shù)。必須使用“@”符號(hào)作為第一個(gè)字符來(lái)指定參數(shù)名稱,參數(shù)名稱必須符合標(biāo)識(shí)符的規(guī)則。默認(rèn)情況下,參數(shù)只能代替常量,而不能用于代替表名、列名或其他數(shù)據(jù)庫(kù)對(duì)象的名稱。default為參數(shù)的默認(rèn)值。如果為參數(shù)定義了默認(rèn)值,則無(wú)需指定此參數(shù)的值即可執(zhí)行過程。默認(rèn)值必須是常量或NULL。如果過程將對(duì)該參數(shù)使用LIKE關(guān)鍵字,那么默認(rèn)值中可以包含通配符(%、_)OUTPUT選項(xiàng)用于指定參數(shù)是輸出參數(shù)。該參數(shù)的值可以返回給存儲(chǔ)過程的調(diào)用方。通常text、ntext和image參數(shù)不能用作OUTPUT參數(shù)。除了使用OUTPUT參數(shù),也可以使用return語(yǔ)句返回值。2.帶參數(shù)的存儲(chǔ)過程【例5.17】在商品銷售管理數(shù)據(jù)庫(kù)SaleProduct中,創(chuàng)建一個(gè)存儲(chǔ)過程up_SearchProduct,要求該存儲(chǔ)過程有一個(gè)輸入?yún)?shù),用于接收商品名稱。執(zhí)行該存儲(chǔ)過程時(shí),將根據(jù)輸入的商品名稱列出所有的商品編號(hào)、生產(chǎn)廠商、價(jià)格,并計(jì)算出該商品的平均價(jià)格。2.帶參數(shù)的存儲(chǔ)過程CREATEPROCEDUREup_SearchProduct@productNamevarchar(20)ASDECLARE@avgnumeric(10,2);SELECTpdID,pdSupplier,pdPriceFROMproductWHEREpdName=@productName;SELECT@avg=AVG(pdPrice)FROMproductWHEREpdName=@productName;SELECT'該商品的平均價(jià)格為:'+STR(@avg)2.帶參數(shù)的存儲(chǔ)過程對(duì)于帶參數(shù)的存儲(chǔ)過程,執(zhí)行時(shí)應(yīng)該提供參數(shù)值??梢圆捎靡韵聝煞N方式:(1)按位置傳遞參數(shù)在調(diào)用存儲(chǔ)過程時(shí),直接給出參數(shù)值。如果多于一個(gè)參數(shù),給出的參數(shù)值要與定義的參數(shù)的順序一致。(2)使用參數(shù)名稱傳遞參數(shù)在調(diào)用存儲(chǔ)過程時(shí),可以使用@parameter=value的形式給出參數(shù)值。采用此方式,參數(shù)如果多于一個(gè)時(shí),給出的參數(shù)順序可以與定義的參數(shù)順序不一致,還可以省略那些已提供默認(rèn)值的參數(shù),但是必須按此種形式提供所有的參數(shù)值。2.帶參數(shù)的存儲(chǔ)過程【例5.18】在SQLServerManagementStudio中執(zhí)行存儲(chǔ)過程up_SearchProduct。USESaleProductGOEXECUTEup_SearchProduct'羽毛球'GO或:USESaleProductGOEXECUTEup_SearchProduct@productName='羽毛球'GO2.帶參數(shù)的存儲(chǔ)過程【例5.19】在商品銷售管理數(shù)據(jù)庫(kù)SaleProduct中,創(chuàng)建一個(gè)存儲(chǔ)過程up_SearchProductOutput,要求該存儲(chǔ)過程有一個(gè)輸入?yún)?shù),用于接收商品名稱。有一個(gè)輸出參數(shù),用于返回該商品的平均價(jià)格。執(zhí)行該存儲(chǔ)過程時(shí),將根據(jù)輸入的商品名稱列出該商品的所有商品編號(hào)、生產(chǎn)廠商、價(jià)格。2.帶參數(shù)的存儲(chǔ)過程CREATEPROCEDUREup_SearchProductOutput@productNamevarchar(20),@avgPricenumeric(10,2)OUTPUTASSELECTpdID,pdSupplier,pdPriceFROMproductWHEREpdName=@productName;SELECT@avgPrice=AVG(pdPrice)FROMproductWHEREpdName=@productName;2.帶參數(shù)的存儲(chǔ)過程【例5.20】執(zhí)行存儲(chǔ)過程up_SearchProductOutput,并打印其輸出參數(shù)。USESaleProductGODECLARE@avgnumeric(10,2)EXECUTEup_SearchProductOutput'羽毛球',@avgOUTPUTPRINT'該商品的平均價(jià)格為:'+STR(@avg)GO2.帶參數(shù)的存儲(chǔ)過程【例5.21】在商品銷售管理數(shù)據(jù)庫(kù)SaleProduct中,創(chuàng)建一個(gè)存儲(chǔ)過程up_SearchProductReturn,要求該存儲(chǔ)過程帶一個(gè)輸入?yún)?shù),用于接收商品名稱。執(zhí)行該存儲(chǔ)過程時(shí),將根據(jù)輸入的商品名稱列出該商品的所有商品編號(hào)、生產(chǎn)廠商、價(jià)格,并使用return語(yǔ)句返回該類商品的平均價(jià)格。2.帶參數(shù)的存儲(chǔ)過程CREATEPROCEDUREup_SearchProductReturn@productNamevarchar(20)ASDECLARE@avgnumeric(10,2);SELECTpdID,pdSupplier,pdPriceFROMproductWHEREpdName=@productName;SELECT@avg=AVG(pdPrice)FROMproductWHEREpdName=@productName;RETURN@avg;2.帶參數(shù)的存儲(chǔ)過程【例5.22】在SQLServerManagementStudio中執(zhí)行存儲(chǔ)過程up_SearchProductReturn。USESaleProductGODECLARE@avgnumeric(10,2)EXECUTE@avg=up_SearchProductReturn'羽毛球'PRINT'該類商品的平均價(jià)格為:'+STR(@avg)GO5.2.4存儲(chǔ)過程的修改和刪除1.修改存儲(chǔ)過程使用ALTERPROCEDURE語(yǔ)句修改存儲(chǔ)過程,其語(yǔ)法格式如下

ALTERPROCEDURE<存儲(chǔ)過程名>[{<參數(shù)名稱><數(shù)據(jù)類型>}[=default][OUTPUT]][,...n][WITH{RECOMPILE|ENCRYPTION|RECOMPILE,ENCRYPTION}]ASsql_statement[...n]5.2.4存儲(chǔ)過程的修改和刪除【例5.23】修改例5.17創(chuàng)建的存儲(chǔ)過程up_SearchProduct,要求該存儲(chǔ)過程的輸入?yún)?shù),用于接收生產(chǎn)廠商名稱。執(zhí)行該存儲(chǔ)過程時(shí),列出該廠商生產(chǎn)的所有商品的編號(hào)、商品名稱、價(jià)格。ALTERPROCEDUREup_SearchProduct@productNamevarchar(10)ASSELECTpdID,pdName,pdPriceFROMproductWHEREpdSupplier=@productName;2.刪除存儲(chǔ)過程使用DROP語(yǔ)句刪除存儲(chǔ)過程,其語(yǔ)法格式為:

DROPPROCEDURE<存儲(chǔ)過程名>2.刪除存儲(chǔ)過程【例5.24】刪除例5.17中創(chuàng)建的存儲(chǔ)過程up_SearchProductUSESaleProductGODROPPROCEDUREup_SearchProduct;GO5.2.5獲得有關(guān)存儲(chǔ)過程的信息存儲(chǔ)過程被創(chuàng)建后,可以使用SQLServer提供的系統(tǒng)存儲(chǔ)過程查看其信息使用sp_help查看存儲(chǔ)過程的的名稱、擁有者、類型和創(chuàng)建時(shí)間使用sp_helptext查看存儲(chǔ)過程的定義信息使用sp_depends查看存儲(chǔ)過程的相關(guān)性。5.2.5獲得有關(guān)存儲(chǔ)過程的信息【例5.25】在SQLServerManagementStudio中執(zhí)行系統(tǒng)存儲(chǔ)過程,查看存儲(chǔ)過程up_TopOrders的信息。USESaleProductEXECsp_helpup_TopOrdersEXECsp_helptextup_TopOrdersEXECsp_dependsup_TopOrdersGO運(yùn)行結(jié)果5.3觸發(fā)器5.3.1基本概念觸發(fā)器(Trigger)是用戶定義在關(guān)系表上的一類由事件驅(qū)動(dòng)的特殊存儲(chǔ)過程。觸發(fā)器不能通過名稱被用戶直接調(diào)用,不允許帶參數(shù)。一旦定義了觸發(fā)器,任何用戶對(duì)數(shù)據(jù)表進(jìn)行更新操作時(shí),服務(wù)器都會(huì)自動(dòng)激活相應(yīng)的觸發(fā)器,在數(shù)據(jù)庫(kù)管理系統(tǒng)核心層進(jìn)行集中的完整性控制。觸發(fā)器可以包含復(fù)雜的T-SQL語(yǔ)句,可用于強(qiáng)制業(yè)務(wù)規(guī)則和數(shù)據(jù)完整性,其控制能力比第3章介紹的完整性約束更靈活,可以實(shí)施更為復(fù)雜的檢查和操作,具有更精細(xì)和更強(qiáng)大的數(shù)據(jù)控制能力。觸發(fā)器與表緊密相連,可以看作表定義的一部分。按觸發(fā)被激活的時(shí)機(jī)可以分為兩種類型AFTER觸發(fā)器,又稱為后觸發(fā)器該類觸發(fā)器是在引起觸發(fā)器執(zhí)行的修改語(yǔ)句(INSERT、UPDATE、或DELETE)成功完成之后執(zhí)行。如果修改語(yǔ)句因語(yǔ)法錯(cuò)誤或違反約束而失敗,觸發(fā)器將不會(huì)執(zhí)行。因此,這些觸發(fā)器不能用于違反約束的處理。此類觸發(fā)器只能定義在表上,不能創(chuàng)建在視圖上??梢詾槊總€(gè)觸發(fā)操作(INSERT、UPDATE或DELETE)創(chuàng)建多個(gè)AFTER觸發(fā)器。按觸發(fā)被激活的時(shí)機(jī)可以分為兩種類型INSTEADOF觸發(fā)器,又稱為替代觸發(fā)器當(dāng)引起觸發(fā)器執(zhí)行的修改語(yǔ)句停止執(zhí)行時(shí),該類觸發(fā)器代替觸發(fā)操作執(zhí)行。該類觸發(fā)器既可在表上定義,也可在視圖上定義。對(duì)于每個(gè)觸發(fā)操作(INSERT、UPDATE和DELETE)只能定義一個(gè)INSTEADOF觸發(fā)器。INSTEADOF觸發(fā)器可用于對(duì)一個(gè)或多個(gè)列執(zhí)行錯(cuò)誤或值檢查,然后在插入、更新或刪除行之前執(zhí)行其他操作。觸發(fā)器的優(yōu)點(diǎn):觸發(fā)器自動(dòng)執(zhí)行觸發(fā)器能夠?qū)?shù)據(jù)庫(kù)中的相關(guān)表實(shí)現(xiàn)級(jí)聯(lián)更改觸發(fā)器可以實(shí)現(xiàn)比CHECK約束更為復(fù)雜的數(shù)據(jù)完整性約束觸發(fā)器可以包含復(fù)雜的處理邏輯,能夠?qū)崿F(xiàn)復(fù)雜的數(shù)據(jù)完整性約束。觸發(fā)器可以評(píng)估數(shù)據(jù)修改前后的表狀態(tài),并根據(jù)其差異采取對(duì)策。一個(gè)表中可以存在多個(gè)同類觸發(fā)器(INSERT、UPDATE或DELETE),對(duì)于同一個(gè)修改語(yǔ)句可以有多個(gè)不同的對(duì)策以響應(yīng)。5.3.2創(chuàng)建觸發(fā)器一個(gè)觸發(fā)器由兩部分組成:觸發(fā)事件及觸發(fā)條件觸發(fā)事件是指對(duì)數(shù)據(jù)庫(kù)的插入、刪除、修改等操作,在這些操作進(jìn)行時(shí),觸發(fā)器被激發(fā)觸發(fā)器條件用于確定DELETE、INSERT或UPDATE語(yǔ)句是否導(dǎo)致觸發(fā)器動(dòng)作。條件成立,則由數(shù)據(jù)庫(kù)管理系統(tǒng)執(zhí)行觸發(fā)器動(dòng)作。動(dòng)作這些動(dòng)作可以是一系列對(duì)數(shù)據(jù)庫(kù)的操作,如撤銷觸發(fā)事件所做的操作等。5.3.2創(chuàng)建觸發(fā)器在創(chuàng)建觸發(fā)器時(shí),必須指明在哪一個(gè)表上定義觸發(fā)器以及觸發(fā)器的名稱、激發(fā)時(shí)機(jī)、激活觸發(fā)器的修改語(yǔ)句(INSERT、UPDATE或DELETE)。只能在當(dāng)前數(shù)據(jù)庫(kù)中創(chuàng)建觸發(fā)器,表的所有者具有創(chuàng)建觸發(fā)器的默認(rèn)權(quán)限,不能將該權(quán)限轉(zhuǎn)給其他用戶。5.3.2創(chuàng)建觸發(fā)器使用CREATETRIGGER語(yǔ)句定義觸發(fā)器,其一般格式為:

CREATETRIGGER<觸發(fā)器名>ON<表名|視圖名>{FOR|AFTER|INSTEADOF}<觸發(fā)事件>AS<觸發(fā)器動(dòng)作體>說(shuō)明(1)<觸發(fā)器名>是要建立的觸發(fā)器名字。觸發(fā)器名必須符合標(biāo)識(shí)符規(guī)則,但不能以#或##開頭。(2)<表名或視圖名>指觸發(fā)器

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論