?? sql.txt
字號:
SQL語言作為關(guān)系數(shù)據(jù)庫管理系統(tǒng)中的一種通用的結(jié)構(gòu)查詢語言,已經(jīng)被眾多的數(shù)據(jù)庫管理系統(tǒng)所采用,如ORACLE、Sybase、Informix等數(shù)據(jù)庫管理系統(tǒng),它們都支持SQL 語言。Delphi與使用SQL語言的數(shù)據(jù)庫管理系統(tǒng)兼容,在使用Delphi開發(fā)數(shù)據(jù)庫應(yīng)用程序時,我們可以使用SQL語言編程,支持SQL編程是Delphi的一個重要特征,這也是體現(xiàn)Delphi作為一個強(qiáng)大的數(shù)據(jù)庫應(yīng)用開發(fā)工具的一個重要標(biāo)志?!?
1 SQL語言簡介
1.1 SQL的歷史
在70年代初,E.E.Codd首先提出了關(guān)系模型。70年代中期,IBM公司在研制 SYSTEM R關(guān)系數(shù)據(jù)庫管理系統(tǒng)中研制了SQL語言,最早的SQL語言(叫SEQUEL2)是在1976 年 11 月的IBM Journal of R&D上公布的。1979年ORACLE公司首先提供商用的SQL,IBM公司在DB2 和SQL/DS數(shù)據(jù)庫系統(tǒng)中也實(shí)現(xiàn)了SQL。
1986年10月,美國ANSI采用SQL作為關(guān)系數(shù)據(jù)庫管理系統(tǒng)的標(biāo)準(zhǔn)語言(ANSI X3. 135-1986),后為國際標(biāo)準(zhǔn)化組織(ISO)采納為國際標(biāo)準(zhǔn)。1989年,美國ANSI采納在ANSI X3.135-1989報(bào)告中定義的關(guān)系數(shù)據(jù)庫管理系統(tǒng)的SQL標(biāo)準(zhǔn)語言,稱為ANSI SQL 89, 該標(biāo)準(zhǔn)替代ANSI X3.135-1986版本。該標(biāo)準(zhǔn)為下列組織所采納:
● 國際標(biāo)準(zhǔn)化組織(ISO),為ISO 9075-1989報(bào)告“Database Language SQL With Integrity Enhancement”
● 美國聯(lián)邦政府,發(fā)布在The Federal Information Processing Standard Publication(FIPS PUB)127
目前,所有主要的關(guān)系數(shù)據(jù)庫管理系統(tǒng)支持某些形式的SQL語言,大部分?jǐn)?shù)據(jù)庫打算遵守ANSI SQL89標(biāo)準(zhǔn)?!?
1.2 SQL的優(yōu)點(diǎn)
SQL廣泛地被采用正說明了它的優(yōu)點(diǎn)。它使全部用戶,包括應(yīng)用程序員、DBA管理員和終端用戶受益非淺。
(1) 非過程化語言
SQL是一個非過程化的語言,因?yàn)樗淮翁幚硪粋€記錄,對數(shù)據(jù)提供自動導(dǎo)航。SQL允許用戶在高層的數(shù)據(jù)結(jié)構(gòu)上工作,而不對單個記錄進(jìn)行操作,可操作記錄集。所有SQL 語句接受集合作為輸入,返回集合作為輸出。SQL的集合特性允許一條SQL語句的結(jié)果作為另一條SQL語句的輸入。
SQL不要求用戶指定對數(shù)據(jù)的存放方法。這種特性使用戶更易集中精力于要得到的結(jié)果。所有SQL語句使用查詢優(yōu)化器,它是RDBMS的一部分,由它決定對指定數(shù)據(jù)存取的最快速度的手段。查詢優(yōu)化器知道存在什么索引,哪兒使用合適,而用戶從不需要知道表是否有索引,表有什么類型的索引。
(2) 統(tǒng)一的語言
SQL可用于所有用戶的DB活動模型,包括系統(tǒng)管理員、數(shù)據(jù)庫管理員、應(yīng)用程序員、決策支持系統(tǒng)人員及許多其它類型的終端用戶。基本的SQL 命令只需很少時間就能學(xué)會,最高級的命令在幾天內(nèi)便可掌握。
SQL為許多任務(wù)提供了命令,包括:
● 查詢數(shù)據(jù)
● 在表中插入、修改和刪除記錄
● 建立、修改和刪除數(shù)據(jù)對象
● 控制對數(shù)據(jù)和數(shù)據(jù)對象的存取
● 保證數(shù)據(jù)庫一致性和完整性
以前的數(shù)據(jù)庫管理系統(tǒng)為上述各類操作提供單獨(dú)的語言,而SQL 將全部任務(wù)統(tǒng)一在一種語言中。
(3) 是所有關(guān)系數(shù)據(jù)庫的公共語言
由于所有主要的關(guān)系數(shù)據(jù)庫管理系統(tǒng)都支持SQL語言,用戶可將使用SQL的技能從一個RDBMS轉(zhuǎn)到另一個。所有用SQL編寫的程序都是可以移植的。
2 TQuery部件在SQL編程中的運(yùn)用
在Delphi中是通過TQuery部件來實(shí)現(xiàn)對SQL語言支持的,也就是說用Delphi 開發(fā)數(shù)據(jù)庫應(yīng)用程序時,使用SQL語言操作數(shù)據(jù)庫中的數(shù)據(jù)的唯一途徑是經(jīng)過TQuery部件。 TQuery部件在Delphi中使用SQL語言編程時占居著絕對重要的地位。在使用Delphi 開發(fā)的數(shù)據(jù)庫應(yīng)用中,可以使用SQL語言訪問下列三個方面的數(shù)據(jù)庫:
● Paradox或dBASE數(shù)據(jù)庫中的表
在訪問這些桌面數(shù)據(jù)庫系統(tǒng)中的數(shù)據(jù)時,只能使用ANSI標(biāo)準(zhǔn)的SQL語言中的部分SQL 語句,它們主要包括:Select、Insert、Update和Delete語句;即本地SQL語句。有關(guān)詳細(xì)情況請參見附錄“局部SQL語句的使用”。
● 本地InterBase數(shù)據(jù)庫服務(wù)器中的數(shù)據(jù)庫
在InterBase數(shù)據(jù)庫中支持的SQL語句, 在Delphi中都可以使用。有關(guān)InterBase中SQL語句的語法和限制,請參看“InterBase的語言參考”。
● 遠(yuǎn)程數(shù)據(jù)庫服務(wù)器中的數(shù)據(jù)庫
當(dāng)然這要求在Delphi中必須安裝相應(yīng)的SQL Link。只要是數(shù)據(jù)庫服務(wù)器上的DBMS支持的SQL語句,在Delphi中都可以使用。有關(guān)語法及限制請參看相關(guān)的數(shù)據(jù)庫管理 系統(tǒng)的文檔。
值得一提的是,Delphi還支持異構(gòu)查詢,即可以同時查詢多個數(shù)據(jù)庫服務(wù)器中相同的或不同類型的數(shù)據(jù)庫表,例如查詢的數(shù)據(jù)可以是來自O(shè)RACLE數(shù)據(jù)庫中的表和Sybase數(shù)據(jù)庫中的表或者其它多個數(shù)據(jù)庫中的表。
2.1 TQuery部件的使用
TQuery部件是一個數(shù)據(jù)集部件,它在Delphi部件選擇板上的數(shù)據(jù)訪問頁(Data Access)上,它與TTable部件具有很多共同的特性,我們在第十五章“數(shù)據(jù)訪問部件的應(yīng)用及編程”中較詳細(xì)地進(jìn)行了介紹。 TQuery 部件在 SQL 編程中占居了十分重要的地位。 它實(shí)現(xiàn)了Delphi對SQL語言的支持,在Delphi開發(fā)的數(shù)據(jù)庫應(yīng)用中,SQL語句是通過TQuery部件傳遞到要訪問的數(shù)據(jù)庫系統(tǒng)的數(shù)據(jù)庫引擎中,由數(shù)據(jù)庫引擎具體執(zhí)行SQL語句,以實(shí)現(xiàn)對數(shù)據(jù)的操作,而不是傳遞給Delphi中的BDE,由BDE實(shí)施具體的SQL動作。
我們已經(jīng)知道了TTable部件在訪問數(shù)據(jù)庫時已經(jīng)具備很強(qiáng)大的功能。TTable部件通過Delphi內(nèi)置的BDE可以實(shí)現(xiàn)對各種數(shù)據(jù)庫系統(tǒng)的訪問,然而TQuery部件提供了一些 TTable部件不具備的功能,它們是:
●多表聯(lián)接查詢
●復(fù)雜的嵌套查詢(Select中包含著Select子查詢)
●明確需要按SQL語言進(jìn)行的操作
因?yàn)門Tabel部件不能使用SQL語言,而在TQuery部件可以使用SQL語言,因而TQuery部件也就具備了強(qiáng)大的關(guān)系查詢能力。當(dāng)然這也使數(shù)據(jù)庫應(yīng)用程序本身變得更復(fù)雜了。
在Delphi應(yīng)用程序中編寫和使用的SQL語句有兩種:即靜態(tài)SQL語句、動態(tài)SQL 語句。靜態(tài)SQL語句是在程序設(shè)計(jì)階段,將SQL命令文本作為TQuery部件的SQL屬性值設(shè)置。而動態(tài)SQL語句編程是SQL語句中包含一系列的參數(shù),在程序運(yùn)行過程中各參數(shù)值是可變的,即可以動態(tài)地給SQL語句中的參數(shù)賦值。
靜態(tài)方式是把SQL命令文作為TQuery部件的SQL屬性值進(jìn)行設(shè)置,這樣,當(dāng)執(zhí)行應(yīng)用程序時,Delphi便執(zhí)行TQuery部件SQL屬性中設(shè)置的SQL命令。如果是SQL中的查詢命令,把TQuery部件通過TDataSource部件與數(shù)據(jù)控制部件相連,查詢的結(jié)果將會顯示在與 TQuery部件相連接的數(shù)據(jù)瀏覽部件中。動態(tài)SQL語句是指SQL語句中包含一些參數(shù)變量,在程序中可以為這些參數(shù)賦值,在程序運(yùn)行過程中,各個參數(shù)值是變化的。TQuery部件的SQL 屬性中的SQL語句的編寫也有兩種方法,一種方法是在程序設(shè)置階段便將相應(yīng)的SQL語句寫入到TQuery的SQL屬性中,另一種方法是在Delphi開發(fā)的應(yīng)用程序?qū)QL語句,包含在Pascal代碼單元中。
在SQL編程中使用TQuery部件的具體方法步驟如下:
①為TQuery部件設(shè)置DatabaseName屬性,它可以是用BDE建立的數(shù)據(jù)庫的別名,或桌面數(shù)據(jù)庫系統(tǒng)中的目錄名或數(shù)據(jù)庫服務(wù)器中的文件名,如果在應(yīng)用中使用了TDatabase 部件,那么TQuery部件的DatabaseName屬性可以是TDatabase部件中定義的一個數(shù)據(jù)庫別名。詳細(xì)情況請參看“TDatabase部件的使用”;
②為TQuery部件設(shè)置SQL屬性,TQuery部件的SQL屬性值就是應(yīng)用程序要執(zhí)行的SQL 命令文本,設(shè)置SQL屬性有兩種方法:
● 在程序設(shè)計(jì)過程中,我們可以通過對象瀏覽器(Object Inspector)編輯SQL屬性在Object Inspector中選擇SQL屬性,這樣會打開String List Editor窗口,在其中我們便可以編寫SQL命令,我還可以打開Visual Query Builder來編寫SQL命令 (只有Delphi的客戶/服務(wù)器版本才具有這一工具)。
● 將SQL命令包含在Pascal代碼單元中
在程序運(yùn)行過程中,首先調(diào)用TQuery部件的Close方法關(guān)閉當(dāng)前的TQuery部件,然后調(diào)用Clear方法清除SQL屬性,并說明新的SQL命令文本,然后調(diào)用Add方法,將新的SQL命令文本加入到SQL屬性中。
③通過調(diào)用TQuery部件的Open方法或ExecSQl方法執(zhí)行 SQL 命令。 Open 方法只執(zhí)行Select命令,ExecSQL方法還可以執(zhí)行其它的SQL命令。Open方法和ExecSQL 方法的區(qū)別我們在后面的章節(jié)里會進(jìn)一步地加以討論的。
如果使用動態(tài)SQL語句,首先調(diào)用prepare方法,給動態(tài)SQL語句中的參數(shù)賦值,然后再調(diào)用Open方法或ExecSQL方法。調(diào)用propare 方法并不是必須的,但是對于要多次執(zhí)行TQuery部件中SQL屬性中的動態(tài)SQL語句,調(diào)用Prepare可以大大提高TQuery部件執(zhí)行SQL語句的性能?!?
2.2 在TQuery部件中編寫簡單的SQL查詢命令
在這一節(jié)里我們將學(xué)習(xí)如何使用TQuery部件編寫簡單的SQL查詢命令,并在Delphi 應(yīng)用程序中實(shí)現(xiàn)SQL查詢。
例如,如果我們想查詢出表Customer.DB中客戶的編號和公司名稱,我們按下列步驟來實(shí)現(xiàn):
①在應(yīng)用窗體中放置一個TQuery部件、一個TDataSource部件一個TDataGrid部件,并將它們連接起來
②設(shè)置窗體TQuery 部件Query1的DatabaseName屬性值為DBDEMOS
③雙擊Object Inspector窗口中Query1的SQL 屬性, Delphi 將顯示 String List Editor窗口。
④在圖17.3中的窗口中輸入SQL語句:
Select CustNo,Company From Custormer;
⑤單擊OK按鈕,關(guān)閉String List Editor窗口。
⑥設(shè)置Query的Open屬性為True。
3 SQL語言編程概述
在Delphi應(yīng)用程序中的SQL命令語句是包含在TQuery部件的SQL屬性中,TQuery部件的SQL屬性是TString類型的,也就是說SQL屬性值是一個字符串列表,這個字符串列表非常類似于一個字符串類型的數(shù)組,有關(guān)TString類型的信息請參看聯(lián)機(jī)幫助。在前一節(jié)里我們介紹了TQuery部件可以執(zhí)行兩種SQL語句:
● 靜態(tài)SQL語句
● 動態(tài)SQL語句
靜態(tài)SQL語句在程序設(shè)計(jì)時便已固定下來,它不包含任何參數(shù)和變量,例如下面的語句便是一條靜態(tài)SQL語句:
Select * From Cusromer Where CustNo = 1234;
而動態(tài)SQL語句,也被稱作參數(shù)化的語句,在其中間包含著表示字段名或表名的參數(shù),例如下面的語句是一條動態(tài)SQL語句:
Select * From Customer Where CustNo =: Number;
其中的變量Number便是一個參數(shù)變量,它由一個冒號引導(dǎo),在程序運(yùn)行過程中,必須要為該參數(shù)賦值,該條SQL語句才能正確執(zhí)行,每次運(yùn)行應(yīng)用程序時可以為該參數(shù)變量賦予不同的值。
3.1 SQL命令文本的編寫
1. 使用String List Editor編寫
我們要為TQuery部件的SQL屬性設(shè)置SQL命令文本時,可以在應(yīng)用窗體中選擇TQuery部件且雙擊Object Inspector窗口中的SQL屬性,這樣便打開了String List Editor 窗口,在該窗口中我們便可以編寫各種SQL命令,如圖17.3所示。
在編寫完適當(dāng)?shù)腟QL語句之后,選擇 OK 按鈕便可以將編輯器中的 SQL 命令文裝入到TQuery部件的SQL屬性中,選擇SAVE按鈕可以將編寫好的SQL命令保存到一個文件中供以后編程時使用。我們在編寫SQL命令文本時還可以選擇Load按鈕從一個 SQL 命令文件中調(diào)入SQL命令。在程序運(yùn)行過程中,要想設(shè)置TQuery部件的SQL屬性,必須首先調(diào)用Close方法,關(guān)閉TQuery部件,然后再調(diào)用Clear方法清除SQL屬性中現(xiàn)存的SQL命令語句,最后再調(diào)用Add方法為SQL屬性設(shè)置新的SQL命令語句。例如:
Query1.Close {關(guān)閉Query1)
Query1.SQL.Clear {清除SQL屬性中的SQL命令語句}
Query1.SQL.Add('Select * From Country');
Query1.SQL.Add('Where Name ="ARGENTINA" ');
在為TQuery部件設(shè)置SQL屬性時調(diào)用Close方法總是很安全的,如果TQuery部件已經(jīng)被關(guān)閉了,調(diào)用Close方法時不會產(chǎn)生任何影響。在應(yīng)用程序中為SQL屬性設(shè)置新的SQL 命令語句時,必須要調(diào)用Clear方法以清除SQL屬性中現(xiàn)存的SQL命令語句,如果不調(diào)用Clear方法,便調(diào)用Add方法向SQL屬性中設(shè)置SQL命令語句,那么新設(shè)置的SQL命令語句會追加在現(xiàn)存SQL命令語句后面,在程序運(yùn)行時常常會出現(xiàn)出乎意料的查詢結(jié)果甚至程序無法運(yùn)行下去。
在這里要特別注意的,一般情況下TQuery部件的SQL屬性只能包含一條完整的SQL語句,它不允許被設(shè)置成多條SQL語句。當(dāng)然有些數(shù)據(jù)庫服務(wù)器也支持在TQuery部件的SQL屬性中設(shè)置多條SQL語句,只要數(shù)據(jù)庫服務(wù)器允許這樣,我們在編程時可以為 SQL 屬性設(shè)置多條SQL語句。
2. 使用Visual Query Builder編寫
客戶/服務(wù)器版本的Delphi還包含一個可視化的查詢構(gòu)造器Visual Query Builder ,用這個可視化的工具我們只能編寫Select語句。在應(yīng)用程序窗體中選擇TQuery部件后,單擊鼠標(biāo)右鍵,彈出一個彈出式菜單,從中選擇Run Visual Query Builder后便會彈出一對話框提示你選擇要訪問的數(shù)據(jù)庫,選擇想要訪問的數(shù)據(jù)庫之后選擇OK按鈕,緊接著會出現(xiàn)一個彈出式對話框提示你選擇要查詢的數(shù)據(jù)庫表,一次可以選擇多個數(shù)據(jù)庫表,若要選擇多個數(shù)據(jù)庫表,每選擇一個表之后單擊Add按鈕,接著選擇另一個表,選擇完要查詢的表之后單擊Close按鈕,這樣,可視化的查詢構(gòu)造器中將會顯示出用戶選擇的數(shù)據(jù)庫表。
有關(guān)如何使用可視化的查詢構(gòu)造器Visual Query Builder 請參看聯(lián)機(jī)幫助信息, 在Visual Query Builder中構(gòu)造完一個查詢并退出Visual Query Builder時,其中的SQL 命令語句會自動地寫入相應(yīng)的TQuery部件的SQL屬性?!?
3.2 SQL程序的執(zhí)行
在為TQuery部件設(shè)置完SQL屬性的屬性值之后,也即編寫好適當(dāng)?shù)腟QL程序之后,可以有多種方式來執(zhí)行SQL程序。
在設(shè)計(jì)過程中,設(shè)置完TQuery部件的SQL屬性之后將其Active屬性的值置為True,這樣便可以執(zhí)行SQL屬性中的SQL程序,如果應(yīng)用中有與TQuery部件相連的數(shù)據(jù)瀏覽部件( 如TDDGrid TDBEdit等)那么在這些數(shù)據(jù)瀏覽部件中會顯示SQL程序的執(zhí)行結(jié)果。
在應(yīng)用程序運(yùn)行過程中,通過程序調(diào)用TQuery部件的Open方法或ExecSQL 方法可以執(zhí)行其SQL屬性中的SQL程序。Open方法和ExecSQL方法是不一樣的。大家在程序設(shè)計(jì)過程中一定要注意。Open方法只能用來執(zhí)行SQL語言的查詢語句(Select命令),并返回一個查詢結(jié)果集,而ExecSQL方法還可以用來執(zhí)行其它常用的SQL語句(如Insert、UPDATE、 DELETE等命令)例如:
Query1.Open (這樣會返回一個查詢結(jié)果集)
如果調(diào)用Open方法,而沒有查詢結(jié)果時,會出錯。此時應(yīng)該調(diào)用ExecSQL 方法來代替Open方法。如:
Query1.ExecSQL (沒有返回結(jié)果)
當(dāng)然在設(shè)計(jì)應(yīng)用程序時,程序設(shè)計(jì)人員是無法確定TQuery部件中的SQL 語句是否會返回一個查詢結(jié)果的。對于這種情況應(yīng)當(dāng)用Try…Except模塊來設(shè)計(jì)程序。在 Try 部分調(diào)用Open方法,而在Except部分調(diào)用ExceSQL方法,這樣才能保證程序的正確運(yùn)行。
例如:
Try
Query1.Open
Except
Query1.ExecSQL
End
在應(yīng)用程序中使用TQuery部件時,還可以設(shè)置它的UniDirectional屬性為True,這樣會加快檢索數(shù)據(jù)庫表的速度,但是這樣只能往一個方向移動記錄指針, 在缺省情況下,UniDirectional屬性的值為False。
3.3 通過TQuery部件如何獲得活動的數(shù)據(jù)
我們在前面的章節(jié)里介紹TTable部件時,我們知道通過TTable部件從數(shù)據(jù)庫中獲得的數(shù)據(jù)都是活動的,也就是說用戶可以直接通過數(shù)據(jù)瀏覽部件對這些數(shù)據(jù)進(jìn)行編輯修改。而通過TQuery部件可以獲得兩種類型的數(shù)據(jù):
● “活動”的數(shù)據(jù)
這種數(shù)據(jù)就跟通過TTable部件獲得的數(shù)據(jù)一樣,用戶可以通過數(shù)據(jù)瀏覽部件來編輯修改這些數(shù)據(jù),并且當(dāng)調(diào)用Post方法或當(dāng)焦點(diǎn)離開當(dāng)前的數(shù)據(jù)瀏覽部件時,用戶對數(shù)據(jù)的修改自動地被寫回到數(shù)據(jù)庫中,詳細(xì)情況請參看第四章“數(shù)據(jù)瀏覽部件的應(yīng)用及編程”。
● 非活動的數(shù)據(jù)(只讀數(shù)據(jù))
用戶通過數(shù)據(jù)瀏覽部件是不能修改其中的數(shù)據(jù)。在缺省情況下,通過TQuery部件獲得的查詢結(jié)果數(shù)據(jù)是只讀數(shù)據(jù),要想獲得“活動”的數(shù)據(jù),在應(yīng)用程序中必須要設(shè)置TQuery部件的RequestLive屬性值為True,然而并不是在任何情況下(通過設(shè)置RequestLive的屬值True)都可以獲得“活動”的數(shù)據(jù)的,要想獲得“活動”的數(shù)據(jù),除了將TQuery部件的RequestLive屬性為True外,BDE要能夠返回“活動”的數(shù)據(jù),相應(yīng)的SQL命令語句還要滿足附錄C中的語法規(guī)則和下列的約束條件:
TQuery部件獲得“活動”的查詢結(jié)果數(shù)據(jù)的約束條件:
當(dāng)查詢Paradox或dBASE數(shù)據(jù)庫中的表:
● 查詢只能涉及到一個單獨(dú)的表
● SQL語句中不能包含ORDER BY命令
● SQL語句中不能含聚集運(yùn)算符SUM或AVG
● 在Select后的字段列表中不能有計(jì)算字段
● 在Select語句WHERE部分只能包含字段值與常量的比較運(yùn)算,這些比較運(yùn)算符是: Like,>,<,>=,<=,各比較運(yùn)算之間可以有并和交運(yùn)算:AND和OR。
當(dāng)通過SQL語句查詢數(shù)據(jù)庫服務(wù)器中的數(shù)據(jù)庫表:
● 查詢只能涉及到一個單獨(dú)的表
● SQL語句中不能包含ORDER BY命令
● SQL語句中不能含聚集運(yùn)算符SUM或AVG運(yùn)算
另外,如果是查詢Sybase數(shù)據(jù)庫中的表,那么被查詢的表中只能有一個索引。
如果在應(yīng)用程序中要求TQuery部件返回一個“活動”的查詢結(jié)果數(shù)據(jù)集,但是SQL 命令語句不滿足上述約束條件時,對于本地?cái)?shù)據(jù)庫的SQL查詢,BDE只能返回只讀的數(shù)據(jù)集。對于數(shù)據(jù)庫服務(wù)器中的SQL查詢,只能返回錯誤的代碼。當(dāng)TQuery 部件返回一個“活動”的查詢結(jié)果數(shù)據(jù)集時,它的CanModify屬性的值會被設(shè)置成True。
表17.1 TQuery部件返回查詢結(jié)果數(shù)據(jù)的類型
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
RequestLive屬性值 CanModify屬性值 查詢結(jié)果的類型
────────────────────────────────
False False 只讀數(shù)據(jù)
True(SQL語句滿足約束條件) True “活動”數(shù)據(jù)
True(SQL語句不滿足約束條件) False 只讀數(shù)據(jù)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
當(dāng)TQuery部件返回只讀的查詢結(jié)果數(shù)據(jù)集,而用戶又希望修改這只讀的數(shù)據(jù)集時,一般這樣來處理,在應(yīng)用程序中另外增加一個 TQuery 部件 Query2( 假設(shè)獲得只讀結(jié)果的TQuery部件的名字是Query1),在Query2中設(shè)置修改語句UpDATE對Query1 中的數(shù)據(jù)進(jìn)行修改操作,這樣會實(shí)現(xiàn)對只讀數(shù)據(jù)的修改。
4 動態(tài)SQL語句的編程
在3節(jié)中,我們已經(jīng)介紹了動態(tài)SQL語句(又被稱為參數(shù)化的SQL語句),在其中包含在程序過程中可以變化的參數(shù),在實(shí)際的程序設(shè)計(jì)中使用得更多的是動態(tài)SQL語句,因而在這一節(jié)里我們重點(diǎn)介紹如何給動態(tài)SQL語句的參數(shù)賦值,以在應(yīng)用程序中靈活地使用SQL語句。動態(tài)SQL語句的編寫、執(zhí)行等等與17.3節(jié)中介紹的SQL語句的編寫、執(zhí)行是一樣的。
動態(tài)SQL語句中的參數(shù),我們可以通過兩種途徑來為它賦值:
1. 利用參數(shù)編輯器(Parameter Editor)來為參數(shù)賦值
具體方法是:選中TQuery部件,單擊鼠標(biāo)右鍵,然后從中選擇Define Parameters 便可以打開參數(shù)編輯器?!?
例如,在TQuery部件的SQL屬性中我們設(shè)置如下的SQL語句:
Setect * From Customer Where CustNO=:Number;
TQuery的DatabaseName屬性為DBDEMOS,其中Number為參數(shù)變量。我們便可以為參數(shù)Number賦值,在Datetype組合框中選擇該參數(shù)的數(shù)據(jù)類型為整數(shù)Integer,在Value編輯框中可以為參數(shù)Number賦一個值,也可以單擊Null Value檢查框?yàn)閰?shù)Number賦一個空值Null。給參數(shù)賦值之后,單擊OK按鈕,這樣TQuery部件中的SQL 查詢便準(zhǔn)備好了,而且參數(shù)值也被賦給了動態(tài)SQL語句中相應(yīng)的參數(shù),此時當(dāng)把TQuery 部件的Active屬性設(shè)置成True時,在與TQuery部件相連的數(shù)據(jù)瀏覽部件中會顯示出查詢結(jié)果,通過參數(shù)編輯器為參數(shù)賦值,這種方式缺乏應(yīng)有的靈活性,在實(shí)際應(yīng)用中用得較少,在實(shí)際應(yīng)用中程序設(shè)計(jì)人員希望用更靈活方便的方式為參數(shù)賦值,那就是我們接下來要介紹的另一種途徑:
2. 在運(yùn)行過程中,通過程序?yàn)閰?shù)賦值
用這種方式為參數(shù)賦值有三種方法:
①根據(jù)參數(shù)在SQL語句中出現(xiàn)的順序,設(shè)置TQuery部件的Params屬性值為參數(shù)賦值。
②直接根據(jù)SQL語句中各參數(shù)的名字,調(diào)用ParamByName方法來為各參數(shù)賦值。
③將TQuery部件的DataSource屬性設(shè)置為另一個數(shù)據(jù)源,這樣將另一個數(shù)據(jù)源中與當(dāng)前TQuery部件的SQL語句中的參數(shù)名相匹配的字段值賦給其對應(yīng)的參數(shù)。
這三種方法我們將在下面的三小節(jié)中具體地介紹
4.1 使用Params屬性為參數(shù)賦值
TQuery部件具有一個Params屬性,它們在設(shè)計(jì)時不可用,在程序運(yùn)行過程中可用,并且是動態(tài)建立的,當(dāng)為TQuery部件編寫動態(tài)SQL 語句時, Delphi 會自動地建立一個數(shù)組Params,數(shù)組Params是以0下標(biāo)開始的,依次對應(yīng)動態(tài)SQL 語句中的參數(shù), 也就是說動態(tài)SQL語句中第一個參數(shù)對應(yīng)Params[0],第二個參數(shù)對應(yīng)params[1],依此類推。
例如:一個TQuery部件Query1,我們?yōu)樗帉懙膭討B(tài)SQL語句是:
Insert Into Customer(CustNo,Name,Country)
Values(:CustNo,:Name, : Country)
對于上述這條動態(tài)SQL語句中的參數(shù),我們可以利用TQuery部件的params 屬性為參數(shù)賦值:Query1.params[0].AsString := "1988";
Query1.params[1].AsString := "Lichtenstein";
Query1.params[2].AsString := "USA";
上述語句將把"1988"賦給參數(shù):Cuse_No,"Lichtenstein"賦給參數(shù):Name,"USA"賦給參數(shù):Country。
4.2 使用ParamByName方法為參數(shù)賦值
ParamByName是一個函數(shù),用動態(tài)SQL語句中的參數(shù)作為調(diào)用ParamByName函數(shù)的參數(shù),這樣便可以為它們賦值,使用這種賦值方法,必須要知道動態(tài)SQL語句參數(shù)的名字。
例如在4.1節(jié)的例子中,也可以用下述方法給參數(shù)賦值:
Query1.ParamByName('CustNo').AsString := "1988";
Query1.ParamByName('Name').AsString := "Lichtenstein";
Query1.ParamByName('Country').AsString := "USA";
使用這種方法同樣可以為各參數(shù)賦值,而且更加直觀一些。
4.3 使用Datasource屬性為參數(shù)賦值
上述兩種方法的共同特點(diǎn)是:我們在為各參數(shù)賦值時,我們是知道各參數(shù)對應(yīng)的具體參數(shù)值的。而在具體的應(yīng)用程序中,有些參數(shù)值常常是無法確定的,例如參數(shù)值來自于另一個查詢結(jié)果,對于這種情況,Delphi提供了使用Datasource屬性為動態(tài)SQL 語句中尚存在沒有賦值的參數(shù)時, Delphi 會自動檢查 TQuery 部件的 Datasource 屬性, 如果為Datasource屬性設(shè)置了屬性值(該屬性的值是另一個TDatasource部件的名字),Delphi 會把沒有賦值的參數(shù)與TDatasource部件中的各字段比較,Delphi 會將相應(yīng)的字段值賦給與其相匹配的參數(shù),利用這種方法也能實(shí)現(xiàn)所謂的連接查詢,我們在學(xué)習(xí)使用TTable部件時,便會創(chuàng)建主要--明細(xì)型數(shù)據(jù)庫應(yīng)用,用TQuery部件創(chuàng)建的連接查詢與主要- -明細(xì)型應(yīng)用是相似的。
例如:在如圖17.7所示的應(yīng)用中,設(shè)置了下列部件:
● 一個TTable部件
名字為Cust,它的DatabaseName屬性為DEMOS,TableName屬性為Customer。
● 一個TDatasource部件
名字為Custsource,其Dataset屬性被設(shè)置為Cust。
● 一個TQuery部件
名字為ORDERS,其DatabaseName被設(shè)置為DEMOS,SQL屬性值為:
Select Orders.CustNo,Orders.OrderNo,Orders.SaleDate FROM Orders
WHERE Orders.CustNo =: CustNo
ORDERS的DataSouce屬性被設(shè)置為CustSource
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -