多层数据库开发九:查询数据库
2006-02-04 13:55:41 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ょ紓宥咃躬瀵鎮㈤崗灏栨嫽闁诲酣娼ф竟濠偽i鍓х<闁绘劦鍓欓崝銈囩磽瀹ュ拑韬€殿喖顭烽幃銏ゅ礂鐏忔牗瀚介梺璇查叄濞佳勭珶婵犲伣锝夘敊閸撗咃紲闂佺粯鍔﹂崜娆撳礉閵堝洨纾界€广儱鎷戦煬顒傗偓娈垮枛椤兘骞冮姀銈呯閻忓繑鐗楃€氫粙姊虹拠鏌ュ弰婵炰匠鍕彾濠电姴浼i敐澶樻晩闁告挆鍜冪床闂備胶绮崝锕傚礈濞嗘挸绀夐柕鍫濇川绾剧晫鈧箍鍎遍幏鎴︾叕椤掑倵鍋撳▓鍨灈妞ゎ厾鍏橀獮鍐閵堝懐顦ч柣蹇撶箲閻楁鈧矮绮欏铏规嫚閺屻儱寮板┑鐐板尃閸曨厾褰炬繝鐢靛Т娴硷綁鏁愭径妯绘櫓闂佸憡鎸嗛崪鍐簥闂傚倷娴囬鏍垂鎼淬劌绀冮柨婵嗘閻﹂亶姊婚崒娆掑厡妞ゃ垹锕ら埢宥夊即閵忕姷顔夐梺鎼炲労閸撴瑩鎮橀幎鑺ョ厸闁告劑鍔庢晶鏇犵磼閳ь剟宕橀埞澶哥盎闂婎偄娲ゅù鐑剿囬敃鈧湁婵犲﹤鐗忛悾娲煛鐏炶濡奸柍瑙勫灴瀹曞崬鈻庤箛鎾寸槗缂傚倸鍊烽梽宥夊礉鎼达絽鍨濇い鏍仜妗呴梺鍛婃处閸ㄦ壆绮婚幎鑺ュ€甸柨婵嗙凹缁ㄨ棄霉閻樿崵鐣烘慨濠冩そ濡啫鈽夊▎鎰€烽梺璇插閻噣宕¢幎鑺ュ仒妞ゆ洍鍋撶€规洖鐖奸、妤佸緞鐎n偅鐝┑鐘愁問閸n垳寰婇崜褉鍋撶粭娑樻搐缁犳煡鏌涢妷顔煎闁藉啰鍠栭弻锝夊棘閹稿孩鍠愰梺鑽ゅ枎缂嶅﹪寮诲☉鈶┾偓锕傚箣濠靛洨浜俊鐐€ら崜娆撴偋閸℃稈鈧棃宕橀鍢壯囧箹缁厜鍋撻懠顒€鍤紓鍌氬€风欢锟犲窗濡ゅ懎绠伴柟闂寸劍閸嬧晠鏌i幋锝嗩棄缁绢厸鍋撻梻浣虹帛閸旀洜绮旈棃娴虫盯宕橀鍏兼К闂侀€炲苯澧柕鍥у楠炴帡骞嬪┑鎰磻闁诲氦顫夐幐椋庣矆娓氣偓閸╃偤骞嬮敂钘変汗闂佸湱绮敮鈺傚閳ь剛绱撴担鐟板姢鐟滄壆鍋熼崚鎺戔枎閹惧疇鎽曞┑鐐村灦閻喖鈻介鍫熺厵閻熸瑥瀚慨鍥ㄣ亜閵夛妇绠炴慨濠冩そ閺屽懘鎮欓懠璺侯伃婵犫拃鍌氬祮闁哄瞼鍠栭幖褰掝敃閿濆懐锛撻梻浣瑰缁诲嫰宕戝☉銏犵厴闁瑰濮崑鎾绘晲鎼存ê浜炬い鎾寸⊕濞呭﹪鏌$仦鐣屝f繛纰变邯楠炲繒浠﹂挊澶婅厫闂傚倷鐒﹂惇褰掑磹閺囥垹绠犻柟閭﹀枟椤洟鏌熼幆褏鎽犲┑顖涙尦閺屾盯骞橀弶鎴犵シ闂佸憡鎸稿畷顒勨€旈崘顔嘉ч柛鈩冾殘娴犳悂姊洪懡銈呮毐闁哄懏鐩幃楣冩倻閽樺)銊ф喐婢舵劕纾婚柟鍓х帛閺呮煡骞栫划鐟板⒉闁诲繐绉瑰铏圭磼濡闉嶅┑鐐插级閿曘垺淇婇悽绋跨妞ゆ牗姘ㄩ悿鈧梻鍌氬€搁悧濠勭矙閹邦喛濮抽柤娴嬫櫇绾捐棄霉閿濆牊顥夐柣鎾村姈閹便劌螣缁嬪灝顬嬪┑鈥冲级閸旀瑩鐛Ο鍏煎珰闁肩⒈鍓﹀Σ浼存⒒娴gǹ鏆遍柟纰卞亰瀹曟劖绻濆В绋挎喘瀵埖鎯旈幘瀛樻澑婵$偑鍊栧濠氬Υ鐎n亶鍟呴柕澶涜礋娴滄粍銇勯幘璺轰粶婵℃彃顭烽弻锝夋晲閸パ冨箣濡ょ姷鍋炵敮锟犵嵁鐎n喖绫嶉柍褜鍓熼幃妤佺節濮橆厸鎷洪柣鐔哥懃鐎氼參宕曞Δ鍛厱婵☆垵銆€閸嬫捇鎮㈤幓鎺戠阀濠电姷鏁告慨鐑藉极閸涘﹥鍙忛柣鎴f閺嬩線鏌涘☉姗堟敾闁告瑥绻戦妵鍕箻閸楃偟浠肩紒鐐劤椤兘寮婚悢鐓庣鐟滃繒鏁☉銏$厓闂佸灝顑呴悘锕傛煏閸パ冾伃妤犵偞甯″畷鍗烆渻閹屾缂傚倸鍊搁崐椋庣矆娓氣偓钘濋梺顒€绉撮弸浣糕攽閻樿櫕鐨戠€规挷绶氶弻娑㈠焺閸愵亖濮囬梺绋匡功閸忔﹢寮诲☉妯锋斀闁糕剝顨忔导鈧俊鐐€栧褰掑礉閺囥垹鐓橀柟杈鹃檮閸婂鏌涢妷銏℃珖閺嶏繝姊绘担鍛婂暈闁圭ǹ顭烽幃鐑芥晜閻e备鏀虫繝鐢靛Т濞诧箓宕甸崘顔界厓闁告繂瀚弳鐔兼煥濞戞瑧鐭掓慨濠囩細閵囨劙骞掗幋婊冩瀳闂備礁鎲¢悷銉︻殽閹间礁鐓濋柟鐐灱閸亪鏌涢銈呮灁闁告ɑ鎮傞弻锝堢疀閺囩偘鎴风紒缁㈠幖閻栫厧鐣烽幋锕€绠婚悹鍥皺閻も偓濠电偠鎻徊浠嬪箟閿熺姴纾规い鏍仦閳锋垹鐥鐐村櫣濞存粌缍婇幃璺衡槈閺嵮冨Е闂佺硶鏂侀崑鎾愁渻閵堝棗绗掗柛鐕佸亰閹啫煤椤忓懐鍘告繛杈剧到濠€杈ㄦ櫠椤忓牊鐓冮悷娆忓閻忔挳鏌熼鐣屾噰鐎殿喖鐖奸獮瀣偐鏉堫煈鏁囬梻鍌氬€风粈浣革耿鏉堛劎浠氶梻浣侯攰婵倗鍒掓惔銊ョ闁圭儤顨呯猾宥夋煕椤愩倕鏋庡ù鐘烘缁辨挻鎷呴崜鎻掑壍濡炪倖娲樻繛濠囧极閸愵喖纾兼繛鎴炶壘楠炲牓姊绘担鍛婃儓婵炲眰鍨藉畷婵嗙暆閸曨剙鈧爼鏌eΟ鑲╁笡闁绘挻娲熼弻鐔兼嚋椤掆偓婵$厧霉濠婂嫬鍔ら柍瑙勫灴閺佸秹宕熼鈩冩線闂備胶枪閿曘儵鎮ч悩鑼殾婵犻潧顑嗛弲婵嬫煃瑜滈崜鐔煎灳閿曞倸閿ゆ俊銈傚亾闁绘帒鐏氶妵鍕箳瀹ュ牆鍘$紓浣哄Т婢т粙鍩€椤掆偓閸樻粓宕戦幘鏂ユ斀闁绘ǹ浜粣鏃堟煕鐎n偒娈旈柍瑙勫灴椤㈡瑧娑甸悜鐣屽弽婵犵數鍋涢幏鎴犲緤閸啣锝夊箛閺夎法顔婇梺鐟板暱绾绢參宕伴幘璇茬闁绘ḿ绮崵鎴︽煠缁嬭法浠涙慨锝嗗姍濮婂宕掑顑藉亾閻戣姤鍤勯柤鍝ユ暩娴犳碍绻濋悽闈涗粶妞ゆ洦鍙冨畷妤€螣娓氼垰娈ㄥ銈嗗姂閸婃牜鈧碍姘ㄩ埀顒傛嚀婢瑰﹪宕伴弽褉鏋旈柕濠忓缁♀偓闂佹眹鍨藉ḿ褎鐗庣紓浣哄亾濠㈡ḿ绮旈悷閭﹀殨闁哄被鍎辩粻鐢告煙閻戞ḿ绠橀柛鐐垫暬閺岋綁鎮╅悜姗嗕哗闁诲繐绻堥崝宀勵敊韫囨稑唯鐟滃宕戦幘鑸靛枂闁告洦鍓欑喊宥呪攽閳藉棗浜濈紒璇插€块敐鐐剁疀濞戞瑦鍎梺闈╁瘜閸橀箖鏁嶅⿰鍐f斀闁宠棄妫楅悘鐘绘煙绾板崬浜伴柨婵堝仜椤撳ジ宕堕埡鍐跨闯濠电偠鎻紞渚€藟閹捐绀夌€广儱顦伴悡娆戠磼鐎n亞浠㈤柡鍡涗憾閺岋綁鏁愰崶褍骞嬪Δ鐘靛仜椤戝寮崘顔肩劦妞ゆ帒鍊绘稉宥呪攽閻樺磭顣查柛瀣剁秮閺屾盯濡烽幋婵嗘殶濡ょ姴娲幃妤冩喆閸曨剙纰嶇紓浣割槹閹告娊鍨鹃弮鍫濈妞ゆ柨妲堣閺屾盯鍩勯崗鐙€浜Λ鍕吋閸モ晝锛濇繛杈剧到婢瑰﹪宕曢幇鐗堢厱闁靛ǹ鍎遍。宕囩磼椤旂⒈鍎忔い鎾冲悑瀵板嫮鈧綆浜栭崑鎾绘煥鐎c劋绨婚梺鐟版惈缁夊爼藝閿旈敮鍋撳▓鍨灈闁诲繑绻堥崺鐐哄箣閿曗偓閻擄繝鏌涢埄鍐炬畼濞寸媭鍨跺娲川婵犲海鍔堕梺鍛婃处閸欏骸煤閸涘﹣绻嗛柕鍫濈箳閸掍即鏌涢悤浣哥仸鐎规洘鍔欏畷褰掝敃閿濆懎浼庢繝纰樻閸ㄦ娊宕㈣缁傚秵銈i崘鈺佲偓鍨叏濡厧浜鹃悗姘炬嫹

核心提示: 第九章 查询数据库这一章介绍如何用TQuery构件查询数据库,如何通过SQL语句检索、插入、更新和删除数据,多层数据库开发九:查询数据库,SQL是符合工业标准的关系数据库语言,既可以用于远程的基于服务器的数据库,先要访问CanModify属性,只有当这个属性返回True时,如Sybase、Oracle、InterBa
第九章 查询数据库
这一章介绍如何用TQuery构件查询数据库,如何通过SQL语句检索、插入、更新和删除数据。SQL是符合工业标准的关系数据库语言,既可以用于远程的基于服务器的数据库,如Sybase、Oracle、InterBase和Microsoft SQL Server,也可以用于本地数据库如Paradox、dBASE、FoxPRo和access以及符合ODBC的数据库。
9.1 有效地使用查询
要有效地使用查询,必须熟悉标准的SQL语言以及所使用的服务器对SQL-92的限制和扩展,同时还要熟悉BDE。
9.1.1 查询桌面数据库
作为一个桌面开发者,应对表格、记录和字段的概念有所了解,又能熟练地使用TTable构件访问数据集中的每一条记录和每一个字段。
还可以使用TTable的范围和过滤功能在数据集中选择一部分记录,前者用于选择一块连续的记录,这些记录的值在一个特定的范围内; 后者用于选择非连续的记录,这些记录符合特定的条件。
所谓查询,非常类似于过滤,不同的是,查询要用到TQuery构件和SQL属性,有时候可能还要用到Params属性。从功能上讲,查询要比过滤复杂和强大些,这主要体现在:
.可以同时查询几个表格
.可以让查询结果中只包含部分字段,而过滤将返回所有字段。
查询也可以带参数,此时称为参数化查询。所谓参数,类似于变量,它的实际的值由BDE在执行SQL语句之前赋值。参数化查询的好处是,不需要修改SQL语句,只要修改参数的值,就能执行不同的查询功能。
大部分情况下,使用TQuery构件是为了在数据集中选择一部分字段和记录,但也可以使用SQL语句实现更新、插入和删除记录的功能,这是与TTable构件的一个区别。
9.1.2 查询远程数据库
要查询远程数据库,必须熟悉SQL语句以及服务器对标准SQL的限制和扩展。
TQuery构件的SQL属性用于指定要执行的SQL语句, Params属性用于提供参数。TQuery构件的功能并不只限于SQL语句和参数,它还是BDE与应用程序之间的接口。
应用程序可以通过TQuery构件的属性和方法来操纵SQL语句和参数。TQuery构件最终还是通过SQL Links与远程服务器进行通讯的,远程服务器把查询结果返回给BDE,再由BDE返回给应用程序。
9.2 可以查询哪些数据库
使用TQuery构件可以查询下列数据库:
一是Paradox或dBASE,这是通过BDE内置的Local SQL实现的。Local SQL是SQL-92标准的一个子集,支持大部分DML和DDL。
二是Local InterBase Server,这是通过InterBase引擎实现的。
三是远程数据库,如Oracle、Sybase、MS-SQL Server、InFormix、DB2和InterBase,不过,必须安装了相应的SQL Links驱动程序。不同的服务器对标准SQL都有不同的限制和扩展,要查询远程数据库之前,务必要查阅它的有关文档。
Delphi 4还支持异构查询,也就是说,可以同时查询几个不同类型的数据库。
9.3 使用TQuery构件的一般步骤
第一步是把一个TQuery构件放到数据模块上,设置它的DatabaseName属性指定要访问的数据库。对于Paradox和dBASE来说,DatabaseName属性可以设为BDE别名如DBEMOS、DefaultDD、IBLOCAL等,也可以是自定义的别名或者表所在的路径。
对于SQL表来说,DatabaseName属性只能设为BDE别名。如果应用程序使用TDatabase构件来连接数据库,DatabaseName属性也可以设为应用程序专用的别名。
第二步是设置SQL属性指定要执行的SQL语句,有必要的话还可以设置Params属性为SQL语句设置参数。
第三步是把TDataSource构件放到数据模块上,设置它的DataSet属性指定TQuery构件。再把TDBGrid构件放到窗体上,设置它的DataSource属性指定TDataSource构件。
第四步是执行SQL语句。要执行SQL语句有两种方式,一是在设计期把Active属性设为True,程序启动时将自动执行SQL语句。另一种方式是在运行期调用Open或ExecSQL执行SQL语句。如果希望返回查询结果,调用Open,如果不需要返回查询结果,调用ExecSQL。在调用Open或ExecSQL之前,最好先调用Prepare通知服务器作好准备。
执行SQL语句所返回的查询结果实际上是数据集中满足特定条件的记录所组成的子集,数据库栅格中只显示符合特定条件的记录。
9.4 指定要执行的SQL语句
可以设置SQL属性以指定要执行的SQL语句。在设计期,只要把Active属性设为True,就会自动执行SQL语句。在运行期,首先要调用Prepare通知服务器准备好,然后调用Open或ExecSQL执行SQL函数语句。
9.4.1 概述
SQL属性是一个典型的TStrings对象。SQL属性一般只包含一条完整的SQL语句,但可以分成几行写,TQuery构件会自动把几行字符串合并成一条SQL语句。
把SQL语句分成几行写的好处是,SQL语句的逻辑结构比较清楚,有利于今后维护和调试。所以,SQL语句的SELECT部分和WHERE部分一般都不在同一行上。
SQL语句可以不带参数,把字段名称和值固定在SQL语句中,例如,下面这个SQL语句就是硬写(Hard-Coded)的:
SELECT * FROM Customer WHERE CustNo = 1231
注意:如果要查询的是本地数据库,如果SQL语句中的字段名包含空格或其他特殊符号,必须用引号括起来,前面还要加上表格名和小圆点。
如果用参数的话,查询就灵活得多,应用程序不需要改写SQL语句本身,只要修改参数的值,就能使SQL语句执行不同的查询功能。在执行SQL语句之前,TQuery构件会自动把实际的值替换SQL语句中的参数,即使并没有显式地调用Prepare函数。
下面这条SQL语句是典型的参数化查询:
SELECT * FROM Customer WHERE CustNo = :Number
其中,Number就是一个参数,它的前面必须加冒号。在运行期,应用程序必须提供Number参数的值,每次执行SQL语句时,Number参数的值可以不同。
参数的值是通过TQuery的Params属性提供的。
9.4.2 在设计期指定SQL语句
在设计期,要指定SQL语句,可以在对象观察器中单击SQL属性边上的省略号按钮,弹出一个字符串列表编辑器,如图9.1所示。
图9.1 在设计期指定SQL语句
SQL语句可以分成几行写,但同一单词不能分开。一般情况下,SQL属性只能包含一条完整的SQL语句,但有些服务器允许同时执行几条SQL语句,这种情况下,可以输入多条SQL语句。
如果使用Delphi 4的Client/Server版本或Enterprise版本,也可以用SQLBuilder这个实用工具来建立SQL语句。要使用SQL Builder,在TQuery构件上单击鼠标右键,在弹出的菜单中选择“SQL Builder”命令。
9.4.3 在运行期指定SQL语句
在运行期,要指定SQL属性有三种方式,一是直接设置SQL属性,二是调用LoadFromFile从文件中读取SQL语句,或者从另一个TStrings对象中获得SQL语句。
在直接设置SQL属性之前,首先要调用Close函数。如果SQL属性中本来已经有了SQL语句,还要调用Clear把原来的SQL语句清除。
下面的代码演示了怎样在运行期直接设置SQL属性:
With CustomerQuery Do
Begin
Close;
With SQL Do
Begin
Clear;
Add('SELECT * FROM Customer');
Add('WHERE Company = 'Light Diver');
End;
Open;
End;
有时候,可能想在原来的SQL语句的基础上修改或增加一行,这时候就不能调用Clear把原来的SQL语句清掉,例如:
CustomerQuery.SQL[1] := 'WHERE Company = "Light Diver"';
也可以调用LoadFromFile从文件中获取SQL语句,这主要是因为TStrings对象支持文件操作。LoadFromFile会自动把原来的SQL语句清掉。
下面的代码是调用LoadFromFile的例子:
CustomerQuery.Close;
CustomerQuery.SQL.LoadFromFile('c:\orders.txt');
CustomerQuery.Open;
还可以从另一个TStrings对象中获取SQL语句,这就要调用TStrings的Assign函数。Assign 会自动把原来的SQL语句清空。
下面的代码是调用Assign的例子:
CustomerQuery.Close;
CustomerQuery.SQL.Assign(Memo1.Lines);
CustomerQuery.Open;
9.5 参 数
要使用参数化查询,必须在SQL语句中加入参数,例如:
INSERT INTO Country (Name, Capital, Population)
VALUES (:Name, :Capital, :Population)
其中,Name、Capital和Population是三个参数。
在执行上述SQL语句之前,应用程序应当调用Prepare函数通知BDE和服务器预先分配好资源,以加快查询速度。程序示例如下:
With Query1 Do
Begin
Close;
Unprepare;
ParamByName('Name').AsString := 'China';
ParamByName('Capital').AsString := 'Beijing';
ParamByName('Population').AsInteger := '120000';
Prepare;
Open;
End;
9.5.1 在设计期提供参数
要在设计期提供参数,单击Params属性边上的省略号按钮,弹出如图9.2所示的编辑器。
图9.2 在设计期设置Params属性
如果SQL语句中没有包含任何参数,图9.2所示的编辑器就是空白的。这个编辑器的工具栏总是禁止的,这意味着只能在SQL语句中加入参数。
选择其中一个参数(TParam对象),就可以在对象观察器中设置它的属性,或者建立事件句柄。TParam的主要属性有:
DataType属性用于指定参数的数据类型,它的初始值总是ftUnknown,必须设置每个参数的数据类型。
ParamType属性用于指定参数的使用类型,它的初始值也是ptUnknown。
Value属性用于给出参数的值。当然,也可以在运行期给出参数的值。
9.5.2 在运行期提供参数
要在运行期访问参数,有三种方式:
一是通过ParamByName函数按名称访问参数。
二是通过Params属性按序号访问参数。
三是通过TParams对象的ParamValues属性按名称访问参数。
假设一条SQL语句有三个参数:
INSERT INTO "COUNTRY.DB"
(Name, Capital, Continent)
VALUES (:Name, :Capital, :Continent)
下面这行代码通过ParamByName函数来访问其中的Capital参数:Query1.ParamByName('Capital').AsString := Edit1.Text;
下面这行代码通过Params属性来访问其中的Name参数:
Query1.Params[0].AsString := Edit1.Text;
下面这行代码通过TParams对象的ParamValues属性来同时访问三个参数:
Query1.Params.ParamValues['Country;Capital;Continent'] :=VarArrayOf([Edit1.Text, Edit2.Text, Edit3.Text]);
9.5.3 从另一个数据集获得参数
TQuery构件的DataSource属性用于指定一个数据源(TDataSource构件),如果应用程序既没有在设计期也没有在运行期给参数赋值,它就在这个数据源中查找与参数名匹配的字段,然后用这个字段的值作为参数的值。
假设一个数据模块叫LinkModule,上面有一个TQuery构件叫OrdersQuery,它的SQL语句如下:
SELECT CustNo, OrderNo, SaleDate
FROM Orders WHERE CustNo = :CustNo
另外,数据模块上还有下列构件:
.一个TTable构件叫CustomersTable,它的TableName属性设为CUSTOMER.DB。
.一个TDataSource构件叫Orderssource,它的DataSet属性设为OrdersQuery。
.一个TDataSource构件叫CustomersSource,它的DataSet属性设为CustomersTable。
.OrdersQuery的DataSource属性也设为CustomersSource。
假设应用程序有一个窗体叫LinkedQuery,窗体上有两个TDBGrid构件,它们的DataSource属性分别指定CustomersSource和OrdersSource。
如果编译和运行这个应用程序,将看到如图9.3所示的效果:
图9.3 从另一个数据集获得参数
这里简单解释一下图9.3。如果没有对SQL语句中的:CustNo参数赋值,OrdersQuery将试图从CustomersSource指定的数据集中查找匹配的字段。由于CustomersSource是从CUSTOMER.DB中获取数据的,而CUSTOMER.DB中恰好有一个CustNo字段,所以,:CustNo参数的值就是CustNo字段的值。如果您在显示CUSTOMER.DB的栅格中选择了另一条记录,将导致:CustNo参数的值跟着变化。
9.6 执 行 查 询
当指定了SQL语句并且提供了参数后,就可以执行查询了。如果是第一次执行查询,最好调用Prepare通知BDE或服务器做好准备,这样能加快查询的速度。
既可以在设计期执行查询,也可以在运行期执行查询。
要在设计期执行查询,只要把Active属性设为True。不过,在设计期能执行的SQL语句,仅限于SELECT语句,不能是INSERT、UPDATE或DELETE语句。
要在运行期执行查询,可以调用Open或ExecSQL函数,其中,Open适合于执行SELECT语句,而ExecSQL适合于执行INSERT、UPDATE或DELETE语句,后者不返回结果。
在调用Open或ExecSQL之前,首先要调用Close。程序示例如下:
CustomerQuery.Close;
CustomerQuery.Open;
如果在编程的时候无法确定是否要返回查询结果,可以用Try...Except结构把这两个过程都写进去,一般Open在Try部分调用,而ExecSQL在Except部分调用,这样,即使Open调用失败,也能执行到ExecSQL。程序示例如下:
Try
Query2.Open;
Except
On E: Exception Do
If not (E is ENoResultSet) then Raise;
End;
前面多次提到,在执行查询前最好先调用Prepare,尽管这并不是必须的。预先调用Prepare能够改善应用程序的性能。程序示例如下:
CustomerQuery.Close;
If not (CustomerQuery.Prepared) then
CustomerQuery.Prepare;
CustomerQuery.Open;
上述程序首先调用Close,然后检查Prepared属性,如果这个属性返回True,表示已经准备好,如果这个属性返回False,表示没有准备好,此时就要调用Prepare。
9.7 异 构 查 询
所谓异构查询,就是同时查询几个不同的数据库。这些数据库的类型可以不同。例如,可以同时查询Oracle数据库、Sybase数据库和本地的dBASE表。当程序执行异构查询的时候,BDE通过Local SQL来分析和处理这个查询,而不是用与服务器相关的特定的SQL语法。
建立一个异构查询的一般步骤是这样的:
第一步,把一个TQuery构件放到窗体或数据模块上,让DatabaseName属性空着。
第二步,为要查询的每一个数据库建立一个单独的BDE别名。
第三步,设置SQL属性以指定要执行的SQL语句。在SQL语句中,表的名字前要加别名和冒号,并且用双引号括起来。字段名前要加表名和小圆点。例如:
SELECT Customer.CustNo, Orders.OrderNo
FROM "Oracle1:CUSTOMER"
JOIN "Sybase1:ORDERS"
ON (Customer.CustNo = Orders.CustNo)
WHERE (Customer.CustNo = 1503)
第四步,设置Params属性提供参数。
第五步,调用Prepare通知BDE或服务器做好准备,然后调用Open或ExecSQL执行查询。如果显式地使用TDatabase构件连接数据库,并且设置了它的DatabaseName属性定义了应用程序专用的别名,在SQL语句中可以用专用的别名代替BDE别名。
9.8 查 询 结 果
默认情况下,查询结果是只读的。应用程序可以用数据控件去显示查询结果,但用户不能编辑数据。怎样才能使用户能够编辑数据呢?
要使用户能够编辑数据,必须把TQuery构件的RequestLive属性设为True。不过,把RequestLive属性设为True并不能保证查询结果一定是可以修改的,因为这还取决于查询使用的是Local SQL还是与服务器相关的SQL。
像查询Paradox或dBASE以及异构查询都是使用Local SQL,而查询远程服务器则使用与服务器相关的SQL。即使RequestLive属性设为True,而且查询的是本地数据库,但由于SELECT语句的文法不合适,BDE也将返回只读的查询结果。
因此,在编辑数据之前,先要访问CanModify属性。只有当这个属性返回True时,才表示查询结果是可编辑的。
更多精彩
赞助商链接