[190] | 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>
|
---|