📄 ch16.htm
字号:
<TD ALIGN="LEFT">AND, OR, NOT</TD> <TD ALIGN="LEFT">Logical operators</TD> </TR></TABLE></P><P><B>Filtering with the Filter Property  </B>Earlier I said there aretwo ways of filtering a table. One way is by using the Filter property. To use this,all you have to do is type the filter statement directly into the Filter propertyin the Object Inspector at design time or assign a string value to this propertyat runtime. Naturally, you have to set the Filtered property to True as well.</P><P>To see what I mean, perform the following exercise. First, set up the core components:</P><DL> <DT></DT> <DD><B>1. </B>Place a Table component, a DataSource component, and a DBGrid component on a form. <P> <DD><B>2. </B>Click on the Table component and change its Database property to DBDEMOS, its TableName property to ORDERS.DB, and its Active property to True. <DT></DT> <DD><B>3. </B>Click on the DataSource component and change its DataSet property to Table1. <P> <DT></DT> <DD><B>4. </B>Click on the DBGrid component and change its DataSource property to DataSource1. Size the DBGrid as desired. <P> <DT></DT> <DD>At this point you should have a grid with data in it. Now you can get on with the business of filtering the table. <P> <DT></DT> <DD><B>5. </B>Enter the following in the Value column next to the Filter property: <P></DL><PRE>CustNo = 1384</PRE><DL> <DT></DT> <DD><B>6. </B>Set the Filtered property to True. <P></DL><P>Now the table should be showing only the orders for customer 1384. Spend sometime experimenting with the filter statement and observe the changes to the tableeach time a different statement is used. Try the following:</P><P><PRE>CustNo = 1510CustNo = 1384 and ShipDate < `1/1/94'CustNo = 1384 and ShipDate > `1/1/94'OrderNo > 1100 and OrderNo < 1125</PRE><PRE>Here you are making changes to the filter at design time, but it's more likely that you will change the filter dynamically at runtime. In that case, it's as simple as</PRE><PRE>Table1.Filter := `CustNo = 1510';</PRE><BLOCKQUOTE> <P><HR><strong>NOTE:</strong> If Filtered is set to True but the Filter property is blank, the entire dataset is returned just as if the table were not filtered. <HR></BLOCKQUOTE><P><B>Filtering with the OnFilterRecord Event  </B>The other way you canfilter a table is with the OnFilterRecord event. To generate an event handler forthis event, double-click in the Value column next to the OnFilterRecord event inthe Object Inspector. Delphi will create an event handler. You can then write codeto filter the table. Let's take the first filter example from earlier (CustNo = 1384)and filter using the OnFilterRecord event instead of the Filter property:</P><P><PRE>procedure TForm1.Table1FilterRecord(DataSet: TDataSet; var Accept: Boolean);var Value : Integer;begin Value := Table1.FieldByName(`CustNo').Value; Accept := (Value = 1384);end;</PRE><P>I've broken the actual code into two lines to make it more readable. The key elementhere is the Accept parameter. The OnFilterRecord event is called once for every rowin the table. Set the Accept parameter to True for any rows that you want to show.The preceding code sets Accept to True for any rows in which the CustNo field containsa value of 1384. Earlier I gave you four sample filters to try. The first two filterswould look like this if you were to use the OnFilterRecord event instead of the Filterproperty:</P><P><PRE>Accept := Table1.FieldByName(`CustNo').Value = 1510;Accept := (Table1.FieldByName(`CustNo').Value = 1384) and (Table1.FieldByName(`ShipDate').AsDateTime < StrToDate(`1/1/94'));</PRE><P>I'm sure you are thinking, "That's sort of messy." You're right. UsingOnFilterRecord means more work, but it's also much more powerful than filtering withjust the Filter property.</P><UL> <LI><B>Using the FilterOptions Property  </B>The FilterOptions property determines how the filter will be applied. This property is a set that can contain either or both foCaseInsensitive or foNoPartialCompare. By default this property is an empty set, which means that filters will be case sensitive and will enable partial comparisons. When partial comparisons are enabled, specifying a filter such as LastName := `M*' results in a dataset containing all records in which the LastName field begins with the letter <I>M</I>.</UL><H4>Finding Records</H4><P>You can search a table for certain records by several different methods. In fact,this section applies to all TDataSet descendants, not just TTable.</P><BLOCKQUOTE> <P><HR><strong>NOTE:</strong> As with filters, finding records in a client/server database is almost always carried out via SQL queries. Finding records using the TTable methods is primarily a local database operation. <HR></BLOCKQUOTE><P>To search a filtered dataset, you can use the FindFirst, FindNext, FindPrior,and FindLast methods. These methods are the best way to search a filtered datasetbecause the filter is reapplied each time one of these methods is called. Therefore,if records that previously did not match the filter have been modified so that theynow match the filter, they will be included in the dataset before the search is performed.</P><P>Another way to search a table is using the FindKey and GotoKey methods. Thesemethods require an index. The FindKey method searches the primary key field or fieldsfor a particular value. If a secondary key is in place, the secondary key field isused to perform the search. The following example sets a secondary key and then searchesfor a customer number of 1384:</P><P><PRE>Table1.IndexName := `CustNo';if not Table1.FindKey([1384]) then MessageBox(Handle, `Record Not Found', `Message', MB_OK);</PRE><P>A third way of searching a table includes using the Locate and Lookup methods.One advantage to these methods is that they don't require the table to be indexed.These methods differ in two ways. First, Locate will use the fastest method availableto search the table; if a table is indexed, Locate will use the index.</P><P>The second way these two methods differ is that the Lookup method will also returnthe values of the fields you have specified in the ResultFields parameter beforecalling Lookup. Both of these methods enable you to specify a field or fields tosearch and the search value. The following example illustrates the use of the Locatemethod:</P><P><PRE>var Options : TLocateOptions;begin Options := [loPartialKey]; if not Table1.Locate(`CustNo', `1384', Options) then MessageBox(Handle, `Record Not Found', `Message', MB_OK);end;</PRE><P>If the record is found, Locate returns True, and the cursor is updated to reflectthe record where the match was found.</P><P><H4>Master/Detail Tables</H4><P>Setting up a master/detail relationship with the Delphi Table component is easy.Let me explain a master/detail relationship and then I'll show you how to set upone. Let's say you have a table called CUSTOMER that contains information on yourcustomers. That table will likely be indexed on a field called CustNo.</P><P>Let's further assume that you have a table called ORDERS that contains a listof all orders placed by your customers. Naturally, this table would also have a CustNofield. Now let's say you want to browse the table containing all your customers.Wouldn't it be nice if you could see each customer's orders while you browse? A master/detailtable enables you to do that. Perform the following steps to get a good understandingof master/detail tables:</P><DL> <DT></DT> <DD><B>1. </B>Start with a new application. Place a Table component on the form. Set its properties as follows: <P></DL><P><TABLE BORDER="1"> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">Name</TD> <TD ALIGN="LEFT">Master</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">DatabaseName</TD> <TD ALIGN="LEFT">DBDEMOS</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">TableName</TD> <TD ALIGN="LEFT">customer.db</TD> </TR></TABLE></P><DL> <DD><B>2. </B>Place a DataSource component on the form and set its DataSet property to Master. <DT></DT> <DD><B>3. </B>Now place a second Table component on the form and change its Name property to Details. You'll set the rest of this table's properties in just a minute. <P> <DT></DT> <DD><B>4. </B>Place a second DataSource component on the form. Change its DataSource property to Details. <P> <DT></DT> <DD><B>5. </B>Click on the Details Table component. Change its properties as follows: <P></DL><P><TABLE BORDER="1"> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">DatabaseName</TD> <TD ALIGN="LEFT">DBDEMOS</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">TableName</TD> <TD ALIGN="LEFT">orders.db</TD> </TR> <TR ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT">MasterSource</TD> <TD ALIGN="LEFT">DataSource1</TD> </TR></TABLE></P><DL> <DT></DT> <DD><B>6. </B>Click on the ellipsis button next to the MasterFields property. The Field Link Designer dialog box is displayed. <P> <DT></DT> <DD><B>7. </B>At the top of the Field Link Designer dialog box is a combo box labeled Available Indexes. Select the CustNo index from this combo box. <P> <DT></DT> <DD><B>8. </B>Now both the Detail Fields list box and the Master Fields list box have a CustNo entry. Select CustNo in each of these list boxes and click the Add button to create the relationship. The Joined Fields list box shows that the two tables are joined by their CustNo fields. <P> <DT></DT> <DD><B>9. </B>Click OK to close the Field Link Designer dialog boxes. <P> <DT></DT> <DD><B>10. </B>Drop two DBGrid components on the form and link one to DataSource1 and the other to DataSource2. <P></DL><P><B>11. </B>Change the Active property of both tables to True. The Master tablewill show all customers, and the Details table will show the orders for each customer.</P><P>What you just did was create a relationship between the master table and the detailtable. This relationship joined these two tables through a common field: CustNo.To fully understand what this means, run the program and move from record to recordin the master table. As you select a customer name in the master table, you willsee only that customer's orders in the detail table.</P><P><H3><A NAME="Heading14"></A>The Query Component</H3><P>The Query component is the preferred method of accessing data in client/serverdatabases. The following sections describe the primary properties and methods ofthe TQuery class.</P><BLOCKQUOTE> <P><HR><strong>TIP:</strong> The Query component doesn't have a TableName property as the Table does. This means that at design time, you can't immediately see a list of tables for the current database. To see a list of tables, you can perform one of two tasks. First, you can temporarily drop a Table component on the form, set the DatabaseName property, and then view the list of tables in the TableName property. You also can select the Query component on the form, right-click on it, and then choose Explore from the context menu. This will take you to either the SQL Explorer (Client/Server version) or the BDE Administrator (Standard and Professional versions). You can use either tool to view the tables in a database. <HR></BLOCKQUOTE><H4>The SQL Property</H4><P>The SQL property is a TStringList that contains the SQL statements to execute.You can set the SQL property's value via the Object Inspector at design time or throughcode at runtime.</P><P>To set the value at design time, click the ellipsis button next to the SQL propertyin the Object Inspector. The String List Editor dialog box
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -