1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
---|
2 | <!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/doc/sql.doc:69 -->
|
---|
3 | <html>
|
---|
4 | <head>
|
---|
5 | <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
---|
6 | <title>SQL Module</title>
|
---|
7 | <style type="text/css"><!--
|
---|
8 | fn { margin-left: 1cm; text-indent: -1cm; }
|
---|
9 | a:link { color: #004faf; text-decoration: none }
|
---|
10 | a:visited { color: #672967; text-decoration: none }
|
---|
11 | body { background: #ffffff; color: black; }
|
---|
12 | --></style>
|
---|
13 | </head>
|
---|
14 | <body>
|
---|
15 |
|
---|
16 | <table border="0" cellpadding="0" cellspacing="0" width="100%">
|
---|
17 | <tr bgcolor="#E5E5E5">
|
---|
18 | <td valign=center>
|
---|
19 | <a href="index.html">
|
---|
20 | <font color="#004faf">Home</font></a>
|
---|
21 | | <a href="classes.html">
|
---|
22 | <font color="#004faf">All Classes</font></a>
|
---|
23 | | <a href="mainclasses.html">
|
---|
24 | <font color="#004faf">Main Classes</font></a>
|
---|
25 | | <a href="annotated.html">
|
---|
26 | <font color="#004faf">Annotated</font></a>
|
---|
27 | | <a href="groups.html">
|
---|
28 | <font color="#004faf">Grouped Classes</font></a>
|
---|
29 | | <a href="functions.html">
|
---|
30 | <font color="#004faf">Functions</font></a>
|
---|
31 | </td>
|
---|
32 | <td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>SQL Module</h1>
|
---|
33 |
|
---|
34 |
|
---|
35 | <p>
|
---|
36 | <p> <center><table cellpadding="4" cellspacing="2" border="0">
|
---|
37 | <tr bgcolor="#f0f0f0">
|
---|
38 | <td valign="top"><a href="qsql.html">QSql</a>
|
---|
39 | <td valign="top"><a href="qsqlcursor.html">QSqlCursor</a>
|
---|
40 | <td valign="top"><a href="qsqldatabase.html">QSqlDatabase</a>
|
---|
41 | <td valign="top"><a href="qsqldriver.html">QSqlDriver</a>
|
---|
42 | <td valign="top"><a href="qsqldriverplugin.html">QSqlDriverPlugin</a>
|
---|
43 | <tr bgcolor="#d0d0d0">
|
---|
44 | <td valign="top"><a href="qsqleditorfactory.html">QSqlEditorFactory</a>
|
---|
45 | <td valign="top"><a href="qsqlerror.html">QSqlError</a>
|
---|
46 | <td valign="top"><a href="qsqlfield.html">QSqlField</a>
|
---|
47 | <td valign="top"><a href="qsqlfieldinfo.html">QSqlFieldInfo</a>
|
---|
48 | <td valign="top"><a href="qsqlform.html">QSqlForm</a>
|
---|
49 | <tr bgcolor="#f0f0f0">
|
---|
50 | <td valign="top"><a href="qsqlindex.html">QSqlIndex</a>
|
---|
51 | <td valign="top"><a href="qsqlpropertymap.html">QSqlPropertyMap</a>
|
---|
52 | <td valign="top"><a href="qsqlquery.html">QSqlQuery</a>
|
---|
53 | <td valign="top"><a href="qsqlrecord.html">QSqlRecord</a>
|
---|
54 | <td valign="top"><a href="qsqlrecordinfo.html">QSqlRecordInfo</a>
|
---|
55 | <tr bgcolor="#d0d0d0">
|
---|
56 | <td valign="top"><a href="qsqlresult.html">QSqlResult</a>
|
---|
57 | <td valign="top"><a href="qsqlselectcursor.html">QSqlSelectCursor</a>
|
---|
58 | <td valign="top" colspan="3" rowspan="1"> See also: <a href="sql-driver.html">Supported Drivers</a>
|
---|
59 | </table></center>
|
---|
60 | <p> <!-- toc -->
|
---|
61 | <ul>
|
---|
62 | <li><a href="#1"> Introduction
|
---|
63 | </a>
|
---|
64 | <li><a href="#2"> SQL Module Architecture
|
---|
65 | </a>
|
---|
66 | <li><a href="#3"> SQL Driver Plugins
|
---|
67 | </a>
|
---|
68 | <li><a href="#4"> Connecting to Databases
|
---|
69 | </a>
|
---|
70 | <li><a href="#5"> Connecting to a Single Database
|
---|
71 | </a>
|
---|
72 | <ul>
|
---|
73 | <li><a href="#5-1"> Connecting to Multiple Databases
|
---|
74 | </a>
|
---|
75 | </ul>
|
---|
76 | <li><a href="#6"> Executing SQL Commands Using QSqlQuery
|
---|
77 | </a>
|
---|
78 | <ul>
|
---|
79 | <li><a href="#6-1"> Transactions
|
---|
80 | </a>
|
---|
81 | <li><a href="#6-2"> Basic Browsing
|
---|
82 | </a>
|
---|
83 | <li><a href="#6-3"> Basic Data Manipulation
|
---|
84 | </a>
|
---|
85 | <li><a href="#6-4"> Navigating Result Sets
|
---|
86 | </a>
|
---|
87 | </ul>
|
---|
88 | <li><a href="#7"> Using QSqlCursor
|
---|
89 | </a>
|
---|
90 | <ul>
|
---|
91 | <li><a href="#7-1"> Retrieving Records
|
---|
92 | </a>
|
---|
93 | <ul>
|
---|
94 | <li><a href="#7-1-1"> Sorting and Filtering Records
|
---|
95 | </a>
|
---|
96 | <li><a href="#7-1-2"> Extracting Data
|
---|
97 | </a>
|
---|
98 | </ul>
|
---|
99 | <li><a href="#7-2"> Manipulating Records
|
---|
100 | </a>
|
---|
101 | <ul>
|
---|
102 | <li><a href="#7-2-1"> Inserting Records
|
---|
103 | </a>
|
---|
104 | <li><a href="#7-2-2"> Updating Records
|
---|
105 | </a>
|
---|
106 | <li><a href="#7-2-3"> Deleting Records
|
---|
107 | </a>
|
---|
108 | </ul>
|
---|
109 | </ul>
|
---|
110 | <li><a href="#8"> Data-Aware Widgets
|
---|
111 | </a>
|
---|
112 | <ul>
|
---|
113 | <li><a href="#8-1"> Data-Aware Tables
|
---|
114 | </a>
|
---|
115 | <li><a href="#8-2"> Creating Data-Aware Forms
|
---|
116 | </a>
|
---|
117 | <ul>
|
---|
118 | <li><a href="#8-2-1"> Displaying a Record
|
---|
119 | </a>
|
---|
120 | <li><a href="#8-2-2"> Displaying a Record in a Data Form
|
---|
121 | </a>
|
---|
122 | <li><a href="#8-2-3"> Editing a Record
|
---|
123 | </a>
|
---|
124 | </ul>
|
---|
125 | <li><a href="#8-3"> Custom Editor Widgets
|
---|
126 | </a>
|
---|
127 | <ul>
|
---|
128 | <li><a href="#8-3-1"> Custom Editor Widgets for Tables
|
---|
129 | </a>
|
---|
130 | </ul>
|
---|
131 | </ul>
|
---|
132 | <li><a href="#9"> Subclassing QSqlCursor
|
---|
133 | </a>
|
---|
134 | <li><a href="#10"> The Example Tables
|
---|
135 | </a>
|
---|
136 | </ul>
|
---|
137 | <!-- endtoc -->
|
---|
138 |
|
---|
139 | <p> <a name="Introduction"></a>
|
---|
140 | <h2> Introduction
|
---|
141 | </h2>
|
---|
142 | <a name="1"></a><p> Qt's SQL classes help you provide seamless database integration to
|
---|
143 | your Qt applications.
|
---|
144 | <p> <blockquote>
|
---|
145 | This overview assumes that you have at least a basic knowledge of SQL.
|
---|
146 | You should be able to understand simple <tt>SELECT</tt>, <tt>INSERT</tt>, <tt>UPDATE</tt>
|
---|
147 | and <tt>DELETE</tt> commands. Although the <a href="qsqlcursor.html">QSqlCursor</a> class provides an
|
---|
148 | interface to database browsing and editing that does not <em>require</em> a
|
---|
149 | knowledge of SQL, a basic understanding of SQL is highly recommended. A
|
---|
150 | standard text covering SQL databases is <em>An Introduction to Database Systems (7th ed.)</em> by C. J. Date, ISBN 0201385902.
|
---|
151 | </blockquote>
|
---|
152 | <p> Whilst this module overview presents the classes from a purely
|
---|
153 | programmatic point of view the <a href="designer-manual.html">Qt
|
---|
154 | Designer</a> manual's "Creating Database Applications" chapter
|
---|
155 | takes a higher-level approach demonstrating how to set up
|
---|
156 | master-detail relationships between widgets, perform drilldown and
|
---|
157 | handle foreign key lookups.
|
---|
158 | <p> This document is divided into six sections:
|
---|
159 | <p> <a href="#Architecture">SQL Module Architecture</a>. This describes
|
---|
160 | how the classes fit together.
|
---|
161 | <p> <a href="#Connecting_to_Databases">Connecting to Databases</a>.
|
---|
162 | This section explains how to set up database connections using the <a href="qsqldatabase.html">QSqlDatabase</a> class.
|
---|
163 | <p> <a href="#Executing_SQL_commands">Executing SQL Commands</a>. This
|
---|
164 | section demonstrates how to issue the standard data manipulation
|
---|
165 | commands, <tt>SELECT</tt>, <tt>INSERT</tt>, <tt>UPDATE</tt> and <tt>DELETE</tt> on tables in
|
---|
166 | the database (although any valid SQL statement can be sent to the
|
---|
167 | database). The focus is purely on database interaction using <a href="qsqlquery.html">QSqlQuery</a>.
|
---|
168 | <p> <a href="#Using_QSqlCursor">Using Cursors</a>. This section explains
|
---|
169 | how to use the <a href="qsqlcursor.html">QSqlCursor</a> class which provides a simpler API than the
|
---|
170 | raw SQL used with <a href="qsqlquery.html">QSqlQuery</a>.
|
---|
171 | <p> <a href="#Data-Aware_Widgets">Data-Aware Widgets</a>. This section shows
|
---|
172 | how to programmatically link your database to the user interface. In
|
---|
173 | this section we introduce the <a href="qdatatable.html">QDataTable</a>, <a href="qsqlform.html">QSqlForm</a>, <a href="qsqlpropertymap.html">QSqlPropertyMap</a> and <a href="qsqleditorfactory.html">QSqlEditorFactory</a> classes and demonstrate how to
|
---|
174 | use custom data-aware widgets. <a href="designer-manual.html">Qt
|
---|
175 | Designer</a> provides an easy visual way of achieving the same
|
---|
176 | thing. See the <a href="designer-manual.html">Qt Designer</a> manual,
|
---|
177 | <a href="qdatabrowser.html">QDataBrowser</a> and <a href="qdataview.html">QDataView</a> for more information.
|
---|
178 | <p> <a href="#Subclassing_QSqlCursor">Subclassing QSqlCursor</a>. This
|
---|
179 | section gives examples of subclassing QSqlCursor. Subclassing can be
|
---|
180 | used to provide default and calculated values for fields (such as
|
---|
181 | auto-numbered primary index fields), and to display calculated data,
|
---|
182 | e.g. showing names rather than ids of foreign keys.
|
---|
183 | <p> All the examples in this document use the tables defined in the
|
---|
184 | <a href="#Example_Tables">Example Tables</a> section.
|
---|
185 | <p> <a name="Architecture"></a>
|
---|
186 | <h2> SQL Module Architecture
|
---|
187 | </h2>
|
---|
188 | <a name="2"></a><p> The SQL classes are divided into three layers:
|
---|
189 | <p> <em>User Interface Layer.</em> These classes provide data-aware widgets
|
---|
190 | that can be connected to tables or views in the database (by using a
|
---|
191 | <a href="qsqlcursor.html">QSqlCursor</a> as a data source). End users can interact directly with
|
---|
192 | these widgets to browse or edit data. <a href="designer-manual.html">Qt
|
---|
193 | Designer</a> is fully integrated with the SQL classes and can be
|
---|
194 | used to create data-aware forms. The data-aware widgets can also be
|
---|
195 | programmed directly with your own C++ code. The classes that support
|
---|
196 | this layer include <a href="qsqleditorfactory.html">QSqlEditorFactory</a>, <a href="qsqlform.html">QSqlForm</a>, <a href="qsqlpropertymap.html">QSqlPropertyMap</a>, <a href="qdatatable.html">QDataTable</a>, <a href="qdatabrowser.html">QDataBrowser</a> and <a href="qdataview.html">QDataView</a>.
|
---|
197 | <p> <em>SQL API Layer.</em> These classes provide access to databases.
|
---|
198 | Connections are made using the <a href="qsqldatabase.html">QSqlDatabase</a> class. Database
|
---|
199 | interaction is achieved either by using the <a href="qsqlquery.html">QSqlQuery</a> class and
|
---|
200 | executing SQL commands directly or by using the higher level <a href="qsqlcursor.html">QSqlCursor</a> class which composes SQL commands automatically. In
|
---|
201 | addition to <a href="qsqldatabase.html">QSqlDatabase</a>, <a href="qsqlcursor.html">QSqlCursor</a> and <a href="qsqlquery.html">QSqlQuery</a>, the SQL
|
---|
202 | API layer is supported by <a href="qsqlerror.html">QSqlError</a>, <a href="qsqlfield.html">QSqlField</a>, <a href="qsqlfieldinfo.html">QSqlFieldInfo</a>,
|
---|
203 | <a href="qsqlindex.html">QSqlIndex</a>, <a href="qsqlrecord.html">QSqlRecord</a> and <a href="qsqlrecordinfo.html">QSqlRecordInfo</a>.
|
---|
204 | <p> <em>Driver Layer.</em> This comprises three classes, <a href="qsqlresult.html">QSqlResult</a>, <a href="qsqldriver.html">QSqlDriver</a> and QSqlDriverFactoryInterface. This layer provides the
|
---|
205 | low level bridge between the database and the SQL classes. This layer
|
---|
206 | is <a href="sql-driver.html">documented separately</a> since it is
|
---|
207 | only relevant to driver writers, and is rarely used in standard
|
---|
208 | database application programming. See <a href="sql-driver.html">here</a> for more information on implementing a Qt SQL driver plugin.
|
---|
209 | <p> <a name="Plugins"></a>
|
---|
210 | <h2> SQL Driver Plugins
|
---|
211 | </h2>
|
---|
212 | <a name="3"></a><p> The Qt SQL module can dynamically load new drivers at runtime using
|
---|
213 | the <a href="plugins-howto.html">Plugins</a>.
|
---|
214 | <p> The <a href="sql-driver.html">SQL driver documentation</a> describes
|
---|
215 | how to build plugins for specific database management systems.
|
---|
216 | <p> Once a plugin is built, Qt will automatically load it, and the driver
|
---|
217 | will be available for use by <a href="qsqldatabase.html">QSqlDatabase</a> (see <a href="qsqldatabase.html#drivers">QSqlDatabase::drivers</a>()
|
---|
218 | for more information).
|
---|
219 | <p> <a name="Connecting_to_Databases"></a>
|
---|
220 | <h2> Connecting to Databases
|
---|
221 | </h2>
|
---|
222 | <a name="4"></a><p> At least one database connection must be created and opened before the
|
---|
223 | <a href="qsqlquery.html">QSqlQuery</a> or <a href="qsqlcursor.html">QSqlCursor</a> classes can be used.
|
---|
224 | <p> If the application only needs a single database connection, the <a href="qsqldatabase.html">QSqlDatabase</a> class can create a connection which is used by default
|
---|
225 | for all SQL operations. If multiple database connections are required
|
---|
226 | these can easily be set up.
|
---|
227 | <p> <a href="qsqldatabase.html">QSqlDatabase</a> requires the <a href="qsqldatabase-h.html">qsqldatabase.h</a> header file.
|
---|
228 | <p> <a name="Connecting_to_a_Single_Database"></a>
|
---|
229 | <h2> Connecting to a Single Database
|
---|
230 | </h2>
|
---|
231 | <a name="5"></a><p> Making a database connection is a simple three step process: activate
|
---|
232 | the driver, set up the connection information, and open the
|
---|
233 | connection.
|
---|
234 | <p>
|
---|
235 |
|
---|
236 | <pre> #include <<a href="qapplication-h.html">qapplication.h</a>>
|
---|
237 | #include <<a href="qsqldatabase-h.html">qsqldatabase.h</a>>
|
---|
238 | #include "../connection.h"
|
---|
239 |
|
---|
240 | int main( int argc, char *argv[] )
|
---|
241 | {
|
---|
242 | <a href="qapplication.html">QApplication</a> app( argc, argv, FALSE );
|
---|
243 |
|
---|
244 | <a name="x2141"></a> <a href="qsqldatabase.html">QSqlDatabase</a> *defaultDB = QSqlDatabase::<a href="qsqldatabase.html#addDatabase">addDatabase</a>( DB_SALES_DRIVER );
|
---|
245 | <a name="x2143"></a> defaultDB-><a href="qsqldatabase.html#setDatabaseName">setDatabaseName</a>( DB_SALES_DBNAME );
|
---|
246 | <a name="x2146"></a> defaultDB-><a href="qsqldatabase.html#setUserName">setUserName</a>( DB_SALES_USER );
|
---|
247 | <a name="x2145"></a> defaultDB-><a href="qsqldatabase.html#setPassword">setPassword</a>( DB_SALES_PASSWD );
|
---|
248 | <a name="x2144"></a> defaultDB-><a href="qsqldatabase.html#setHostName">setHostName</a>( DB_SALES_HOST );
|
---|
249 |
|
---|
250 | <a name="x2142"></a> if ( defaultDB-><a href="qsqldatabase.html#open">open</a>() ) {
|
---|
251 | // Database successfully opened; we can now issue SQL commands.
|
---|
252 | }
|
---|
253 |
|
---|
254 | return 0;
|
---|
255 | }
|
---|
256 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-connect1-main-cpp.html">sql/overview/connect1/main.cpp</a>
|
---|
257 | </em></p>
|
---|
258 | </blockquote><p> First we activate the driver by calling <a href="qsqldatabase.html#addDatabase">QSqlDatabase::addDatabase</a>(),
|
---|
259 | passing the name of the driver we wish to use for this connection. At
|
---|
260 | the time of writing the available drivers are: <a href="sql-driver.html#QODBC3">QODBC3</a> (Open Database
|
---|
261 | Connectivity, includes Microsoft SQL Server support), <a href="sql-driver.html#QOCI8">QOCI8</a> (Oracle 8 and 9),
|
---|
262 | <a href="sql-driver.html#QTDS7">QTDS7</a> (Sybase Adaptive Server), <a href="sql-driver.html#QPSQL7">QPSQL7</a> (PostgreSQL 6 and 7),
|
---|
263 | <a href="sql-driver.html#QMYSQL3">QMYSQL3</a> (MySQL), <a href="sql-driver.html#QDB2">QDB2</a> (IBM DB2), <a href="sql-driver.html#QSQLITE">QSQLITE</a> (SQLite) and <a href="sql-driver.html#QIBASE">QIBASE</a> (Interbase).
|
---|
264 | Note that some of these drivers aren't included in the Qt Open Source Edition; see
|
---|
265 | the <tt>README</tt> files for details.
|
---|
266 | <p> The connection which is created becomes the application's default
|
---|
267 | database connection and will be used by the Qt SQL classes if no
|
---|
268 | other database is specified.
|
---|
269 | <p> Second we call setDatabaseName(), setUserName(), setPassword() and
|
---|
270 | setHostName() to initialize the connection information. Note that for
|
---|
271 | the QOCI8 (Oracle 8 and 9) driver the TNS Service Name must be passed
|
---|
272 | to setDatbaseName(). When connecting to ODBC data sources the Data
|
---|
273 | Source Name (DSN) should be used in the setDatabaseName() call.
|
---|
274 | <p> Third we call open() to open the database and give us access to the
|
---|
275 | data. If this call fails it will return FALSE; error information can
|
---|
276 | be obtained from <a href="qsqldatabase.html#lastError">QSqlDatabase::lastError</a>().
|
---|
277 | <p> <a name="Connecting_to_Multiple_Databases"></a>
|
---|
278 | <h3> Connecting to Multiple Databases
|
---|
279 | </h3>
|
---|
280 | <a name="5-1"></a><p> Connecting to multiple databases is achieved using the two argument form
|
---|
281 | of <a href="qsqldatabase.html#addDatabase">QSqlDatabase::addDatabase</a>() where the second argument is a unique
|
---|
282 | identifier distinguishing the connection.
|
---|
283 | <p> In the example below we have moved the connections into their own
|
---|
284 | function, <tt>createConnections()</tt>, and added some basic error handling.
|
---|
285 | <p> <pre>
|
---|
286 | #define DB_SALES_DRIVER "QPSQL7"
|
---|
287 | #define DB_SALES_DBNAME "sales"
|
---|
288 | #define DB_SALES_USER "salesperson"
|
---|
289 | #define DB_SALES_PASSWD "salesperson"
|
---|
290 | #define DB_SALES_HOST "database.domain.no"
|
---|
291 |
|
---|
292 | #define DB_ORDERS_DRIVER "QOCI8"
|
---|
293 | #define DB_ORDERS_DBNAME "orders"
|
---|
294 | #define DB_ORDERS_USER "orderperson"
|
---|
295 | #define DB_ORDERS_PASSWD "orderperson"
|
---|
296 | #define DB_ORDERS_HOST "database.domain.no"
|
---|
297 |
|
---|
298 | bool createConnections();
|
---|
299 | </pre>
|
---|
300 |
|
---|
301 | <p> We set up some constants and also declare the <tt>createConnections()</tt>
|
---|
302 | function in <tt>connection.h</tt>.
|
---|
303 | <p>
|
---|
304 |
|
---|
305 | <pre> #include <<a href="qsqldatabase-h.html">qsqldatabase.h</a>>
|
---|
306 | #include "connection.h"
|
---|
307 |
|
---|
308 | bool createConnections()
|
---|
309 | {
|
---|
310 |
|
---|
311 | <a name="x2147"></a> <a href="qsqldatabase.html">QSqlDatabase</a> *defaultDB = QSqlDatabase::<a href="qsqldatabase.html#addDatabase">addDatabase</a>( DB_SALES_DRIVER );
|
---|
312 | <a name="x2150"></a> defaultDB-><a href="qsqldatabase.html#setDatabaseName">setDatabaseName</a>( DB_SALES_DBNAME );
|
---|
313 | <a name="x2153"></a> defaultDB-><a href="qsqldatabase.html#setUserName">setUserName</a>( DB_SALES_USER );
|
---|
314 | <a name="x2152"></a> defaultDB-><a href="qsqldatabase.html#setPassword">setPassword</a>( DB_SALES_PASSWD );
|
---|
315 | <a name="x2151"></a> defaultDB-><a href="qsqldatabase.html#setHostName">setHostName</a>( DB_SALES_HOST );
|
---|
316 | <a name="x2149"></a> if ( ! defaultDB-><a href="qsqldatabase.html#open">open</a>() ) {
|
---|
317 | <a name="x2148"></a> <a href="qapplication.html#qWarning">qWarning</a>( "Failed to open sales database: " + defaultDB-><a href="qsqldatabase.html#lastError">lastError</a>().text() );
|
---|
318 | return FALSE;
|
---|
319 | }
|
---|
320 |
|
---|
321 | <a href="qsqldatabase.html">QSqlDatabase</a> *oracle = QSqlDatabase::<a href="qsqldatabase.html#addDatabase">addDatabase</a>( DB_ORDERS_DRIVER, "ORACLE" );
|
---|
322 | oracle-><a href="qsqldatabase.html#setDatabaseName">setDatabaseName</a>( DB_ORDERS_DBNAME );
|
---|
323 | oracle-><a href="qsqldatabase.html#setUserName">setUserName</a>( DB_ORDERS_USER );
|
---|
324 | oracle-><a href="qsqldatabase.html#setPassword">setPassword</a>( DB_ORDERS_PASSWD );
|
---|
325 | oracle-><a href="qsqldatabase.html#setHostName">setHostName</a>( DB_ORDERS_HOST );
|
---|
326 | if ( ! oracle-><a href="qsqldatabase.html#open">open</a>() ) {
|
---|
327 | <a href="qapplication.html#qWarning">qWarning</a>( "Failed to open orders database: " + oracle-><a href="qsqldatabase.html#lastError">lastError</a>().text() );
|
---|
328 | return FALSE;
|
---|
329 | }
|
---|
330 |
|
---|
331 | <a href="qsqlquery.html">QSqlQuery</a> q(QString::null, defaultDB);
|
---|
332 | <a name="x2154"></a> q.<a href="qsqlquery.html#exec">exec</a>("create table people (id integer primary key, name char(40))");
|
---|
333 | q.<a href="qsqlquery.html#exec">exec</a>("create table staff (id integer primary key, forename char(40), "
|
---|
334 | "surname char(40), salary float, statusid integer)");
|
---|
335 | q.<a href="qsqlquery.html#exec">exec</a>("create table status (id integer primary key, name char(30))");
|
---|
336 | q.<a href="qsqlquery.html#exec">exec</a>("create table creditors (id integer primary key, forename char(40), "
|
---|
337 | "surname char(40), city char(30))");
|
---|
338 | q.<a href="qsqlquery.html#exec">exec</a>("create table prices (id integer primary key, name char(40), price float)");
|
---|
339 | q.<a href="qsqlquery.html#exec">exec</a>("create table invoiceitem (id integer primary key, "
|
---|
340 | "pricesid integer, quantity integer, paiddate date)");
|
---|
341 |
|
---|
342 | <a href="qsqlquery.html">QSqlQuery</a> q2(QString::null, oracle);
|
---|
343 | q2.<a href="qsqlquery.html#exec">exec</a>("create table people (id integer primary key, name char(40))");
|
---|
344 |
|
---|
345 | return TRUE;
|
---|
346 | }
|
---|
347 | </pre><blockquote><p align="center"><em> From <a href="sql.html">sql/overview/connection.cpp</a>
|
---|
348 | </em></p>
|
---|
349 | </blockquote><p> We've chosen to isolate database connection in our <tt>createConnections()</tt> function.cpp.
|
---|
350 | <p> <a name="create_connections"></a>
|
---|
351 |
|
---|
352 |
|
---|
353 | <pre> #include <<a href="qapplication-h.html">qapplication.h</a>>
|
---|
354 | #include <<a href="qsqldatabase-h.html">qsqldatabase.h</a>>
|
---|
355 | #include "../connection.h"
|
---|
356 |
|
---|
357 | int main( int argc, char *argv[] )
|
---|
358 | {
|
---|
359 | <a href="qapplication.html">QApplication</a> app( argc, argv, FALSE );
|
---|
360 |
|
---|
361 | if ( createConnections() ) {
|
---|
362 | // Databases successfully opened; get pointers to them:
|
---|
363 | <a name="x2155"></a> <a href="qsqldatabase.html">QSqlDatabase</a> *oracledb = QSqlDatabase::<a href="qsqldatabase.html#database">database</a>( "ORACLE" );
|
---|
364 | // Now we can now issue SQL commands to the oracle connection
|
---|
365 | // or to the default connection
|
---|
366 | }
|
---|
367 |
|
---|
368 | return 0;
|
---|
369 | }
|
---|
370 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-create_connections-main-cpp.html">sql/overview/create_connections/main.cpp</a>
|
---|
371 | </em></p>
|
---|
372 | </blockquote><p> The static function <a href="qsqldatabase.html#database">QSqlDatabase::database</a>() can be called from
|
---|
373 | anywhere to provide a pointer to a database connection. If we call it
|
---|
374 | without a parameter it will return the default connection. If called
|
---|
375 | with the identifier we've used for a connection, e.g. "ORACLE", in the
|
---|
376 | above example, it will return a pointer to the specified connection.
|
---|
377 | <p> If you create a <tt>main.cpp</tt> using <a href="designer-manual.html">Qt
|
---|
378 | Designer</a>, it will <em>not</em> include our example
|
---|
379 | createConnections() function. This means that applications that
|
---|
380 | preview correctly in <a href="designer-manual.html">Qt Designer</a>
|
---|
381 | will not run unless you implement your own database connections
|
---|
382 | function.
|
---|
383 | <p> Note that in the code above the ODBC connection was not named and is
|
---|
384 | therefore used as the default connection. <a href="qsqldatabase.html">QSqlDatabase</a> maintains
|
---|
385 | ownership of the pointers returned by the addDatabase() static
|
---|
386 | function. To remove a database from the list of maintained
|
---|
387 | connections, first close the database with <a href="qsqldatabase.html#close">QSqlDatabase::close</a>(), and
|
---|
388 | then remove it using the static function
|
---|
389 | <a href="qsqldatabase.html#removeDatabase">QSqlDatabase::removeDatabase</a>().
|
---|
390 | <p> <a name="Executing_SQL_commands"></a>
|
---|
391 | <h2> Executing SQL Commands Using <a href="qsqlquery.html">QSqlQuery</a>
|
---|
392 | </h2>
|
---|
393 | <a name="6"></a><p> The <a href="qsqlquery.html">QSqlQuery</a> class provides an interface for executing SQL commands.
|
---|
394 | It also has functions for navigating through the result sets of <tt>SELECT</tt>
|
---|
395 | queries and for retrieving individual records and field values.
|
---|
396 | <p> The <a href="qsqlcursor.html">QSqlCursor</a> class described in the next section inherits from <a href="qsqlquery.html">QSqlQuery</a> and provides a higher level interface that composes SQL
|
---|
397 | commands for us. <a href="qsqlcursor.html">QSqlCursor</a> is particularly easy to integrate with
|
---|
398 | on-screen widgets. Programmers unfamiliar with SQL can safely skip this
|
---|
399 | section and use the <a href="qsqlcursor.html">QSqlCursor</a> class covered in
|
---|
400 | <a href="#Using_QSqlCursor">"Using QSqlCursor"</a>.
|
---|
401 | <p> <a name="Transactions"></a>
|
---|
402 | <h3> Transactions
|
---|
403 | </h3>
|
---|
404 | <a name="6-1"></a><p> If the underlying database engine supports transactions
|
---|
405 | <a href="qsqldriver.html#hasFeature">QSqlDriver::hasFeature</a>( QSqlDriver::Transactions ) will return TRUE.
|
---|
406 | You can use <a href="qsqldatabase.html#transaction">QSqlDatabase::transaction</a>() to initiate a transaction,
|
---|
407 | followed by the SQL commands you want to execute within the context of
|
---|
408 | the transaction, and then either <a href="qsqldatabase.html#commit">QSqlDatabase::commit</a>() or
|
---|
409 | <a href="qsqldatabase.html#rollback">QSqlDatabase::rollback</a>().
|
---|
410 | <p> <a name="Basic_Browsing"></a>
|
---|
411 | <h3> Basic Browsing
|
---|
412 | </h3>
|
---|
413 | <a name="6-2"></a><p>
|
---|
414 |
|
---|
415 | <pre> #include <<a href="qapplication-h.html">qapplication.h</a>>
|
---|
416 | #include <<a href="qsqldatabase-h.html">qsqldatabase.h</a>>
|
---|
417 | #include <<a href="qsqlquery-h.html">qsqlquery.h</a>>
|
---|
418 | #include "../connection.h"
|
---|
419 |
|
---|
420 | int main( int argc, char *argv[] )
|
---|
421 | {
|
---|
422 | <a href="qapplication.html">QApplication</a> app( argc, argv, FALSE );
|
---|
423 |
|
---|
424 | if ( createConnections() ) {
|
---|
425 | <a name="x2156"></a> <a href="qsqldatabase.html">QSqlDatabase</a> *oracledb = QSqlDatabase::<a href="qsqldatabase.html#database">database</a>( "ORACLE" );
|
---|
426 | // Copy data from the oracle database to the ODBC (default)
|
---|
427 | // database
|
---|
428 | <a href="qsqlquery.html">QSqlQuery</a> target;
|
---|
429 | <a href="qsqlquery.html">QSqlQuery</a> query( "SELECT id, name FROM people", oracledb );
|
---|
430 | <a name="x2158"></a> if ( query.<a href="qsqlquery.html#isActive">isActive</a>() ) {
|
---|
431 | <a name="x2159"></a> while ( query.<a href="qsqlquery.html#next">next</a>() ) {
|
---|
432 | <a name="x2157"></a> target.<a href="qsqlquery.html#exec">exec</a>( "INSERT INTO people ( id, name ) VALUES ( " +
|
---|
433 | <a name="x2160"></a> query.<a href="qsqlquery.html#value">value</a>(0).toString() +
|
---|
434 | ", '" + query.<a href="qsqlquery.html#value">value</a>(1).toString() + "' )" );
|
---|
435 | }
|
---|
436 | }
|
---|
437 | }
|
---|
438 |
|
---|
439 | return 0;
|
---|
440 | }
|
---|
441 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-basicbrowsing-main-cpp.html">sql/overview/basicbrowsing/main.cpp</a>
|
---|
442 | </em></p>
|
---|
443 | </blockquote><p> In the example above we've added an additional header file,
|
---|
444 | <a href="qsqlquery-h.html">qsqlquery.h</a>. The first query we create, <tt>target</tt>, uses the default
|
---|
445 | database and is initially empty. For the second query, <tt>q</tt>, we specify
|
---|
446 | the "ORACLE" database that we want to retrieve records from. Both the
|
---|
447 | database connections were set up in the createConnections() function we
|
---|
448 | wrote earlier.
|
---|
449 | <p> After creating the initial <tt>SELECT</tt> statement, isActive() is checked
|
---|
450 | to see if the query executed successfully. The next() function is
|
---|
451 | used to iterate through the query results. The value() function
|
---|
452 | returns the contents of fields as QVariants. The insertions are
|
---|
453 | achieved by creating and executing queries against the default
|
---|
454 | database using the <tt>target</tt> <a href="qsqlquery.html">QSqlQuery</a>.
|
---|
455 | <p> Note that this example and all the other examples in this document use
|
---|
456 | the tables defined in the <a href="#Example_Tables">Example Tables</a>
|
---|
457 | section.
|
---|
458 | <p>
|
---|
459 |
|
---|
460 | <pre> int count = 0;
|
---|
461 | <a name="x2162"></a> if ( query.<a href="qsqlquery.html#isActive">isActive</a>() ) {
|
---|
462 | <a name="x2163"></a> while ( query.<a href="qsqlquery.html#next">next</a>() ) {
|
---|
463 | <a name="x2161"></a> target.<a href="qsqlquery.html#exec">exec</a>( "INSERT INTO people ( id, name ) VALUES ( " +
|
---|
464 | <a name="x2165"></a> query.<a href="qsqlquery.html#value">value</a>(0).toString() +
|
---|
465 | ", '" + query.<a href="qsqlquery.html#value">value</a>(1).toString() + "' )" );
|
---|
466 | if ( target.<a href="qsqlquery.html#isActive">isActive</a>() )
|
---|
467 | <a name="x2164"></a> count += target.<a href="qsqlquery.html#numRowsAffected">numRowsAffected</a>();
|
---|
468 | }
|
---|
469 | }
|
---|
470 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-basicbrowsing2-main-cpp.html">sql/overview/basicbrowsing2/main.cpp</a>
|
---|
471 | </em></p>
|
---|
472 | </blockquote><p> The above code introduces a count of how many records are successfully
|
---|
473 | inserted. Note that isActive() returns FALSE if the query, e.g. the
|
---|
474 | insertion, fails. numRowsAffected() returns -1 if the number of rows
|
---|
475 | cannot be determined, e.g. if the query fails.
|
---|
476 | <p> <a name="Basic_Data_Manipulation"></a>
|
---|
477 | <h3> Basic Data Manipulation
|
---|
478 | </h3>
|
---|
479 | <a name="6-3"></a><p>
|
---|
480 |
|
---|
481 | <pre> ** $Id: sql.html 2051 2007-02-21 10:04:20Z chehrlic $
|
---|
482 | **
|
---|
483 | ** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.
|
---|
484 | **
|
---|
485 | ** This file is part of an example program for Qt. This example
|
---|
486 | ** program may be used, distributed and modified without limitation.
|
---|
487 | **
|
---|
488 | *****************************************************************************/
|
---|
489 |
|
---|
490 | #include <<a href="qapplication-h.html">qapplication.h</a>>
|
---|
491 | #include <<a href="qsqldatabase-h.html">qsqldatabase.h</a>>
|
---|
492 | #include <<a href="qsqlquery-h.html">qsqlquery.h</a>>
|
---|
493 | #include "../connection.h"
|
---|
494 |
|
---|
495 | bool createConnections();
|
---|
496 |
|
---|
497 | int main( int argc, char *argv[] )
|
---|
498 | {
|
---|
499 | <a href="qapplication.html">QApplication</a> app( argc, argv, FALSE );
|
---|
500 |
|
---|
501 | int rows = 0;
|
---|
502 |
|
---|
503 | if ( createConnections() ) {
|
---|
504 | <a href="qsqlquery.html">QSqlQuery</a> query( "INSERT INTO staff ( id, forename, surname, salary ) "
|
---|
505 | "VALUES ( 1155, 'Ginger', 'Davis', 50000 )" );
|
---|
506 | <a name="x2168"></a><a name="x2167"></a> if ( query.<a href="qsqlquery.html#isActive">isActive</a>() ) rows += query.<a href="qsqlquery.html#numRowsAffected">numRowsAffected</a>() ;
|
---|
507 |
|
---|
508 | <a name="x2166"></a> query.<a href="qsqlquery.html#exec">exec</a>( "UPDATE staff SET salary=60000 WHERE id=1155" );
|
---|
509 | if ( query.<a href="qsqlquery.html#isActive">isActive</a>() ) rows += query.<a href="qsqlquery.html#numRowsAffected">numRowsAffected</a>() ;
|
---|
510 |
|
---|
511 | query.<a href="qsqlquery.html#exec">exec</a>( "DELETE FROM staff WHERE id=1155" );
|
---|
512 | if ( query.<a href="qsqlquery.html#isActive">isActive</a>() ) rows += query.<a href="qsqlquery.html#numRowsAffected">numRowsAffected</a>() ;
|
---|
513 | }
|
---|
514 |
|
---|
515 | return ( rows == 3 ) ? 0 : 1;
|
---|
516 | }
|
---|
517 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-basicdatamanip-main-cpp.html">sql/overview/basicdatamanip/main.cpp</a>
|
---|
518 | </em></p>
|
---|
519 | </blockquote><p> This example demonstrates straightforward SQL DML (data manipulation
|
---|
520 | language) commands. Since we did not specify a database in the <a href="qsqlquery.html">QSqlQuery</a> constructor the default database is used. <a href="qsqlquery.html">QSqlQuery</a> objects
|
---|
521 | can also be used to execute SQL DDL (data definition language) commands
|
---|
522 | such as <tt>CREATE TABLE</tt> and <tt>CREATE INDEX</tt>.
|
---|
523 | <p> <a name="Navigating_Result_Sets"></a>
|
---|
524 | <h3> Navigating Result Sets
|
---|
525 | </h3>
|
---|
526 | <a name="6-4"></a><p> Once a <tt>SELECT</tt> query has been executed successfully we have access
|
---|
527 | to the result set of records that matched the query criteria. We have
|
---|
528 | already used one of the navigation functions, next(), which can be
|
---|
529 | used alone to step sequentially through the records. <a href="qsqlquery.html">QSqlQuery</a> also
|
---|
530 | provides first(), last() and prev(). After any of these commands we
|
---|
531 | can check that we are on a valid record by calling isValid().
|
---|
532 | <p> We can also navigate to any arbitrary record using seek(). The
|
---|
533 | first record in the dataset is zero. The number of the last record is
|
---|
534 | size() - 1. Note that not all databases provide the size of a
|
---|
535 | <tt>SELECT</tt> query and in such cases size() returns -1.
|
---|
536 | <p>
|
---|
537 |
|
---|
538 | <pre> if ( createConnections() ) {
|
---|
539 | <a href="qsqlquery.html">QSqlQuery</a> query( "SELECT id, name FROM people ORDER BY name" );
|
---|
540 | <a name="x2171"></a> if ( ! query.<a href="qsqlquery.html#isActive">isActive</a>() ) return 1; // Query failed
|
---|
541 | int i;
|
---|
542 | <a name="x2174"></a> i = query.<a href="qsqlquery.html#size">size</a>(); // In this example we have 9 records; i == 9.
|
---|
543 | <a name="x2170"></a> query.<a href="qsqlquery.html#first">first</a>(); // Moves to the first record.
|
---|
544 | <a name="x2169"></a> i = query.<a href="qsqlquery.html#at">at</a>(); // i == 0
|
---|
545 | <a name="x2172"></a> query.<a href="qsqlquery.html#last">last</a>(); // Moves to the last record.
|
---|
546 | i = query.<a href="qsqlquery.html#at">at</a>(); // i == 8
|
---|
547 | <a name="x2173"></a> query.<a href="qsqlquery.html#seek">seek</a>( query.<a href="qsqlquery.html#size">size</a>() / 2 ); // Moves to the middle record.
|
---|
548 | i = query.<a href="qsqlquery.html#at">at</a>(); // i == 4
|
---|
549 | }
|
---|
550 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-navigating-main-cpp.html">sql/overview/navigating/main.cpp</a>
|
---|
551 | </em></p>
|
---|
552 | </blockquote><p> The example above shows some of the navigation functions in use.
|
---|
553 | <p> Not all drivers support size(), but we can interrogate the driver to
|
---|
554 | find out:
|
---|
555 | <p> <pre>
|
---|
556 | <a href="qsqldatabase.html">QSqlDatabase</a>* defaultDB = QSqlDatabase::<a href="qsqldatabase.html#database">database</a>();
|
---|
557 | if ( defaultDB-><a href="qsqldatabase.html#driver">driver</a>()->hasFeature( QSqlDriver::QuerySize ) ) {
|
---|
558 | // QSqlQuery::size() supported
|
---|
559 | }
|
---|
560 | else {
|
---|
561 | // QSqlQuery::size() cannot be relied upon
|
---|
562 | }
|
---|
563 | </pre>
|
---|
564 |
|
---|
565 | <p> Once we have located the record we are interested in we may wish to
|
---|
566 | retrieve data from it.
|
---|
567 | <p>
|
---|
568 |
|
---|
569 | <pre> if ( createConnections() ) {
|
---|
570 | <a href="qsqlquery.html">QSqlQuery</a> query( "SELECT id, surname FROM staff" );
|
---|
571 | <a name="x2175"></a> if ( query.<a href="qsqlquery.html#isActive">isActive</a>() ) {
|
---|
572 | <a name="x2176"></a> while ( query.<a href="qsqlquery.html#next">next</a>() ) {
|
---|
573 | <a href="qapplication.html#qDebug">qDebug</a>( query.<a href="qsqlquery.html#value">value</a>(0).toString() + ": " +
|
---|
574 | <a name="x2177"></a> query.<a href="qsqlquery.html#value">value</a>(1).toString() );
|
---|
575 | }
|
---|
576 | }
|
---|
577 | }
|
---|
578 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-retrieve1-main-cpp.html">sql/overview/retrieve1/main.cpp</a>
|
---|
579 | </em></p>
|
---|
580 | </blockquote><p> Note that if you wish to iterate through the record set in order the
|
---|
581 | only navigation function you need is next().
|
---|
582 | <p> Tip: The lastQuery() function returns the text of the last query
|
---|
583 | executed. This can be useful to check that the query you think is being
|
---|
584 | executed is the one actually being executed.
|
---|
585 | <p> <a name="Using_QSqlCursor"></a>
|
---|
586 | <h2> Using <a href="qsqlcursor.html">QSqlCursor</a>
|
---|
587 | </h2>
|
---|
588 | <a name="7"></a><p> The <a href="qsqlcursor.html">QSqlCursor</a> class provides a high level interface to browsing and
|
---|
589 | editing records in SQL database tables or views without the need to
|
---|
590 | write your own SQL.
|
---|
591 | <p> QSqlCursor can do almost everything that <a href="qsqlquery.html">QSqlQuery</a> can, with two
|
---|
592 | exceptions. Since cursors represent tables or views within the
|
---|
593 | database, by default, <a href="qsqlcursor.html">QSqlCursor</a> objects retrieve all the fields of
|
---|
594 | each record in the table or view whenever navigating to a new
|
---|
595 | record. If only some fields are relevant simply confine your
|
---|
596 | processing to those and ignore the others. Or, manually disable the
|
---|
597 | generation of certain fields using <a href="qsqlrecord.html#setGenerated">QSqlRecord::setGenerated</a>(). Another
|
---|
598 | approach is to create a <tt>VIEW</tt> which only presents the fields you're
|
---|
599 | interested in; but note that some databases do not support editable
|
---|
600 | views. So if you really don't want to retrieve all the fields in the
|
---|
601 | cursor, then you should use a <a href="qsqlquery.html">QSqlQuery</a> instead, and customize the
|
---|
602 | query to suit your needs. You can edit records using a <a href="qsqlcursor.html">QSqlCursor</a>
|
---|
603 | providing that the table or view has a primary index that uniquely
|
---|
604 | distinguishes each record. If this condition is not met then you'll
|
---|
605 | need to use a <a href="qsqlquery.html">QSqlQuery</a> for edits.
|
---|
606 | <p> <a href="qsqlcursor.html">QSqlCursor</a> operates on a single record at a time. Whenever performing
|
---|
607 | an insert, update or delete using QSqlCursor, only a single record in
|
---|
608 | the database is affected. When navigating through records in the
|
---|
609 | cursor, only one record at a time is available in application code.
|
---|
610 | In addition, QSqlCursor maintains a separate 'edit buffer' which is
|
---|
611 | used to make changes to a single record in the database. The edit
|
---|
612 | buffer is maintained in a separate memory area, and is unnaffected by
|
---|
613 | the 'navigation buffer' which changes as the cursor moves from record
|
---|
614 | to record.
|
---|
615 | <p> Before we can use <a href="qsqlcursor.html">QSqlCursor</a> objects we must first create and open
|
---|
616 | a database connection. Connecting is described in the <a href="#Connecting_to_Databases">Connecting to Databases</a> section
|
---|
617 | above. For the examples that follow we will assume that the
|
---|
618 | connections have been created using the createConnections() function
|
---|
619 | defined in the <a href="#create_connections">QSqlDatabase example</a>
|
---|
620 | presented earlier.
|
---|
621 | <p> In the <a href="#Data-Aware_Widgets">data-aware widgets</a> section that
|
---|
622 | follows this one we show how to link widgets to database cursors. Once
|
---|
623 | we have a knowledge of both cursors and data-aware widgets we can
|
---|
624 | discuss <a href="#Subclassing_QSqlCursor">subclassing QSqlCursor</a>.
|
---|
625 | <p> The <a href="qsqlcursor.html">QSqlCursor</a> class requires the <a href="qsqlcursor-h.html">qsqlcursor.h</a> header file.
|
---|
626 | <p> <a name="Retrieving_Records"></a>
|
---|
627 | <h3> Retrieving Records
|
---|
628 | </h3>
|
---|
629 | <a name="7-1"></a><p>
|
---|
630 |
|
---|
631 | <pre> #include <<a href="qapplication-h.html">qapplication.h</a>>
|
---|
632 | #include <<a href="qsqldatabase-h.html">qsqldatabase.h</a>>
|
---|
633 | #include <<a href="qsqlcursor-h.html">qsqlcursor.h</a>>
|
---|
634 | #include "../connection.h"
|
---|
635 |
|
---|
636 | int main( int argc, char *argv[] )
|
---|
637 | {
|
---|
638 | <a href="qapplication.html">QApplication</a> app( argc, argv );
|
---|
639 |
|
---|
640 | if ( createConnections() ) {
|
---|
641 | <a href="qsqlcursor.html">QSqlCursor</a> cur( "staff" ); // Specify the table/view name
|
---|
642 | <a name="x2178"></a> cur.<a href="qsqlcursor.html#select">select</a>(); // We'll retrieve every record
|
---|
643 | while ( cur.<a href="qsqlquery.html#next">next</a>() ) {
|
---|
644 | <a name="x2179"></a> <a href="qapplication.html#qDebug">qDebug</a>( cur.<a href="qsqlquery.html#value">value</a>( "id" ).toString() + ": " +
|
---|
645 | cur.<a href="qsqlquery.html#value">value</a>( "surname" ).toString() + " " +
|
---|
646 | cur.<a href="qsqlquery.html#value">value</a>( "salary" ).toString() );
|
---|
647 | }
|
---|
648 | }
|
---|
649 |
|
---|
650 | return 0;
|
---|
651 | }
|
---|
652 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-retrieve2-main-cpp.html">sql/overview/retrieve2/main.cpp</a>
|
---|
653 | </em></p>
|
---|
654 | </blockquote><p> We create the <a href="qsqlcursor.html">QSqlCursor</a> object, specifying the table or view to use.
|
---|
655 | If we need to use a database other than the default we can specify it
|
---|
656 | in the <a href="qsqlcursor.html">QSqlCursor</a> constructor.
|
---|
657 | <p> The SQL executed by the cur.select() call is
|
---|
658 | <p> <pre>
|
---|
659 | SELECT staff.id, staff.forename, staff.surname, staff.salary, staff.statusid FROM staff
|
---|
660 | </pre>
|
---|
661 |
|
---|
662 | <p> Next, we iterate through the records returned by this select statement
|
---|
663 | using cur.next(). Field values are retrieved in in a similar way to
|
---|
664 | <a href="qsqlquery.html">QSqlQuery</a>, except that we pass field names rather than numeric indexes
|
---|
665 | to value() and setValue().
|
---|
666 | <p> <a name="Sorting_Data"></a>
|
---|
667 | <h4> Sorting and Filtering Records
|
---|
668 | </h4>
|
---|
669 | <a name="7-1-1"></a><p> To specify a subset of records to retrieve we can pass filtering
|
---|
670 | criteria to the select() function. Each record that is returned will
|
---|
671 | meet the criteria of the filter (the filter corresponds to the SQL
|
---|
672 | statement's <tt>WHERE</tt> clause).
|
---|
673 | <p> <pre>
|
---|
674 | cur.select( "id > 100" );
|
---|
675 | </pre>
|
---|
676 |
|
---|
677 | <p> This select() call will execute the SQL
|
---|
678 | <pre>
|
---|
679 | SELECT staff.id, staff.forename, staff.surname, staff.salary, staff.statusid
|
---|
680 | FROM staff WHERE staff.id > 100
|
---|
681 | </pre>
|
---|
682 |
|
---|
683 | <p> This will retrieve only those staff whose <tt>id</tt> is greater than 100.
|
---|
684 | <p> In addition to retrieving selected records we often want to specify a
|
---|
685 | sort order for the returned records. This is achieved by creating a <a href="qsqlindex.html">QSqlIndex</a> object which contains the names of the field(s) we wish to
|
---|
686 | sort by and pass this object to the select() call.
|
---|
687 | <p> <pre>
|
---|
688 | <a href="qsqlcursor.html">QSqlCursor</a> cur( "staff" );
|
---|
689 | <a href="qsqlindex.html">QSqlIndex</a> nameIndex = cur.<a href="qsqlcursor.html#index">index</a>( "surname" );
|
---|
690 | cur.<a href="qsqlcursor.html#select">select</a>( nameIndex );
|
---|
691 | </pre>
|
---|
692 |
|
---|
693 | <p> Here we create a <a href="qsqlindex.html">QSqlIndex</a> object with one field, "surname". When
|
---|
694 | we call the select() function we pass the index object, which
|
---|
695 | specifies that the records should be returned sorted by
|
---|
696 | staff.surname. Each field in the index object is used in the ORDER BY
|
---|
697 | clause of the select statement. The SQL executed here is
|
---|
698 | <pre>
|
---|
699 | SELECT staff.id, staff.forename, staff.surname, staff.salary, staff.statusid
|
---|
700 | FROM staff ORDER BY staff.surname ASC
|
---|
701 | </pre>
|
---|
702 |
|
---|
703 | <p> Combining the retrieval of a subset of records and ordering the results
|
---|
704 | is straightforward.
|
---|
705 | <p> <pre>
|
---|
706 | cur.select( "staff.surname LIKE 'A%'", nameIndex );
|
---|
707 | </pre>
|
---|
708 |
|
---|
709 | <p> We pass in a filter string (the <tt>WHERE</tt> clause), and the <a href="qsqlindex.html">QSqlIndex</a>
|
---|
710 | object to sort by (the <tt>ORDER BY</tt> clause). This produces
|
---|
711 | <p> <pre>
|
---|
712 | SELECT staff.id, staff.forename, staff.surname, staff.salary, staff.statusid
|
---|
713 | FROM staff WHERE staff.surname LIKE 'A%' ORDER BY staff.surname ASC
|
---|
714 | </pre>
|
---|
715 |
|
---|
716 | <p> To sort by more than one field, an index can be created which contains
|
---|
717 | multiple fields. Ascending and descending order can be set using
|
---|
718 | <a href="qsqlindex.html#setDescending">QSqlIndex::setDescending</a>(); the default is ascending.
|
---|
719 | <p>
|
---|
720 |
|
---|
721 | <pre> <a href="qsqlcursor.html">QSqlCursor</a> cur( "staff" );
|
---|
722 | <a href="qstringlist.html">QStringList</a> fields = QStringList() << "surname" << "forename";
|
---|
723 | <a name="x2181"></a> <a href="qsqlindex.html">QSqlIndex</a> order = cur.<a href="qsqlcursor.html#index">index</a>( fields );
|
---|
724 | <a name="x2182"></a> cur.<a href="qsqlcursor.html#select">select</a>( order );
|
---|
725 | <a name="x2183"></a> while ( cur.<a href="qsqlquery.html#next">next</a>() ) {
|
---|
726 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-order1-main-cpp.html">sql/overview/order1/main.cpp</a>
|
---|
727 | </em></p>
|
---|
728 | </blockquote><p> Here we create a string list containing the fields we wish to sort by,
|
---|
729 | in the order they are to be used. Then we create a <a href="qsqlindex.html">QSqlIndex</a> object
|
---|
730 | based on these fields, finally executing the select() call using this
|
---|
731 | index. This executes
|
---|
732 | <pre>
|
---|
733 | SELECT staff.id, staff.forename, staff.surname, staff.salary, staff.statusid
|
---|
734 | FROM staff ORDER BY staff.surname ASC, staff.forename ASC
|
---|
735 | </pre>
|
---|
736 |
|
---|
737 | <p> If we need to retrieve records with fields that match specific criteria we
|
---|
738 | can create a filter based on an index.
|
---|
739 | <p>
|
---|
740 |
|
---|
741 | <pre> <a href="qsqlcursor.html">QSqlCursor</a> cur( "staff" );
|
---|
742 | <a href="qstringlist.html">QStringList</a> fields = QStringList() << "id" << "forename";
|
---|
743 | <a name="x2184"></a> <a href="qsqlindex.html">QSqlIndex</a> order = cur.<a href="qsqlcursor.html#index">index</a>( fields );
|
---|
744 | <a href="qsqlindex.html">QSqlIndex</a> filter = cur.<a href="qsqlcursor.html#index">index</a>( "surname" );
|
---|
745 | <a name="x2186"></a> cur.<a href="qsqlrecord.html#setValue">setValue</a>( "surname", "Bloggs" );
|
---|
746 | <a name="x2185"></a> cur.<a href="qsqlcursor.html#select">select</a>( filter, order );
|
---|
747 | while ( cur.<a href="qsqlquery.html#next">next</a>() ) {
|
---|
748 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-order2-main-cpp.html">sql/overview/order2/main.cpp</a>
|
---|
749 | </em></p>
|
---|
750 | </blockquote><p> This executes
|
---|
751 | <pre>
|
---|
752 | SELECT staff.id, staff.forename, staff.surname, staff.salary, staff.statusid
|
---|
753 | FROM staff WHERE staff.surname='Bloggs' ORDER BY staff.id ASC, staff.forename ASC
|
---|
754 | </pre>
|
---|
755 |
|
---|
756 | <p> The "order" <a href="qsqlindex.html">QSqlIndex</a> contains two fields, "id" and "forename"
|
---|
757 | which are used to order the results. The "filter" <a href="qsqlindex.html">QSqlIndex</a>
|
---|
758 | contains a single field, "surname". When an index is passed as a
|
---|
759 | filter to the select() function, for each field in the filter, a
|
---|
760 | <em>fieldname=value</em> subclause is created where the value
|
---|
761 | is taken from the current cursor's value for that field. We use
|
---|
762 | setValue() to ensure that the value used is the one we want.
|
---|
763 | <p> <a name="Extracting_Data"></a>
|
---|
764 | <h4> Extracting Data
|
---|
765 | </h4>
|
---|
766 | <a name="7-1-2"></a><p>
|
---|
767 |
|
---|
768 | <pre> <a href="qsqlcursor.html">QSqlCursor</a> cur( "creditors" );
|
---|
769 | <a href="qstringlist.html">QStringList</a> orderFields = QStringList() << "surname" << "forename";
|
---|
770 | <a name="x2188"></a> <a href="qsqlindex.html">QSqlIndex</a> order = cur.<a href="qsqlcursor.html#index">index</a>( orderFields );
|
---|
771 |
|
---|
772 | <a href="qstringlist.html">QStringList</a> filterFields = QStringList() << "surname" << "city";
|
---|
773 | <a href="qsqlindex.html">QSqlIndex</a> filter = cur.<a href="qsqlcursor.html#index">index</a>( filterFields );
|
---|
774 | <a name="x2190"></a> cur.<a href="qsqlrecord.html#setValue">setValue</a>( "surname", "Chirac" );
|
---|
775 | cur.<a href="qsqlrecord.html#setValue">setValue</a>( "city", "Paris" );
|
---|
776 |
|
---|
777 | <a name="x2189"></a> cur.<a href="qsqlcursor.html#select">select</a>( filter, order );
|
---|
778 |
|
---|
779 | while ( cur.<a href="qsqlquery.html#next">next</a>() ) {
|
---|
780 | <a name="x2191"></a> int id = cur.<a href="qsqlquery.html#value">value</a>( "id" ).toInt();
|
---|
781 | <a href="qstring.html">QString</a> name = cur.<a href="qsqlquery.html#value">value</a>( "forename" ).toString() + " " +
|
---|
782 | cur.<a href="qsqlquery.html#value">value</a>( "surname" ).toString();
|
---|
783 | <a name="x2193"></a> <a href="qapplication.html#qDebug">qDebug</a>( QString::<a href="qstring.html#number">number</a>( id ) + ": " + name );
|
---|
784 | }
|
---|
785 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-extract-main-cpp.html">sql/overview/extract/main.cpp</a>
|
---|
786 | </em></p>
|
---|
787 | </blockquote><p> In this example we begin by creating a cursor on the creditors table.
|
---|
788 | We create two <a href="qsqlindex.html">QSqlIndex</a> objects. The first, "order", is created
|
---|
789 | from the "orderFields" string list. The second, "filter", is created
|
---|
790 | from the "filterFields" string list. We set the values of the two
|
---|
791 | fields used in the filter, "surname" and "city", to the values we're
|
---|
792 | interested in. Now we call select() which generates and executes the
|
---|
793 | following SQL:
|
---|
794 | <pre>
|
---|
795 | SELECT creditors.city, creditors.surname, creditors.forename, creditors.id
|
---|
796 | FROM creditors
|
---|
797 | WHERE creditors.surname = 'Chirac' AND creditors.city = 'Paris'
|
---|
798 | ORDER BY creditors.surname ASC, creditors.forename ASC
|
---|
799 | </pre>
|
---|
800 |
|
---|
801 | The filter fields are used in the <tt>WHERE</tt> clause. Their values are
|
---|
802 | taken from the cursor's current values for those fields; we set these
|
---|
803 | values ourselves with the setValue() calls. The order fields are used
|
---|
804 | in the <tt>ORDER BY</tt> clause.
|
---|
805 | <p> Now we iterate through each matching record (if any). We retrieve the
|
---|
806 | contents of the id, forename and surname fields and pass them on to
|
---|
807 | some processing function, in this example a simple <a href="qapplication.html#qDebug">qDebug</a>() call.
|
---|
808 | <p> <a name="Manipulating_Records"></a>
|
---|
809 | <h3> Manipulating Records
|
---|
810 | </h3>
|
---|
811 | <a name="7-2"></a><p> Records can be inserted, updated or deleted in a table or view using a
|
---|
812 | <a href="qsqlcursor.html">QSqlCursor</a> providing that the table or view has a primary index
|
---|
813 | that uniquely distinguishes each record. If this is not the case a <a href="qsqlquery.html">QSqlQuery</a> must be used instead. (Note that not all databases support
|
---|
814 | editable views.)
|
---|
815 | <p> Each cursor has an internal 'edit buffer' which is used by all the
|
---|
816 | edit operations (insert, update and delete). The editing process is
|
---|
817 | the same for each operation: acquire a pointer to the relevant buffer;
|
---|
818 | call setValue() to <a href="primes.html#prime">prime</a> the buffer with the values you want; call
|
---|
819 | insert() or update() or del() to perform the desired operation. For
|
---|
820 | example, when inserting a record using a cursor, you call
|
---|
821 | primeInsert() to get a pointer to the edit buffer and then call
|
---|
822 | setValue() on this buffer to set each field's value. Then you call
|
---|
823 | QSQlCursor::insert() to insert the contents of the edit buffer into
|
---|
824 | the database. Similarly, when updating (or deleting) a record, the
|
---|
825 | values of the fields in the edit buffer are used to update (or delete)
|
---|
826 | the record in the database. The 'edit buffer' is unaffected by any
|
---|
827 | <a href="#Navigating_Result_Sets">cursor navigation</a> functions.
|
---|
828 | Note that if you pass a string value to setValue() any single quotes
|
---|
829 | will be escaped (turned into a pair of single quotes) since a single
|
---|
830 | quote is a special character in SQL.
|
---|
831 | <p> The primeInsert(), primeUpdate() and primeDelete() methods all return
|
---|
832 | a pointer to the internal edit buffer. Each method can potentially
|
---|
833 | perform different operations on the edit buffer before returning it.
|
---|
834 | By default, <a href="qsqlcursor.html#primeInsert">QSqlCursor::primeInsert</a>() clears all the field values in
|
---|
835 | the edit buffer (see <a href="qsqlrecord.html#clearValues">QSqlRecord::clearValues</a>()). Both <a href="qsqlcursor.html#primeUpdate">QSqlCursor::primeUpdate</a>() and <a href="qsqlcursor.html#primeDelete">QSqlCursor::primeDelete</a>() initialize the
|
---|
836 | edit buffer with the current contents of the cursor before returning
|
---|
837 | it. All three of these functions are virtual, so you can redefine the
|
---|
838 | behavior (for example, reimplementing primeInsert() to auto-number
|
---|
839 | fields in the edit buffer). Data-aware user-interface controls emit
|
---|
840 | signals, e.g. primeInsert(), that you can connect to; these pass a
|
---|
841 | pointer to the appropriate buffer so subclassing may not be necessary.
|
---|
842 | See <a href="#Subclassing_QSqlCursor">subclassing QSqlCursor</a> for
|
---|
843 | more information on subclassing; see the <a href="designer-manual.html">Qt
|
---|
844 | Designer</a> manual for more on connecting to the primeInsert()
|
---|
845 | signal.
|
---|
846 | <p> When insert(), update() or del() is called on a cursor, it will be
|
---|
847 | invalidated and will no longer be positioned on a valid record. If you
|
---|
848 | need to move to another record after performing an insert(), update()
|
---|
849 | or del() you must make a fresh select() call. This ensures that
|
---|
850 | changes to the database are accurately reflected in the cursor.
|
---|
851 | <p> <a name="Inserting_Records"></a>
|
---|
852 | <h4> Inserting Records
|
---|
853 | </h4>
|
---|
854 | <a name="7-2-1"></a><p>
|
---|
855 |
|
---|
856 | <pre> <a href="qsqlcursor.html">QSqlCursor</a> cur( "prices" );
|
---|
857 | <a href="qstringlist.html">QStringList</a> names = QStringList() <<
|
---|
858 | "Screwdriver" << "Hammer" << "Wrench" << "Saw";
|
---|
859 | int id = 20;
|
---|
860 | <a name="x2197"></a> for ( QStringList::Iterator name = names.<a href="qvaluelist.html#begin">begin</a>();
|
---|
861 | <a name="x2198"></a> name != names.<a href="qvaluelist.html#end">end</a>(); ++name ) {
|
---|
862 | <a name="x2195"></a> <a href="qsqlrecord.html">QSqlRecord</a> *buffer = cur.<a href="qsqlcursor.html#primeInsert">primeInsert</a>();
|
---|
863 | <a name="x2196"></a> buffer-><a href="qsqlrecord.html#setValue">setValue</a>( "id", id );
|
---|
864 | buffer-><a href="qsqlrecord.html#setValue">setValue</a>( "name", *name );
|
---|
865 | buffer-><a href="qsqlrecord.html#setValue">setValue</a>( "price", 100.0 + (double)id );
|
---|
866 | <a name="x2194"></a> count += cur.<a href="qsqlcursor.html#insert">insert</a>();
|
---|
867 | id++;
|
---|
868 | }
|
---|
869 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-insert-main-cpp.html">sql/overview/insert/main.cpp</a>
|
---|
870 | </em></p>
|
---|
871 | </blockquote><p> In this example we create a cursor on the "prices" table. Next we
|
---|
872 | create a list of product names which we iterate over. For each
|
---|
873 | iteration we call the cursor's primeInsert() method. This method
|
---|
874 | returns a pointer to a <a href="qsqlrecord.html">QSqlRecord</a> buffer in which all the fields
|
---|
875 | are set to <tt>NULL</tt>. (Note that <a href="qsqlcursor.html#primeInsert">QSqlCursor::primeInsert</a>() is virtual,
|
---|
876 | and can be customized by derived classes. See <a href="qsqlcursor.html">QSqlCursor</a>). Next we
|
---|
877 | call setValue() for each field that requires a value. Finally we call
|
---|
878 | insert() to insert the record. The insert() call returns the number of
|
---|
879 | rows inserted.
|
---|
880 | <p> We obtained a pointer to a <a href="qsqlrecord.html">QSqlRecord</a> object from the primeInsert()
|
---|
881 | call. <a href="qsqlrecord.html">QSqlRecord</a> objects can hold the data for a single record plus some
|
---|
882 | meta-data about the record. In practice most interaction with a
|
---|
883 | QSqlRecord consists of simple value() and setValue() calls as shown in
|
---|
884 | this and the following example.
|
---|
885 | <p> <a name="Updating_Records"></a>
|
---|
886 | <h4> Updating Records
|
---|
887 | </h4>
|
---|
888 | <a name="7-2-2"></a><p>
|
---|
889 |
|
---|
890 | <pre> <a href="qsqlcursor.html">QSqlCursor</a> cur( "prices" );
|
---|
891 | <a name="x2200"></a> cur.<a href="qsqlcursor.html#select">select</a>( "id=202" );
|
---|
892 | if ( cur.<a href="qsqlquery.html#next">next</a>() ) {
|
---|
893 | <a name="x2199"></a> <a href="qsqlrecord.html">QSqlRecord</a> *buffer = cur.<a href="qsqlcursor.html#primeUpdate">primeUpdate</a>();
|
---|
894 | <a name="x2204"></a> double price = buffer-><a href="qsqlrecord.html#value">value</a>( "price" ).toDouble();
|
---|
895 | double newprice = price * 1.05;
|
---|
896 | <a name="x2203"></a> buffer-><a href="qsqlrecord.html#setValue">setValue</a>( "price", newprice );
|
---|
897 | <a name="x2201"></a> cur.<a href="qsqlcursor.html#update">update</a>();
|
---|
898 | }
|
---|
899 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-update-main-cpp.html">sql/overview/update/main.cpp</a>
|
---|
900 | </em></p>
|
---|
901 | </blockquote><p> This example begins with the creation of a cursor over the prices table.
|
---|
902 | We select the record we wish to update with the select() call and
|
---|
903 | move to it with the next() call. We call primeUpdate() to get a <a href="qsqlrecord.html">QSqlRecord</a> pointer to a buffer which is populated with the contents of
|
---|
904 | the current record. We retrieve the value of the price field, calculate
|
---|
905 | a new price, and set the the price field to the newly calculated value.
|
---|
906 | Finally we call update() to update the record. The update() call returns
|
---|
907 | the number of rows updated.
|
---|
908 | <p> If many identical updates need to be performed, for example increasing
|
---|
909 | the price of every item in the price list, using a single SQL statement
|
---|
910 | with <a href="qsqlquery.html">QSqlQuery</a> is more efficient, e.g.
|
---|
911 | <p> <pre>
|
---|
912 | <a href="qsqlquery.html">QSqlQuery</a> query( "UPDATE prices SET price = price * 1.05" );
|
---|
913 | </pre>
|
---|
914 |
|
---|
915 | <p> <a name="Deleting_Records"></a>
|
---|
916 | <h4> Deleting Records
|
---|
917 | </h4>
|
---|
918 | <a name="7-2-3"></a><p>
|
---|
919 |
|
---|
920 | <pre> <a href="qsqlcursor.html">QSqlCursor</a> cur( "prices" );
|
---|
921 | <a name="x2207"></a> cur.<a href="qsqlcursor.html#select">select</a>( "id=999" );
|
---|
922 | <a name="x2208"></a> if ( cur.<a href="qsqlquery.html#next">next</a>() ) {
|
---|
923 | <a name="x2206"></a> cur.<a href="qsqlcursor.html#primeDelete">primeDelete</a>();
|
---|
924 | <a name="x2205"></a> cur.<a href="qsqlcursor.html#del">del</a>();
|
---|
925 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-delete-main-cpp.html">sql/overview/delete/main.cpp</a>
|
---|
926 | </em></p>
|
---|
927 | </blockquote><p> To delete records, select the record to be deleted and navigate to it.
|
---|
928 | Then call primeDelete() to populate the cursor with the primary key
|
---|
929 | of the selected record, (in this example, the <tt>prices.id</tt> field), and
|
---|
930 | then call <a href="qsqlcursor.html#del">QSqlCursor::del</a>() to delete it.
|
---|
931 | <p> As with update(), if multiple deletions need to be made with some common
|
---|
932 | criteria it is more efficient to do so using a single SQL statement,
|
---|
933 | e.g.
|
---|
934 | <p> <pre>
|
---|
935 | <a href="qsqlquery.html">QSqlQuery</a> query( "DELETE FROM prices WHERE id >= 2450 AND id <= 2500" );
|
---|
936 | </pre>
|
---|
937 |
|
---|
938 | <p> <a name="Data-Aware_Widgets"></a>
|
---|
939 | <h2> Data-Aware Widgets
|
---|
940 | </h2>
|
---|
941 | <a name="8"></a><p> Data-Aware Widgets provide a simple yet powerful means of connecting
|
---|
942 | databases to Qt user interfaces. The easiest way of creating and
|
---|
943 | manipulating data-aware widgets is with <a href="designer-manual.html">Qt
|
---|
944 | Designer</a>. For those who prefer a purely programmatic approach
|
---|
945 | the following examples and explanations provide an introduction. Note
|
---|
946 | that the "Creating Database Applications" chapter of the <a href="designer-manual.html">Qt Designer</a> manual and its accompanying
|
---|
947 | examples provides additional information.
|
---|
948 | <p> <a name="Data-Aware_Tables"></a>
|
---|
949 | <h3> Data-Aware Tables
|
---|
950 | </h3>
|
---|
951 | <a name="8-1"></a><p>
|
---|
952 |
|
---|
953 | <pre> #include <<a href="qapplication-h.html">qapplication.h</a>>
|
---|
954 | #include <<a href="qsqldatabase-h.html">qsqldatabase.h</a>>
|
---|
955 | #include <<a href="qsqlcursor-h.html">qsqlcursor.h</a>>
|
---|
956 | #include <<a href="qdatatable-h.html">qdatatable.h</a>>
|
---|
957 | #include "../connection.h"
|
---|
958 |
|
---|
959 | int main( int argc, char *argv[] )
|
---|
960 | {
|
---|
961 | <a href="qapplication.html">QApplication</a> app( argc, argv );
|
---|
962 |
|
---|
963 | if ( createConnections() ) {
|
---|
964 | <a href="qsqlcursor.html">QSqlCursor</a> staffCursor( "staff" );
|
---|
965 | <a href="qdatatable.html">QDataTable</a> *staffTable = new <a href="qdatatable.html">QDataTable</a>( &staffCursor, TRUE );
|
---|
966 | app.<a href="qapplication.html#setMainWidget">setMainWidget</a>( staffTable );
|
---|
967 | <a name="x2211"></a> staffTable-><a href="qdatatable.html#refresh">refresh</a>();
|
---|
968 | staffTable-><a href="qwidget.html#show">show</a>();
|
---|
969 |
|
---|
970 | return app.<a href="qapplication.html#exec">exec</a>();
|
---|
971 | }
|
---|
972 |
|
---|
973 | return 0;
|
---|
974 | }
|
---|
975 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-table1-main-cpp.html">sql/overview/table1/main.cpp</a>
|
---|
976 | </em></p>
|
---|
977 | </blockquote><p> Data-Aware tables require the <a href="qdatatable-h.html">qdatatable.h</a> and <a href="qsqlcursor-h.html">qsqlcursor.h</a> header
|
---|
978 | files. We create our application object, call createConnections() and
|
---|
979 | create the cursor. We create the <a href="qdatatable.html">QDataTable</a> passing it a pointer to
|
---|
980 | the cursor, and set the autoPopulate flag to TRUE. Next we make our <a href="qdatatable.html">QDataTable</a> the main widget and call refresh() to populate it with data
|
---|
981 | and call show() to make it visible.
|
---|
982 | <p> The autoPopulate flag tells the <a href="qdatatable.html">QDataTable</a> whether or nor it should
|
---|
983 | create columns based on the cursor. autoPopulate does not affect the
|
---|
984 | loading of data into the table; that is achieved by the refresh()
|
---|
985 | function.
|
---|
986 | <p>
|
---|
987 |
|
---|
988 | <pre> <a href="qsqlcursor.html">QSqlCursor</a> staffCursor( "staff" );
|
---|
989 | <a href="qdatatable.html">QDataTable</a> *staffTable = new <a href="qdatatable.html">QDataTable</a>( &staffCursor );
|
---|
990 |
|
---|
991 | app.<a href="qapplication.html#setMainWidget">setMainWidget</a>( staffTable );
|
---|
992 |
|
---|
993 | <a name="x2214"></a> staffTable-><a href="qdatatable.html#addColumn">addColumn</a>( "forename", "Forename" );
|
---|
994 | staffTable-><a href="qdatatable.html#addColumn">addColumn</a>( "surname", "Surname" );
|
---|
995 | staffTable-><a href="qdatatable.html#addColumn">addColumn</a>( "salary", "Annual Salary" );
|
---|
996 |
|
---|
997 | <a href="qstringlist.html">QStringList</a> order = QStringList() << "surname" << "forename";
|
---|
998 | <a name="x2216"></a> staffTable-><a href="qdatatable.html#setSort">setSort</a>( order );
|
---|
999 |
|
---|
1000 | <a name="x2215"></a> staffTable-><a href="qdatatable.html#refresh">refresh</a>();
|
---|
1001 | staffTable-><a href="qwidget.html#show">show</a>();
|
---|
1002 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-table2-main-cpp.html">sql/overview/table2/main.cpp</a>
|
---|
1003 | </em></p>
|
---|
1004 | </blockquote><p> We create an empty <a href="qdatatable.html">QDataTable</a> which we make into our main widget and
|
---|
1005 | then we manually add the columns we want in the order we wish them to
|
---|
1006 | appear. For each column we specify the field name and optionally a
|
---|
1007 | display label.
|
---|
1008 | <p> We have also opted to sort the rows in the table; this could also have
|
---|
1009 | been achieved by applying the sort to the cursor itself.
|
---|
1010 | <p> Once everything is set up we call refresh() to load the data from the
|
---|
1011 | database and show() to make the widget visible.
|
---|
1012 | <p> QDataTables only retrieve visible rows which (depending on the driver)
|
---|
1013 | allows even large tables to be displayed very quickly with minimal
|
---|
1014 | memory cost.
|
---|
1015 | <p> <a name="Creating_Forms"></a>
|
---|
1016 | <h3> Creating Data-Aware Forms
|
---|
1017 | </h3>
|
---|
1018 | <a name="8-2"></a><p> Creating data-aware forms is more involved than using data-aware
|
---|
1019 | tables because we must take care of each field individually. Most of
|
---|
1020 | the code below can be automatically generated by <a href="designer-manual.html">Qt Designer</a>. See the <a href="designer-manual.html">Qt Designer</a> manual for more details.
|
---|
1021 | <p> <a name="Displaying_a_Record"></a>
|
---|
1022 | <h4> Displaying a Record
|
---|
1023 | </h4>
|
---|
1024 | <a name="8-2-1"></a><p>
|
---|
1025 |
|
---|
1026 | <pre> #include <<a href="qapplication-h.html">qapplication.h</a>>
|
---|
1027 | #include <<a href="qdialog-h.html">qdialog.h</a>>
|
---|
1028 | #include <<a href="qlabel-h.html">qlabel.h</a>>
|
---|
1029 | #include <<a href="qlayout-h.html">qlayout.h</a>>
|
---|
1030 | #include <<a href="qlineedit-h.html">qlineedit.h</a>>
|
---|
1031 | #include <<a href="qsqldatabase-h.html">qsqldatabase.h</a>>
|
---|
1032 | #include <<a href="qsqlcursor-h.html">qsqlcursor.h</a>>
|
---|
1033 | #include <<a href="qsqlform-h.html">qsqlform.h</a>>
|
---|
1034 | #include "../connection.h"
|
---|
1035 |
|
---|
1036 | class FormDialog : public <a href="qdialog.html">QDialog</a>
|
---|
1037 | {
|
---|
1038 | public:
|
---|
1039 | FormDialog();
|
---|
1040 | };
|
---|
1041 |
|
---|
1042 | FormDialog::FormDialog()
|
---|
1043 | {
|
---|
1044 | <a href="qlabel.html">QLabel</a> *forenameLabel = new <a href="qlabel.html">QLabel</a>( "Forename:", this );
|
---|
1045 | <a href="qlabel.html">QLabel</a> *forenameDisplay = new <a href="qlabel.html">QLabel</a>( this );
|
---|
1046 | <a href="qlabel.html">QLabel</a> *surnameLabel = new <a href="qlabel.html">QLabel</a>( "Surname:", this );
|
---|
1047 | <a href="qlabel.html">QLabel</a> *surnameDisplay = new <a href="qlabel.html">QLabel</a>( this );
|
---|
1048 | <a href="qlabel.html">QLabel</a> *salaryLabel = new <a href="qlabel.html">QLabel</a>( "Salary:", this );
|
---|
1049 | <a href="qlineedit.html">QLineEdit</a> *salaryEdit = new <a href="qlineedit.html">QLineEdit</a>( this );
|
---|
1050 |
|
---|
1051 | <a href="qgridlayout.html">QGridLayout</a> *grid = new <a href="qgridlayout.html">QGridLayout</a>( this );
|
---|
1052 | <a name="x2221"></a> grid-><a href="qgridlayout.html#addWidget">addWidget</a>( forenameLabel, 0, 0 );
|
---|
1053 | grid-><a href="qgridlayout.html#addWidget">addWidget</a>( forenameDisplay, 0, 1 );
|
---|
1054 | grid-><a href="qgridlayout.html#addWidget">addWidget</a>( surnameLabel, 1, 0 );
|
---|
1055 | grid-><a href="qgridlayout.html#addWidget">addWidget</a>( surnameDisplay, 1, 1 );
|
---|
1056 | grid-><a href="qgridlayout.html#addWidget">addWidget</a>( salaryLabel, 2, 0 );
|
---|
1057 | grid-><a href="qgridlayout.html#addWidget">addWidget</a>( salaryEdit, 2, 1 );
|
---|
1058 | <a name="x2222"></a> grid-><a href="qlayout.html#activate">activate</a>();
|
---|
1059 |
|
---|
1060 | <a href="qsqlcursor.html">QSqlCursor</a> staffCursor( "staff" );
|
---|
1061 | staffCursor.<a href="qsqlcursor.html#select">select</a>();
|
---|
1062 | staffCursor.<a href="qsqlquery.html#next">next</a>();
|
---|
1063 |
|
---|
1064 | <a href="qsqlform.html">QSqlForm</a> sqlForm( this );
|
---|
1065 | <a name="x2227"></a><a name="x2223"></a> sqlForm.<a href="qsqlform.html#setRecord">setRecord</a>( staffCursor.<a href="qsqlcursor.html#primeUpdate">primeUpdate</a>() );
|
---|
1066 | <a name="x2225"></a> sqlForm.<a href="qsqlform.html#insert">insert</a>( forenameDisplay, "forename" );
|
---|
1067 | sqlForm.<a href="qsqlform.html#insert">insert</a>( surnameDisplay, "surname" );
|
---|
1068 | sqlForm.<a href="qsqlform.html#insert">insert</a>( salaryEdit, "salary" );
|
---|
1069 | <a name="x2226"></a> sqlForm.<a href="qsqlform.html#readFields">readFields</a>();
|
---|
1070 | }
|
---|
1071 |
|
---|
1072 | int main( int argc, char *argv[] )
|
---|
1073 | {
|
---|
1074 | <a href="qapplication.html">QApplication</a> app( argc, argv );
|
---|
1075 |
|
---|
1076 | if ( ! createConnections() ) return 1;
|
---|
1077 |
|
---|
1078 | FormDialog *formDialog = new FormDialog();
|
---|
1079 | <a name="x2220"></a> formDialog-><a href="qdialog.html#show">show</a>();
|
---|
1080 | app.<a href="qapplication.html#setMainWidget">setMainWidget</a>( formDialog );
|
---|
1081 |
|
---|
1082 | return app.<a href="qapplication.html#exec">exec</a>();
|
---|
1083 | }
|
---|
1084 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-form1-main-cpp.html">sql/overview/form1/main.cpp</a>
|
---|
1085 | </em></p>
|
---|
1086 | </blockquote><p> We include the header files for the widgets that we need. We also
|
---|
1087 | include <a href="qsqldatabase-h.html">qsqldatabase.h</a> and <a href="qsqlcursor-h.html">qsqlcursor.h</a> as usual, but we now add
|
---|
1088 | <a href="qsqlform-h.html">qsqlform.h</a>.
|
---|
1089 | <p> The form will be presented as a dialog so we subclass <a href="qdialog.html">QDialog</a> with
|
---|
1090 | our own FormDialog class. We use a <a href="qlineedit.html">QLineEdit</a> for the salary so that
|
---|
1091 | the user can change it. All the widgets are laid out using a grid.
|
---|
1092 | <p> We create a cursor on the staff table, select all records and move to
|
---|
1093 | the first record.
|
---|
1094 | <p> Now we create a <a href="qsqlform.html">QSqlForm</a> object and set the <a href="qsqlform.html">QSqlForm</a>'s record buffer
|
---|
1095 | to the cursor's update buffer. For each widget that we wish to make
|
---|
1096 | data-aware we insert a pointer to the widget and the associated field
|
---|
1097 | name into the <a href="qsqlform.html">QSqlForm</a>. Finally we call readFields() to populate the
|
---|
1098 | widgets with data from the database via the cursor's buffer.
|
---|
1099 | <p> <a name="Displaying_a_Record_in_a_DataForm"></a>
|
---|
1100 | <h4> Displaying a Record in a Data Form
|
---|
1101 | </h4>
|
---|
1102 | <a name="8-2-2"></a><p> <a href="qdataview.html">QDataView</a> is a Widget that can hold a read-only <a href="qsqlform.html">QSqlForm</a>. In
|
---|
1103 | addition to <a href="qsqlform.html">QSqlForm</a> it offers the slot refresh( <a href="qsqlrecord.html">QSqlRecord</a> * ) so it
|
---|
1104 | can easily be linked together with a <a href="qdatatable.html">QDataTable</a> to display a detailed
|
---|
1105 | view of a record:
|
---|
1106 | <p> <pre>
|
---|
1107 | connect( myDataTable, SIGNAL( currentChanged( <a href="qsqlrecord.html">QSqlRecord</a>* ) ),
|
---|
1108 | myDataView, SLOT( refresh( <a href="qsqlrecord.html">QSqlRecord</a>* ) ) );
|
---|
1109 | </pre>
|
---|
1110 |
|
---|
1111 | <p> <a name="Editing_a_Record"></a>
|
---|
1112 | <h4> Editing a Record
|
---|
1113 | </h4>
|
---|
1114 | <a name="8-2-3"></a><p> This example is similar to the previous one so we will focus on the
|
---|
1115 | differences.
|
---|
1116 | <p>
|
---|
1117 |
|
---|
1118 | <pre> class FormDialog : public <a href="qdialog.html">QDialog</a>
|
---|
1119 | {
|
---|
1120 | <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a>
|
---|
1121 | public:
|
---|
1122 | FormDialog();
|
---|
1123 | ~FormDialog();
|
---|
1124 | public slots:
|
---|
1125 | void save();
|
---|
1126 | private:
|
---|
1127 | <a href="qsqlcursor.html">QSqlCursor</a> staffCursor;
|
---|
1128 | <a href="qsqlform.html">QSqlForm</a> *sqlForm;
|
---|
1129 | <a href="qsqlindex.html">QSqlIndex</a> idIndex;
|
---|
1130 | };
|
---|
1131 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-form2-main-h.html">sql/overview/form2/main.h</a>
|
---|
1132 | </em></p>
|
---|
1133 | </blockquote><p> The save slot will be used for a button that the user can press to
|
---|
1134 | confirm their update. We also hold pointers to the <a href="qsqlcursor.html">QSqlCursor</a> and the
|
---|
1135 | <a href="qsqlform.html">QSqlForm</a> since they will need to be accessed outside the constructor.
|
---|
1136 | <p>
|
---|
1137 |
|
---|
1138 | <pre> staffCursor.setTrimmed( "forename", TRUE );
|
---|
1139 | staffCursor.setTrimmed( "surname", TRUE );
|
---|
1140 | </pre>
|
---|
1141 | <p> We call setTrimmed() on the text fields so that any spaces used to
|
---|
1142 | right pad the fields are removed when the fields are retrieved.
|
---|
1143 | <p> Properties that we might wish to apply to fields, such as alignment
|
---|
1144 | and validation are achieved in the conventional way, for example, by
|
---|
1145 | calling <a href="qlineedit.html#setAlignment">QLineEdit::setAlignment</a>() and <a href="qlineedit.html#setValidator">QLineEdit::setValidator</a>().
|
---|
1146 | <p> <pre> <a href="qlineedit.html">QLineEdit</a> *forenameEdit = new <a href="qlineedit.html">QLineEdit</a>( this );
|
---|
1147 | </pre>
|
---|
1148 | <p> <pre> <a href="qpushbutton.html">QPushButton</a> *saveButton = new <a href="qpushbutton.html">QPushButton</a>( "&Save", this );
|
---|
1149 | <a href="qobject.html#connect">connect</a>( saveButton, SIGNAL(<a href="qbutton.html#clicked">clicked</a>()), this, SLOT(save()) );
|
---|
1150 | </pre>
|
---|
1151 | <p> The FormDialog constructor is similar to the one in the previous
|
---|
1152 | example. We have changed the forename and surname widgets to
|
---|
1153 | <a href="qlineedit.html">QLineEdit</a>s to make them editable and have added a <a href="qpushbutton.html">QPushButton</a>
|
---|
1154 | the user can click to save their updates.
|
---|
1155 | <p> <pre> <a name="x2230"></a> grid-><a href="qgridlayout.html#addWidget">addWidget</a>( saveButton, 3, 0 );
|
---|
1156 | </pre>
|
---|
1157 | <p> We add an extra row to the grid containing the save button.
|
---|
1158 | <p> <pre> idIndex = staffCursor.index( "id" );
|
---|
1159 | staffCursor.select( idIndex );
|
---|
1160 | staffCursor.first();
|
---|
1161 | </pre>
|
---|
1162 | <p> We create a <a href="qsqlindex.html">QSqlIndex</a> object and then execute a select() using the
|
---|
1163 | index. We then move to the first record in the result set.
|
---|
1164 | <p> <pre> sqlForm = new <a href="qsqlform.html">QSqlForm</a>( this );
|
---|
1165 | <a name="x2233"></a> sqlForm-><a href="qsqlform.html#setRecord">setRecord</a>( staffCursor.primeUpdate() );
|
---|
1166 | </pre>
|
---|
1167 | <p> We create a new <a href="qsqlform.html">QSqlForm</a> object and set it's record buffer to the
|
---|
1168 | cursor's update buffer.
|
---|
1169 | <p> <pre> <a name="x2231"></a> sqlForm-><a href="qsqlform.html#insert">insert</a>( forenameEdit, "forename" );
|
---|
1170 | sqlForm-><a href="qsqlform.html#insert">insert</a>( surnameEdit, "surname" );
|
---|
1171 | sqlForm-><a href="qsqlform.html#insert">insert</a>( salaryEdit, "salary" );
|
---|
1172 | <a name="x2232"></a> sqlForm-><a href="qsqlform.html#readFields">readFields</a>();
|
---|
1173 | </pre>
|
---|
1174 | <p> Now we link the buffer's fields to the <a href="qlineedit.html">QLineEdit</a> controls. (In the
|
---|
1175 | previous example we linked the cursor's fields.) The edit controls are
|
---|
1176 | populated by the readFields() call as before.
|
---|
1177 | <p> <pre> FormDialog::~FormDialog()
|
---|
1178 | {
|
---|
1179 |
|
---|
1180 | }
|
---|
1181 | </pre>
|
---|
1182 | <p> In the destructor we don't have to worry about the widgets or QSqlForm
|
---|
1183 | since they are children of the form and will be deleted by Qt at the
|
---|
1184 | right time.
|
---|
1185 | <p> <pre> void FormDialog::save()
|
---|
1186 | {
|
---|
1187 | <a name="x2234"></a> sqlForm-><a href="qsqlform.html#writeFields">writeFields</a>();
|
---|
1188 | staffCursor.update();
|
---|
1189 | staffCursor.select( idIndex );
|
---|
1190 | staffCursor.first();
|
---|
1191 | }
|
---|
1192 | </pre>
|
---|
1193 | <p> Finally we add the save functionality for when the user presses the
|
---|
1194 | save button. We write back the data from the widgets to the <a href="qsqlrecord.html">QSqlRecord</a> buffer with the writeFields() call. Then we update the
|
---|
1195 | database with the updated version of the record with the cursor's
|
---|
1196 | update() function. At this point the cursor is no longer positioned at
|
---|
1197 | a valid record so we reissue the select() call using our <a href="qsqlindex.html">QSqlIndex</a>
|
---|
1198 | and move to the first record.
|
---|
1199 | <p> <a href="qdatabrowser.html">QDataBrowser</a> and <a href="qdataview.html">QDataView</a> are widgets which provide a great deal of
|
---|
1200 | the above functionality. <a href="qdatabrowser.html">QDataBrowser</a> provides a data form which
|
---|
1201 | allows editing of and navigation through a cursor's records. <a href="qdataview.html">QDataView</a> provides a read only form for data in a cursor or database
|
---|
1202 | record. See the class documentation or the <a href="designer-manual.html">Qt Designer</a> manual for more information on using these
|
---|
1203 | widgets.
|
---|
1204 | <p> Link to <a href="sql.html">sql/overview/form2/main.cpp</a>
|
---|
1205 | <p> <a name="Custom_Editor_Widgets"></a>
|
---|
1206 | <h3> Custom Editor Widgets
|
---|
1207 | </h3>
|
---|
1208 | <a name="8-3"></a><p> <a href="qsqlform.html">QSqlForm</a> uses <a href="qsqlpropertymap.html">QSqlPropertyMap</a> to handle the transfer of data between
|
---|
1209 | widgets and database fields. Custom widgets can also be used in a form
|
---|
1210 | by installing a property map that contains information about the
|
---|
1211 | properties of the custom widget which should be used to transfer the
|
---|
1212 | data.
|
---|
1213 | <p> This example is based on the form2 example in the previous section so
|
---|
1214 | we will only cover the differences here. The full source is in <a href="sql-overview-custom1-main-h.html">sql/overview/custom1/main.h</a> and <a href="sql-overview-custom1-main-cpp.html">sql/overview/custom1/main.cpp</a>
|
---|
1215 | <p>
|
---|
1216 |
|
---|
1217 | <pre> class CustomEdit : public <a href="qlineedit.html">QLineEdit</a>
|
---|
1218 | {
|
---|
1219 | Q_OBJECT
|
---|
1220 | Q_PROPERTY( QString upperLine READ upperLine WRITE setUpperLine )
|
---|
1221 | public:
|
---|
1222 | CustomEdit( <a href="qwidget.html">QWidget</a> *parent=0, const char *name=0 );
|
---|
1223 | <a href="qstring.html">QString</a> upperLine() const;
|
---|
1224 | void setUpperLine( const <a href="qstring.html">QString</a> &line );
|
---|
1225 | public slots:
|
---|
1226 | void changed( const <a href="qstring.html">QString</a> &line );
|
---|
1227 | private:
|
---|
1228 | <a href="qstring.html">QString</a> upperLineText;
|
---|
1229 | };
|
---|
1230 | </pre>
|
---|
1231 | <p> We've created a simple subclass of <a href="qlineedit.html">QLineEdit</a> and added a property,
|
---|
1232 | upperLineText, which will hold an uppercase version of the text. We
|
---|
1233 | also created a slot, changed().
|
---|
1234 | <p> <pre> <a href="qsqlpropertymap.html">QSqlPropertyMap</a> *propMap;
|
---|
1235 | </pre>
|
---|
1236 | <p> We will be using a property map so we add a pointer to a property map
|
---|
1237 | to our FormDialog's private data.
|
---|
1238 | <p>
|
---|
1239 |
|
---|
1240 | <pre> CustomEdit::CustomEdit( <a href="qwidget.html">QWidget</a> *parent, const char *name ) :
|
---|
1241 | <a href="qlineedit.html">QLineEdit</a>( parent, name )
|
---|
1242 | {
|
---|
1243 | <a href="qobject.html#connect">connect</a>( this, SIGNAL(<a href="qlineedit.html#textChanged">textChanged</a>(const <a href="qstring.html">QString</a> &)),
|
---|
1244 | this, SLOT(changed(const <a href="qstring.html">QString</a> &)) );
|
---|
1245 | }
|
---|
1246 | </pre>
|
---|
1247 | <p> In the CustomEdit constructor we use the QLineEdit constructor and add
|
---|
1248 | a connection between the textChanged signal and our own changed slot.
|
---|
1249 | <p> <pre> void CustomEdit::changed( const <a href="qstring.html">QString</a> &line )
|
---|
1250 | {
|
---|
1251 | setUpperLine( line );
|
---|
1252 | }
|
---|
1253 | </pre>
|
---|
1254 | <p> The changed() slot calls our setUpperLine() function.
|
---|
1255 | <p> <pre> void CustomEdit::setUpperLine( const <a href="qstring.html">QString</a> &line )
|
---|
1256 | {
|
---|
1257 | <a name="x2240"></a> upperLineText = line.<a href="qstring.html#upper">upper</a>();
|
---|
1258 | setText( upperLineText );
|
---|
1259 | }
|
---|
1260 | </pre>
|
---|
1261 | <p> The setUpperLine() function places an uppercase copy of the text in the
|
---|
1262 | upperLineText buffer and then sets the text of the widget to this text.
|
---|
1263 | <p> Our CustomEdit class ensures that the text entered is always uppercase
|
---|
1264 | and provides a property that can be used with a property map to link
|
---|
1265 | CustomEdit instances directly to database fields.
|
---|
1266 | <p> <pre> CustomEdit *forenameEdit = new CustomEdit( this );
|
---|
1267 | </pre>
|
---|
1268 | <p> <pre> CustomEdit *surnameEdit = new CustomEdit( this );
|
---|
1269 | </pre>
|
---|
1270 | <p> We use the same FormDialog as we did before, but this time replace two
|
---|
1271 | of the <a href="qlineedit.html">QLineEdit</a> widgets with our own CustomEdit widgets.
|
---|
1272 | <p> Laying out the grid and setting up the cursor is the same as before.
|
---|
1273 | <p> <pre> propMap = new <a href="qsqlpropertymap.html">QSqlPropertyMap</a>;
|
---|
1274 | <a name="x2239"></a><a name="x2235"></a> propMap-><a href="qsqlpropertymap.html#insert">insert</a>( forenameEdit-><a href="qobject.html#className">className</a>(), "upperLine" );
|
---|
1275 | </pre>
|
---|
1276 | <p> We create a new property map on the heap and register our CustomEdit
|
---|
1277 | class and its upperLine property with the property map.
|
---|
1278 | <p> <pre> sqlForm = new <a href="qsqlform.html">QSqlForm</a>( this );
|
---|
1279 | <a name="x2238"></a><a name="x2236"></a> sqlForm-><a href="qsqlform.html#setRecord">setRecord</a>( staffCursor-><a href="qsqlcursor.html#primeUpdate">primeUpdate</a>() );
|
---|
1280 | <a name="x2237"></a> sqlForm-><a href="qsqlform.html#installPropertyMap">installPropertyMap</a>( propMap );
|
---|
1281 | </pre>
|
---|
1282 | <p> The final change is to install the property map into the <a href="qsqlform.html">QSqlForm</a> once
|
---|
1283 | the QSqlForm has been created. This passes responsibility for the
|
---|
1284 | property map's memory to QSqlForm which itself is owned by the
|
---|
1285 | FormDialog, so Qt will delete them at the right time.
|
---|
1286 | <p> The behaviour of this example is identical to the previous one except
|
---|
1287 | that the forename and surname fields will be uppercase since they use
|
---|
1288 | our CustomEdit widget.
|
---|
1289 | <p> <a name="Custom_Editor_Widgets_for_Tables"></a>
|
---|
1290 | <h4> Custom Editor Widgets for Tables
|
---|
1291 | </h4>
|
---|
1292 | <a name="8-3-1"></a><p> We must reimpliment <a href="qsqleditorfactory.html">QSqlEditorFactory</a> to use custom editor widgets in
|
---|
1293 | tables. In the following example we will create a custom editor based
|
---|
1294 | on <a href="qcombobox.html">QComboBox</a> and a QSqlEditorFactory subclass to show how a <a href="qdatatable.html">QDataTable</a>
|
---|
1295 | can use a custom editor.
|
---|
1296 | <p>
|
---|
1297 |
|
---|
1298 | <pre> class StatusPicker : public <a href="qcombobox.html">QComboBox</a>
|
---|
1299 | {
|
---|
1300 | Q_OBJECT
|
---|
1301 | Q_PROPERTY( int statusid READ statusId WRITE setStatusId )
|
---|
1302 | public:
|
---|
1303 | StatusPicker( <a href="qwidget.html">QWidget</a> *parent=0, const char *name=0 );
|
---|
1304 | int statusId() const;
|
---|
1305 | void setStatusId( int id );
|
---|
1306 | private:
|
---|
1307 | <a href="qmap.html">QMap</a>< int, int > index2id;
|
---|
1308 | };
|
---|
1309 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-table3-main-h.html">sql/overview/table3/main.h</a>
|
---|
1310 | </em></p>
|
---|
1311 | </blockquote><p> We create a property, statusid, and define our READ and WRITE methods
|
---|
1312 | for it. The statusid's in the status table will probably be different
|
---|
1313 | from the combobox's indexes so we create a <a href="qmap.html">QMap</a> to map combobox indexes
|
---|
1314 | to/from the statusids that we will list in the combobox.
|
---|
1315 | <p> <pre> class CustomSqlEditorFactory : public <a href="qsqleditorfactory.html">QSqlEditorFactory</a>
|
---|
1316 | {
|
---|
1317 | Q_OBJECT
|
---|
1318 | public:
|
---|
1319 | <a href="qwidget.html">QWidget</a> *createEditor( <a href="qwidget.html">QWidget</a> *parent, const <a href="qsqlfield.html">QSqlField</a> *field );
|
---|
1320 | };
|
---|
1321 | </pre>
|
---|
1322 | <p> We also need to subclass <a href="qsqleditorfactory.html">QSqlEditorFactory</a> declaring a createEditor()
|
---|
1323 | function since that is the only function we need to reimplement.
|
---|
1324 | <p>
|
---|
1325 |
|
---|
1326 | <pre> StatusPicker::StatusPicker( <a href="qwidget.html">QWidget</a> *parent, const char *name )
|
---|
1327 | : <a href="qcombobox.html">QComboBox</a>( parent, name )
|
---|
1328 | {
|
---|
1329 | <a href="qsqlcursor.html">QSqlCursor</a> cur( "status" );
|
---|
1330 | <a name="x2242"></a><a name="x2241"></a> cur.<a href="qsqlcursor.html#select">select</a>( cur.<a href="qsqlcursor.html#index">index</a>( "name" ) );
|
---|
1331 |
|
---|
1332 | int i = 0;
|
---|
1333 | while ( cur.<a href="qsqlquery.html#next">next</a>() ) {
|
---|
1334 | <a name="x2243"></a> <a href="qcombobox.html#insertItem">insertItem</a>( cur.<a href="qsqlquery.html#value">value</a>( "name" ).toString(), i );
|
---|
1335 | index2id[i] = cur.<a href="qsqlquery.html#value">value</a>( "id" ).toInt();
|
---|
1336 | i++;
|
---|
1337 | }
|
---|
1338 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-table3-main-cpp.html">sql/overview/table3/main.cpp</a>
|
---|
1339 | </em></p>
|
---|
1340 | </blockquote><p> In the StatusPicker's constructor we create a cursor over the status
|
---|
1341 | table indexed by the name field. We then iterate over each record in the
|
---|
1342 | status table inserting each name into the combobox. We store the
|
---|
1343 | statusid for each name in the index2id <a href="qmap.html">QMap</a> using the same QMap index as
|
---|
1344 | the combobox index.
|
---|
1345 | <p> <pre> int StatusPicker::statusId() const
|
---|
1346 | {
|
---|
1347 | return index2id[ currentItem() ];
|
---|
1348 | }
|
---|
1349 | </pre>
|
---|
1350 | <p> The statusid property READ function simply involves looking up the
|
---|
1351 | combobox's index for the currently selected item in the index2id QMap
|
---|
1352 | which maps combobox indexes to statusids.
|
---|
1353 | <p> <pre> void StatusPicker::setStatusId( int statusid )
|
---|
1354 | {
|
---|
1355 | QMap<int,int>::Iterator it;
|
---|
1356 | for ( it = index2id.begin(); it != index2id.end(); ++it ) {
|
---|
1357 | if ( it.data() == statusid ) {
|
---|
1358 | setCurrentItem( it.key() );
|
---|
1359 | break;
|
---|
1360 | }
|
---|
1361 | }
|
---|
1362 | }
|
---|
1363 | </pre>
|
---|
1364 | <p> The statusId() function implements the statusid property's WRITE
|
---|
1365 | function. We create an iterator over a QMap and iterate over the
|
---|
1366 | index2id QMap. We compare each index2id element's data (statusid) to
|
---|
1367 | the id parameter's value. If we have a match we set the combobox's
|
---|
1368 | current item to the index2id element's key (the combobox index), and
|
---|
1369 | leave the loop.
|
---|
1370 | <p> When the user edits the status field in the <a href="qdatatable.html">QDataTable</a> they will be
|
---|
1371 | presented with a combobox of valid status names taken from the status
|
---|
1372 | table. However the status displayed is still the raw statusid. To
|
---|
1373 | display the status name when the field isn't being edited requires us
|
---|
1374 | to subclass QDataTable and reimplement the paintField() function.
|
---|
1375 | <p>
|
---|
1376 |
|
---|
1377 | <pre> class CustomTable : public <a href="qdatatable.html">QDataTable</a>
|
---|
1378 | {
|
---|
1379 | Q_OBJECT
|
---|
1380 | public:
|
---|
1381 | CustomTable(
|
---|
1382 | <a href="qsqlcursor.html">QSqlCursor</a> *cursor, bool autoPopulate = FALSE,
|
---|
1383 | <a href="qwidget.html">QWidget</a> * parent = 0, const char * name = 0 ) :
|
---|
1384 | <a href="qdatatable.html">QDataTable</a>( cursor, autoPopulate, parent, name ) {}
|
---|
1385 | void paintField(
|
---|
1386 | <a href="qpainter.html">QPainter</a> * p, const <a href="qsqlfield.html">QSqlField</a>* field, const <a href="qrect.html">QRect</a> & cr, bool );
|
---|
1387 |
|
---|
1388 | };
|
---|
1389 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-table4-main-h.html">sql/overview/table4/main.h</a>
|
---|
1390 | </em></p>
|
---|
1391 | </blockquote><p> We simply call the original <a href="qdatatable.html">QDataTable</a> constructor without changing
|
---|
1392 | anything. We also declare the paintField function.
|
---|
1393 | <p>
|
---|
1394 |
|
---|
1395 | <pre> <a name="x2245"></a>void CustomTable::<a href="qdatatable.html#paintField">paintField</a>( <a href="qpainter.html">QPainter</a> * p, const <a href="qsqlfield.html">QSqlField</a>* field,
|
---|
1396 | const <a href="qrect.html">QRect</a> & cr, bool b)
|
---|
1397 | {
|
---|
1398 | if ( !field )
|
---|
1399 | return;
|
---|
1400 | <a name="x2249"></a> if ( field-><a href="qsqlfield.html#name">name</a>() == "statusid" ) {
|
---|
1401 | <a href="qsqlquery.html">QSqlQuery</a> query( "SELECT name FROM status WHERE id=" +
|
---|
1402 | <a name="x2250"></a> field-><a href="qsqlfield.html#value">value</a>().toString() );
|
---|
1403 | <a href="qstring.html">QString</a> text;
|
---|
1404 | if ( query.<a href="qsqlquery.html#next">next</a>() ) {
|
---|
1405 | <a name="x2252"></a> text = query.<a href="qsqlquery.html#value">value</a>( 0 ).toString();
|
---|
1406 | }
|
---|
1407 | p-><a href="qpainter.html#drawText">drawText</a>( 2,2, cr.<a href="qrect.html#width">width</a>()-4, cr.<a href="qrect.html#height">height</a>()-4, fieldAlignment( field ), text );
|
---|
1408 | }
|
---|
1409 | else {
|
---|
1410 | QDataTable::<a href="qdatatable.html#paintField">paintField</a>( p, field, cr, b) ;
|
---|
1411 | }
|
---|
1412 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-table4-main-cpp.html">sql/overview/table4/main.cpp</a>
|
---|
1413 | </em></p>
|
---|
1414 | </blockquote><p> The paintField code is based on <a href="qdatatable.html">QDataTable</a>'s source code. We need to
|
---|
1415 | make three changes. Firstly add an if clause <tt>field->name() == "statusid"</tt> and look up the textual value for the id with a
|
---|
1416 | straighforward <a href="qsqlquery.html">QSqlQuery</a>. Secondly call the superclass to handle other
|
---|
1417 | fields. The last change is in our main function where we change
|
---|
1418 | staffTable from being a QDataTable to being a CustomTable.
|
---|
1419 | <p> <a name="Subclassing_QSqlCursor"></a>
|
---|
1420 | <h2> Subclassing <a href="qsqlcursor.html">QSqlCursor</a>
|
---|
1421 | </h2>
|
---|
1422 | <a name="9"></a><p>
|
---|
1423 |
|
---|
1424 | <pre> #include <<a href="qapplication-h.html">qapplication.h</a>>
|
---|
1425 | #include <<a href="qsqldatabase-h.html">qsqldatabase.h</a>>
|
---|
1426 | #include <<a href="qsqlcursor-h.html">qsqlcursor.h</a>>
|
---|
1427 | #include <<a href="qdatatable-h.html">qdatatable.h</a>>
|
---|
1428 | #include "../connection.h"
|
---|
1429 |
|
---|
1430 | int main( int argc, char *argv[] )
|
---|
1431 | {
|
---|
1432 | <a href="qapplication.html">QApplication</a> app( argc, argv );
|
---|
1433 |
|
---|
1434 | if ( createConnections() ) {
|
---|
1435 | <a href="qsqlcursor.html">QSqlCursor</a> invoiceItemCursor( "invoiceitem" );
|
---|
1436 |
|
---|
1437 | <a href="qdatatable.html">QDataTable</a> *invoiceItemTable = new <a href="qdatatable.html">QDataTable</a>( &invoiceItemCursor );
|
---|
1438 |
|
---|
1439 | app.<a href="qapplication.html#setMainWidget">setMainWidget</a>( invoiceItemTable );
|
---|
1440 |
|
---|
1441 | <a name="x2255"></a> invoiceItemTable-><a href="qdatatable.html#addColumn">addColumn</a>( "pricesid", "PriceID" );
|
---|
1442 | invoiceItemTable-><a href="qdatatable.html#addColumn">addColumn</a>( "quantity", "Quantity" );
|
---|
1443 | invoiceItemTable-><a href="qdatatable.html#addColumn">addColumn</a>( "paiddate", "Paid" );
|
---|
1444 |
|
---|
1445 | <a name="x2256"></a> invoiceItemTable-><a href="qdatatable.html#refresh">refresh</a>();
|
---|
1446 | invoiceItemTable-><a href="qwidget.html#show">show</a>();
|
---|
1447 |
|
---|
1448 | return app.<a href="qapplication.html#exec">exec</a>();
|
---|
1449 | }
|
---|
1450 |
|
---|
1451 | return 1;
|
---|
1452 | }
|
---|
1453 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-subclass1-main-cpp.html">sql/overview/subclass1/main.cpp</a>
|
---|
1454 | </em></p>
|
---|
1455 | </blockquote><p> This example is very similar to the table1 example presented earlier. We
|
---|
1456 | create a cursor, add the fields and their display labels to a <a href="qdatatable.html">QDataTable</a>,
|
---|
1457 | call refresh() to load the data and call show() to show the widget.
|
---|
1458 | <p> Unfortunately this example is unsatisfactory. It is tedious to set the
|
---|
1459 | table name and any custom characteristics for the fields every time we
|
---|
1460 | need a cursor over this table. And it would be far better if we
|
---|
1461 | displayed the name of the product rather than its pricesid. Since we
|
---|
1462 | know the price of the product and the quantity we could also show the
|
---|
1463 | product cost and the cost of each invoiceitem. Finally it would be
|
---|
1464 | useful (or even essential for primary keys) if we could default some of
|
---|
1465 | the values when the user adds a new record.
|
---|
1466 | <p>
|
---|
1467 |
|
---|
1468 | <pre> class InvoiceItemCursor : public <a href="qsqlcursor.html">QSqlCursor</a>
|
---|
1469 | {
|
---|
1470 | public:
|
---|
1471 | InvoiceItemCursor();
|
---|
1472 | };
|
---|
1473 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-subclass2-main-h.html">sql/overview/subclass2/main.h</a>
|
---|
1474 | </em></p>
|
---|
1475 | </blockquote><p> We have created a separate header file and subclassed <a href="qsqlcursor.html">QSqlCursor</a>.
|
---|
1476 | <p>
|
---|
1477 |
|
---|
1478 | <pre> InvoiceItemCursor::InvoiceItemCursor() :
|
---|
1479 | <a href="qsqlcursor.html">QSqlCursor</a>( "invoiceitem" )
|
---|
1480 | {
|
---|
1481 | // NOOP
|
---|
1482 | }
|
---|
1483 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-subclass2-main-cpp.html">sql/overview/subclass2/main.cpp</a>
|
---|
1484 | </em></p>
|
---|
1485 | </blockquote><p> In our class's constructor we call the QSqlCursor constructor with the
|
---|
1486 | name of the table. We don't have any other characteristics to add at
|
---|
1487 | this stage.
|
---|
1488 | <p> <pre> InvoiceItemCursor invoiceItemCursor;
|
---|
1489 | </pre>
|
---|
1490 | <p> Whenever we require a cursor over the invoiceitem table we can create
|
---|
1491 | an InvoiceItemCursor instead of a generic QSqlCursor.
|
---|
1492 | <p> We still need to show the product name rather than the pricesid.
|
---|
1493 | <p>
|
---|
1494 |
|
---|
1495 | <pre> protected:
|
---|
1496 | <a href="qvariant.html">QVariant</a> calculateField( const <a href="qstring.html">QString</a> & name );
|
---|
1497 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-subclass3-main-h.html">sql/overview/subclass3/main.h</a>
|
---|
1498 | </em></p>
|
---|
1499 | </blockquote><p> The change in the header file is minimal: we simply add the signature
|
---|
1500 | of the calculateField() function since we will be reimplementing it.
|
---|
1501 | <p>
|
---|
1502 |
|
---|
1503 | <pre> InvoiceItemCursor::InvoiceItemCursor() :
|
---|
1504 | <a href="qsqlcursor.html">QSqlCursor</a>( "invoiceitem" )
|
---|
1505 | {
|
---|
1506 | <a href="qsqlfieldinfo.html">QSqlFieldInfo</a> productName( "productname", QVariant::String );
|
---|
1507 | <a href="qsqlcursor.html#append">append</a>( productName );
|
---|
1508 | <a name="x2260"></a> <a href="qsqlcursor.html#setCalculated">setCalculated</a>( productName.<a href="qsqlfieldinfo.html#name">name</a>(), TRUE );
|
---|
1509 | }
|
---|
1510 |
|
---|
1511 | <a name="x2259"></a>QVariant InvoiceItemCursor::<a href="qsqlcursor.html#calculateField">calculateField</a>( const <a href="qstring.html">QString</a> & name )
|
---|
1512 | {
|
---|
1513 | if ( name == "productname" ) {
|
---|
1514 | <a href="qsqlquery.html">QSqlQuery</a> query( "SELECT name FROM prices WHERE id=" +
|
---|
1515 | <a href="qsqlrecord.html#field">field</a>( "pricesid" )->value().toString() );
|
---|
1516 | if ( query.<a href="qsqlquery.html#next">next</a>() )
|
---|
1517 | <a name="x2262"></a> return query.<a href="qsqlquery.html#value">value</a>( 0 );
|
---|
1518 | }
|
---|
1519 |
|
---|
1520 | return QVariant( <a href="qstring.html#QString-null">QString::null</a> );
|
---|
1521 | }
|
---|
1522 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-subclass3-main-cpp.html">sql/overview/subclass3/main.cpp</a>
|
---|
1523 | </em></p>
|
---|
1524 | </blockquote><p> We have changed the InvoiceItemCursor constructor. We now create a new
|
---|
1525 | <a href="qsqlfield.html">QSqlField</a> called productname and append this to the
|
---|
1526 | InvoiceItemCursor's set of fields. We call setCalculated() on
|
---|
1527 | productname to identify it as a calculated field. The first argument
|
---|
1528 | to setCalculated() is the field name, the second a bool which if TRUE
|
---|
1529 | signifies that calculateField() must be called to get the field's
|
---|
1530 | value.
|
---|
1531 | <p> <pre> <a name="x2258"></a> invoiceItemTable-><a href="qdatatable.html#addColumn">addColumn</a>( "productname", "Product" );
|
---|
1532 | </pre>
|
---|
1533 | <p> We add our new fields with addColumn() which adds them to the form and
|
---|
1534 | sets their display names.
|
---|
1535 | <p> We have to define our own calculateField() function. In our example
|
---|
1536 | database the pricesid in the invoiceitem table is a foreign key into
|
---|
1537 | the prices table. We find the name of the product by executing a query
|
---|
1538 | on the prices table using the pricesid. This returns the product's
|
---|
1539 | name.
|
---|
1540 | <p> We are now able to extend the example to include calculated fields
|
---|
1541 | which perform real calculations.
|
---|
1542 | <p> The header file, <a href="sql-overview-subclass4-main-h.html">sql/overview/subclass4/main.h</a>, remains unchanged
|
---|
1543 | from the previous example, but the constructor and calculateField()
|
---|
1544 | function require some simple expansion. We'll look at each in turn.
|
---|
1545 | <p>
|
---|
1546 |
|
---|
1547 | <pre> InvoiceItemCursor::InvoiceItemCursor() :
|
---|
1548 | <a href="qsqlcursor.html">QSqlCursor</a>( "invoiceitem" )
|
---|
1549 | {
|
---|
1550 | <a href="qsqlfieldinfo.html">QSqlFieldInfo</a> productName( "productname", QVariant::String );
|
---|
1551 | <a href="qsqlcursor.html#append">append</a>( productName );
|
---|
1552 | <a name="x2264"></a> <a href="qsqlcursor.html#setCalculated">setCalculated</a>( productName.<a href="qsqlfieldinfo.html#name">name</a>(), TRUE );
|
---|
1553 |
|
---|
1554 | <a href="qsqlfieldinfo.html">QSqlFieldInfo</a> productPrice( "price", QVariant::Double );
|
---|
1555 | <a href="qsqlcursor.html#append">append</a>( productPrice );
|
---|
1556 | <a href="qsqlcursor.html#setCalculated">setCalculated</a>( productPrice.<a href="qsqlfieldinfo.html#name">name</a>(), TRUE );
|
---|
1557 |
|
---|
1558 | <a href="qsqlfieldinfo.html">QSqlFieldInfo</a> productCost( "cost", QVariant::Double );
|
---|
1559 | <a href="qsqlcursor.html#append">append</a>( productCost );
|
---|
1560 | <a href="qsqlcursor.html#setCalculated">setCalculated</a>( productCost.<a href="qsqlfieldinfo.html#name">name</a>(), TRUE );
|
---|
1561 | }
|
---|
1562 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-subclass4-main-cpp.html">sql/overview/subclass4/main.cpp</a>
|
---|
1563 | </em></p>
|
---|
1564 | </blockquote><p> We create two extra fields, price and cost, and append them to the
|
---|
1565 | cursor's set of fields. Both are registered as calculated fields with
|
---|
1566 | calls to setCalculated().
|
---|
1567 | <p> <pre> <a name="x2263"></a>QVariant InvoiceItemCursor::<a href="qsqlcursor.html#calculateField">calculateField</a>( const <a href="qstring.html">QString</a> & name )
|
---|
1568 | {
|
---|
1569 |
|
---|
1570 | if ( name == "productname" ) {
|
---|
1571 | <a href="qsqlquery.html">QSqlQuery</a> query( "SELECT name FROM prices WHERE id=" +
|
---|
1572 | <a href="qsqlrecord.html#field">field</a>( "pricesid" )->value().toString() );
|
---|
1573 | <a name="x2265"></a> if ( query.<a href="qsqlquery.html#next">next</a>() )
|
---|
1574 | <a name="x2266"></a> return query.<a href="qsqlquery.html#value">value</a>( 0 );
|
---|
1575 | }
|
---|
1576 | else if ( name == "price" ) {
|
---|
1577 | <a href="qsqlquery.html">QSqlQuery</a> query( "SELECT price FROM prices WHERE id=" +
|
---|
1578 | <a href="qsqlrecord.html#field">field</a>( "pricesid" )->value().toString() );
|
---|
1579 | if ( query.<a href="qsqlquery.html#next">next</a>() )
|
---|
1580 | return query.<a href="qsqlquery.html#value">value</a>( 0 );
|
---|
1581 | }
|
---|
1582 | else if ( name == "cost" ) {
|
---|
1583 | <a href="qsqlquery.html">QSqlQuery</a> query( "SELECT price FROM prices WHERE id=" +
|
---|
1584 | <a href="qsqlrecord.html#field">field</a>( "pricesid" )->value().toString() );
|
---|
1585 | if ( query.<a href="qsqlquery.html#next">next</a>() )
|
---|
1586 | return QVariant( query.<a href="qsqlquery.html#value">value</a>( 0 ).toDouble() *
|
---|
1587 | <a href="qsqlquery.html#value">value</a>( "quantity").toDouble() );
|
---|
1588 | }
|
---|
1589 |
|
---|
1590 | return QVariant( QString::null );
|
---|
1591 | }
|
---|
1592 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-subclass4-main-cpp.html">sql/overview/subclass4/main.cpp</a>
|
---|
1593 | </em></p>
|
---|
1594 | </blockquote><p> The calculateField() function has expanded slightly because now we
|
---|
1595 | must calculate the value of three different fields. The productname
|
---|
1596 | and price fields are produced by looking up the corresponding values
|
---|
1597 | in the prices table keyed by pricesid. The cost field is calculated
|
---|
1598 | simply by multiplying the price by the quantity. Note that we cast the
|
---|
1599 | cost to a <a href="qvariant.html">QVariant</a> since that is the type that calculateField() must
|
---|
1600 | return.
|
---|
1601 | <p> We've written three separate queries rather than one to make the
|
---|
1602 | example more like a real application where it is more likely that each
|
---|
1603 | calculated field would be a lookup against a different table or view.
|
---|
1604 | <p> The last feature that we need to add is defaulting values when the
|
---|
1605 | user attempts to insert a new record.
|
---|
1606 | <p>
|
---|
1607 |
|
---|
1608 | <pre> <a href="qsqlrecord.html">QSqlRecord</a> *primeInsert();
|
---|
1609 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-subclass5-main-h.html">sql/overview/subclass5/main.h</a>
|
---|
1610 | </em></p>
|
---|
1611 | </blockquote><p> We declare our own primeInsert() function since we will need to
|
---|
1612 | reimplement this.
|
---|
1613 | <p> The constructor and the calculateField() function remain unchanged.
|
---|
1614 | <p>
|
---|
1615 |
|
---|
1616 | <pre> <a name="x2267"></a>QSqlRecord *InvoiceItemCursor::<a href="qsqlcursor.html#primeInsert">primeInsert</a>()
|
---|
1617 | {
|
---|
1618 | <a href="qsqlrecord.html">QSqlRecord</a> *buffer = <a href="qsqlcursor.html#editBuffer">editBuffer</a>();
|
---|
1619 | <a href="qsqlquery.html">QSqlQuery</a> query( "SELECT NEXTVAL( 'invoiceitem_seq' )" );
|
---|
1620 | <a name="x2268"></a> if ( query.<a href="qsqlquery.html#next">next</a>() )
|
---|
1621 | <a name="x2270"></a><a name="x2269"></a> buffer-><a href="qsqlrecord.html#setValue">setValue</a>( "id", query.<a href="qsqlquery.html#value">value</a>( 0 ) );
|
---|
1622 | buffer-><a href="qsqlrecord.html#setValue">setValue</a>( "paiddate", QDate::currentDate() );
|
---|
1623 | buffer-><a href="qsqlrecord.html#setValue">setValue</a>( "quantity", 1 );
|
---|
1624 |
|
---|
1625 | return buffer;
|
---|
1626 | }
|
---|
1627 | </pre><blockquote><p align="center"><em> From <a href="sql-overview-subclass5-main-cpp.html">sql/overview/subclass5/main.cpp</a>
|
---|
1628 | </em></p>
|
---|
1629 | </blockquote><p> We get a pointer to the internal edit buffer that the cursor uses for
|
---|
1630 | inserts and updates. The id field is a unique integer that we generate
|
---|
1631 | using the invoiceitem_seq. We default the value of the paiddate field
|
---|
1632 | to today's date and default the quantity to 1. Finally we return a
|
---|
1633 | pointer to the buffer. The rest of the code is unchanged from the
|
---|
1634 | previous version.
|
---|
1635 | <p> <a name="Example_Tables"></a>
|
---|
1636 | <h2> The Example Tables
|
---|
1637 | </h2>
|
---|
1638 | <a name="10"></a><p> The example tables used can be recreated with the following standard
|
---|
1639 | SQL. You may need to modify the SQL to match that used by your
|
---|
1640 | particular database.
|
---|
1641 | <p> <pre>
|
---|
1642 | create table people (id integer primary key, name char(40))
|
---|
1643 |
|
---|
1644 | create table staff (id integer primary key, forename char(40),
|
---|
1645 | surname char(40), salary float, statusid integer)
|
---|
1646 |
|
---|
1647 | create table status (id integer primary key, name char(30))
|
---|
1648 |
|
---|
1649 | create table creditors (id integer primary key, forename char(40),
|
---|
1650 | surname char(40), city char(30))
|
---|
1651 |
|
---|
1652 | create table prices (id integer primary key, name char(40), price float)
|
---|
1653 |
|
---|
1654 | create table invoiceitem (id integer primary key,
|
---|
1655 | pricesid integer, quantity integer,
|
---|
1656 | paiddate date)
|
---|
1657 | </pre>
|
---|
1658 |
|
---|
1659 | <p> A sequence was used in the calculateField() example above. Note that
|
---|
1660 | sequences are not supported in all databases.
|
---|
1661 | <p> <pre>
|
---|
1662 | create sequence invoiceitem_seq
|
---|
1663 | </pre>
|
---|
1664 |
|
---|
1665 | <p>
|
---|
1666 | <!-- eof -->
|
---|
1667 | <p><address><hr><div align=center>
|
---|
1668 | <table width=100% cellspacing=0 border=0><tr>
|
---|
1669 | <td>Copyright © 2007
|
---|
1670 | <a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
|
---|
1671 | <td align=right><div align=right>Qt 3.3.8</div>
|
---|
1672 | </table></div></address></body>
|
---|
1673 | </html>
|
---|