後一頁 前一頁 回目錄 回首頁 |
17.5 SQL程式設計實例 我們在學習了SQL程式的編寫方法之後,我們便可以著手建立自己的應用程式了, 通過建立應用程式我們對Delphi的強大功能就會有更深刻的印象,同時會進一步全面掌握有關SQL程式設計的知識,在本節中我們主要介紹兩個例子,前一個例子主要是用靜態的SQL語句程式設計,後一個例子是用動態SQL語句程式設計。 17.5.1 設計簡單的SQL程式編輯器 例17.1:在這個例子中,我們設計一個互動式的SQL程式編輯器, 在這個編輯器中,我們可以根據SQL語言的語法規則,編寫常用的SQL命令,並通過按一下編輯器中的有關的按鈕,直接執行編寫好的SQL命令,SQL命令的執行結果也會及時地通過一個TDBGrid 部件顯示出來。 表17.3 SQL編輯器中個主要部件的屬性 ──────────────────── 部 件 屬 性 值 ———————————————————— Form1 Caption=SQL程式編輯器 DBGrid1 DataSource=DataSource1 Button1 Caption=執行(&E) Button2 Caption=清除(&C) Button3 Caption=結束(&X) Button3 kind=bkClose Memo1 DataSource1 DataSet=Query1 Query1 DatabaseName=DEMOS ────────────────────
因為我們在設定Query1的DatabaseName屬性時將其設定為DEMOS, 所以我們設計的這個SQL程式編輯器只能對DEOMS中的資料庫表進行操作。 按一下按鈕Button1的事件處理過程代碼為:
程式清單17.1
procedure TForm1.Button1Click(Sender:TObject); begin Query1.close; Query1.SQL.clear; Query1.SQL.Add(Memo1.text); Query1.Open; end;
按一下按鈕Button2的事件處理過程為:
程式清單17.2
procedure TForm1.Button2Click(Sender:TObject); begin Query1.close; Query1.SQL.clear; Query1.ExceSQL; end;
下面我們對程式清單17.1和程式清單17.2中的程式代碼進行簡要的分析: 程式清單17.1中的程式代碼是用來執行查詢的。
Query1.close;
這一行程式是用來關閉Query1的,我們在前面的章節中介紹過,只有在呼叫close 方法將TQuery部件關閉之後,才能修改其SQL屬性值,執行close命令關閉查詢是很安全的,如果查詢已經被關閉了,呼叫該方法不會產生任何影響。
Query1.SQL.clear;
因為TQuery部件的SQL屬性只能包含一條SQL語句,呼叫Clear 方法的目的是為了清除SQL屬性原來的屬性值即原來的SQL命令語句,如果不呼叫clear方法清除原來的SQL命令語句,當在後面的程式中呼叫Add方法為SQL屬性設定新的SQL命令語句時,Delphi 會將新的SQL命令語句加在原來的SQL命令語句,這樣使得SQL屬性中包含兩條獨立的SQL語句,這是不允許的。
Query1.SQL.Add(Memo.text);
該條命令是將SQL編輯器的編輯區內的內容(TMemo部件Memo1)設定成Query1的SQL屬性值。
Query1.open;
該語句用來執行Query1中的SQL命令語句, 如果執行查詢從資料庫中獲得查詢結果,查詢結果會在數據網格DBGrid1中顯示出來。 程式清單2是用來清除查詢的, 其前兩行語句跟程式清單1中的代碼是一樣的。Query1.ExecSQL有一些特別,呼叫ExecSQL方法也是打開Query1,ExecSQL方法與open方法不一樣的,請參看前面的章節,當Query1中SQL屬性值為空時,即沒有SQL語句時,只能呼叫ExecSQL方法來打開Query1,如果呼叫 open 方法會返回一個錯誤。 在執行完 Query1.ExecSQL語句之後,應用程式將會清除數據網格DBGrid1中的所有內容。 17.5.2 設計一個資料庫查詢器 例17.2:在資料庫查詢器中,用戶可以選擇要查詢的資料庫,查詢資料庫中的那一個表、根據資料庫表中那一個欄位進行查詢,並且可以方便地指定查詢條件,指定查詢條件主要包括指定邏輯運算符(=、>、<、<=、>=、like、in、NOT like、NOT in)和欄位值。 例子全部的程式清單如下: unit main;
interface
uses SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DB, DBTables, Buttons, ComCtrls, Tabnotbk;
type TQueryForm = class(TForm) BitBtn1: TBitBtn; DataSource1: TDataSource; Table1: TTable; GroupBox1: TGroupBox; CheckBox1: TCheckBox; CheckBox2: TCheckBox; PageControl1: TPageControl; TabSheet1: TTabSheet; Label5: TLabel; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; ListBox1: TListBox; ListBox2: TListBox; ListBox3: TListBox; Edit1: TEdit; ComboBox1: TComboBox; BitBtn2: TBitBtn; TabSheet2: TTabSheet; Memo1: TMemo; procedure FormCreate(Sender: TObject); procedure ListBox1Click(Sender: TObject); procedure ListBox2Click(Sender: TObject); procedure BitBtn2Click(Sender: TObject); end;
var QueryForm: TQueryForm;
implementation
{$R *.DFM}
uses RSLTFORM;
procedure TQueryForm.FormCreate(Sender: TObject); begin Screen.Cursor := crHourglass;
{ Populate the alias list }
with ListBox1 do begin Items.Clear; Session.GetAliasNames(Items); end;
{ Make sure there are aliases defined }
Screen.Cursor := crDefault; if ListBox1.Items.Count < 1 then MessageDlg( 'There are no database aliases currently defined. You need at least one alias to use this demonstration.', mtError, [mbOK], 0 );
{ Default the drop-down list to the first value in the list } ComboBox1.ItemIndex := 0; end;
procedure TQueryForm.ListBox1Click(Sender: TObject); var strValue: string; { Holds the alias selected by the user } bIsLocal: Boolean; { Indicates whether or not an alias is local } slParams: TStringList; { Holds the parameters of the selected alias } iCounter: Integer; { An integer counter variable for loops} begin
{ Determine the alias name selected by the user }
with ListBox1 do strValue := Items.Strings[ItemIndex];
{ Get the names of the tables in the alias and put them in the appropriate list box, making sure the user's choices are reflected in the list. }
ListBox2.Items.Clear; Session.GetTableNames(strValue, { alias to enumerate } '', { pattern to match } CheckBox1.Checked, { show extensions flag } CheckBox2.Checked, { show system tables flag } ListBox2.Items); { target for table list }
{ Make sure there are tables defined in the alias. If not, show an error; otherwise, clear the list box. }
Screen.Cursor := crDefault; if ListBox2.Items.Count < 1 then MessageDlg('There are no tables in the alias you selected. Please choose another', mtError, [mbOK], 0 );
ListBox3.Items.Clear; end;
procedure TQueryForm.ListBox2Click(Sender: TObject); begin Screen.Cursor := crHourglass; try { First, disable the TTable object. } if Table1.Active then Table1.Close;
{ Open the selected table }
with ListBox1 do Table1.DatabaseName := Items.Strings[ItemIndex];
with ListBox2 do Table1.TableName := Items.Strings[ItemIndex];
{ Open the table and put a list of the field names in the Fields list box. }
Table1.Open; if Table1.Active then Table1.GetFieldNames(ListBox3.Items); finally Screen.Cursor := crDefault; end; end;
procedure TQueryForm.BitBtn2Click(Sender: TObject); var strAlias, { Alias name selected by the user } strTable, { Table name selected by the user } strField, { Field name selected by the user } strValue, { Field Value entered by the user } strWhere, { WHERE clause for the user's query } strQuote, { Holds quotes is the query field is text } strQuery: string; { String used to construct the query } frmQuery: TResultForm; { The Results form } type
{ The following type is used with the Type drop-down list. The text values corresponding with each item is described in comments, along with the relevant SQL operators. }
etSQLOps = (soNoCondition, { not field conditions: no WHERE clause } soEqual, { equals: = } soNotEqual, { is not equal to: <> } soLessThan, { is less than: < } soLessEqual, { is less than or equal to: <= } soMoreThan, { is greater than: > } soMoreEqual, { is greater than or equal to: >= } soStartsWith, { starts with: LIKE xx% } soNoStartsWith, { doesn't start with: NOT LIKE xx% } soEndsWith, { ends with: LIKE %xx } soNoEndsWith, { doesn't end with: NOT LIKE %xx } soContains, { contains: LIKE %xx% } soNoContains, { doesn't contain: NOT LIKE %xx% } soBlank, { is blank: } soNotBlank, { is not blank: } soInside, { contains only: IN ( xx, yy, zz ) } soOutside); { doesn't contain: NOT IN (xx, yy, zz) } begin
{ Initialize the variables needed to run the query }
with ListBox1 do if ItemIndex = -1 then raise Exception.Create('Can''t Run Query: No Alias Selected') else strAlias := Items.Strings[ItemIndex];
with ListBox2 do if ItemIndex = -1 then raise Exception.Create('Can''t Run Query: No Table Selected') else strTable := Items.Strings[ItemIndex];
with ListBox3 do if ItemIndex = -1 then begin if ComboBox1.ItemIndex > Ord(soNocondition) then raise Exception.Create('Can''t Run Query: No Field Selected') else strField := ''; end else strField := Items.Strings[ItemIndex];
if (Edit1.Text = '') and (ComboBox1.ItemIndex > Ord(soNoCondition)) and (ComboBox1.ItemIndex < Ord(soBlank)) then raise Exception.create('Can''t Run Query: No Search Value Entered') else strValue := Edit1.Text;
{ See if the field being search is a string field. If so, then pad the quote string with quotation marks; otherwise, set it to a null value. }
if strField <> '' then with Table1.FieldByName(strField) do if (DataType = ftString) or (DataType = ftMemo) then strQuote := '"' else strQuote := '';
{ Construct the WHERE clause of the query based on the user's choice in Type. }
case etSQLOps(ComboBox1.ItemIndex) of soNoCondition: strWhere := ''; soEqual: strWhere := strField + ' = ' + strQuote + strValue+ strQuote; soNotEqual: strWhere := strField + ' <> ' + strQuote + strValue + strQuote; soLessThan: strWhere := strField + ' < ' + strQuote + strValue + strQuote; soLessEqual: strWhere := strField + ' <= ' + strQuote + strValue + strQuote; soMoreThan: strWhere := strField + ' > ' + strQuote + strValue + strQuote; soMoreEqual: strWhere := strField + ' >= ' + strQuote + strValue + strQuote; soStartsWith: strWhere := strField + ' LIKE ' + strQuote + strValue + '%' + strQuote; soNoStartsWith: strWhere := strField + ' NOT LIKE ' + strQuote + strValue + '%' + strQuote; soEndsWith: strWhere := strField + ' LIKE ' + strQuote + '%' + strValue + strQuote; soNoEndsWith: strWhere := strField + ' NOT LIKE ' + strQuote + '%' + strValue + strQuote; soContains: strWhere := strField + ' LIKE '+ strQuote+'%'+ strValue + '%' + strQuote; soNoContains: strWhere := strField + ' NOT LIKE ' + strQuote + '%' + strValue + '%' + strQuote; soBlank: strWhere := strField + ' IS NULL'; soNotBlank: strWhere := strField + ' IS NOT NULL'; end;
if ComboBox1.ItemIndex = Ord(soNoCondition) then strQuery := 'SELECT * FROM "' + strTable + '"' else if Table1.FieldByName(strField).DataType = ftString then strQuery := 'SELECT * FROM "' + strTable + '" t WHERE t.' + strWhere else strQuery := 'SELECT * FROM "' + strTable + '" t WHERE t.' + strWhere;
{ Create an instance of the browser form. } frmQuery := TResultForm.Create(Application);
{ Use a resource protection block in case an exception is raised. This ensures that the memory allocated for the Results form is released. } try with frmQuery do begin Screen.Cursor := crHourglass; if Query1.Active then Query1.Close; Query1.DatabaseName := strAlias; {set the alias the query poitns to} Query1.SQL.clear; { empty existing SQL in the query } Query1.SQL.Add(strQuery); { add query string to query object } Query1.Active := True; { try to run the query } Screen.Cursor := crDefault;
if Query1.Active then begin { If the query didn't return any records, there's no point in displaying the form. In that event, raise an exception. } if Query1.RecordCount < 1 then raise Exception.create('No records matched your criteria. Please try again.' );
{ write a message to the browse form's status line } if strField = '' then Panel3.Caption := 'Now showing all records from ' + strTable + '...' else Panel3.Caption := 'Now showing '+ strTable +' where '+ strField +' contains values equal to '+ strValue + '...';
{ show the form } ShowModal; end; end; finally frmQuery.Free; end; end;
end.
unit RSLTFORM;
interface
uses SysUtils, Windows, Messages, Classes, Graphics, Controls, StdCtrls, DB, Forms, DBCtrls, DBGrids, DBTables, Buttons, Grids, ExtCtrls, Dialogs;
type TResultForm = class(TForm) DBGrid1: TDBGrid; DBNavigator: TDBNavigator; Panel1: TPanel; DataSource1: TDataSource; Panel2: TPanel; Panel3: TPanel; Query1: TQuery; SpeedButton2: TSpeedButton; Panel4: TPanel; SpeedButton1: TSpeedButton; procedure SpeedButton1Click(Sender: TObject); procedure SpeedButton2Click(Sender: TObject); end;
var ResultForm: TResultForm;
implementation
{$R *.DFM}
procedure TResultForm.SpeedButton1Click(Sender: TObject); begin Close; end;
procedure TResultForm.SpeedButton2Click(Sender: TObject); var strText: string; { Variable to hold display text } iCounter: Integer; { Loop counter variable } begin
{ Build a string containing the query }
strText := ''; for iCounter := 0 to Query1.SQL.Count - 1 do strText := strText + Query1.SQL[iCounter];
{ Display the query text }
MessageDlg('The underlying query is: ' + #10 + #10 + strText, mtInformation, [mbOK], 0 ); end;
end.
|
後一頁 前一頁 回目錄 回首頁 |