A set of classes for connecting to SQL databases and running SQL commands on them.

The SQLDB unit defines four main classes to handle data in SQL based databases.

  1. represents the connection to the database. Here, properties pertaining to the connection (machine, database, user password) must be set. This is an abstract class, which should not be used directly. Per database type (mysql, firebird, postgres, oracle, sqlite) a descendent should be made and used.
  2. is a descendent which can be used to view and manipulate the result of an SQL select query. It can also be used to execute all kinds of SQL statements.
  3. represents the transaction in which an SQL command is running. SQLDB supports multiple simultaneous transactions in a database connection. For databases that do not support this functionality natively, it is simulated by maintaining multiple connections to the database.
  4. can be used when many SQL commands must be executed on a database, for example when creating a database.

There is also a unified way to retrieve schema information, and a registration for connector types. More information on how to use these components can be found in .

Using parameters

SQLDB implements parametrized queries, simulating them if the native SQL client does not support parametrized queries. A parametrized query means that the SQL statement contains placeholders for actual values. The following is a typical example:

SELECT * FROM MyTable WHERE (id=:id)

The :id is a parameter with the name id. It does not contain a value yet. The value of the parameter will be specified separately. In SQLDB this happens through the TParams collection, where each element of the collection is a named parameter, specified in the SQL statement. The value can be specified as follows:

Params.ParamByname('id').AsInteger:=123;

This will tell SQLDB that the parameter id is of type integer, and has value 123.

SQLDB uses parameters for 3 purposes:

  1. When executing a query multiple times, simply with different values, this helps increase the speed if the server supports parametrized queries: the query must be prepared only once.
  2. Master-Detail relationships between datasets can be established based on a parametrized detail query: the value of the parameters in the detail query is automatically obtained from fields with the same names in the master dataset. As the user scrolls through the master dataset, the detail dataset is refreshed with the new values of the params.
  3. Updating of data in the database happens through parametrized update/delete/insert statements: the , , properties of must contain parametrized queries.

An additional advantage of using parameters is that they help to avoid SQL injection: by specifying a parameter type and value, SQLDB will automatically check whether the value is of the correct type, and will apply proper quoting when the native engine does not support parameters directly.

Automatic generation of update SQL statements

SQLDB (more in particular, ) can automatically generate update statements for the data it fetches. To this end, it will scan the SQL statement and determine the main table in the query: this is the first table encountered in the FROM part of the SELECT statement.

For INSERT and UPDATE operations, the SQL statement will update/insert all fields that have pfInUpdate in their ProviderFlags property. Read-only fields will not be added to the SQL statement. Fields that are NULL will not be added to an insert query, which means that the database server will insert whatever is in the DEFAULT clause of the corresponding field definition.

The WHERE clause for update and delete statements consists of all fields with pfInKey in their ProviderFlags property. Depending on the value of the UpdateMode property, additional fields may be added to the WHERE clause:

upWhereKeyOnly
No additional fields are added: only fields marked with pfInKey are used in the WHERE clause
upWhereChanged
All fields whose value changed are added to the WHERE clause, using their old value.
upWhereAll
All fields are added to the WHERE clause, using their old value.

In order to let SQLDB generate correct statements, it is important to set the ProviderFlags properties correct for all fields.

In many cases, for example when only a single table is queried, and no AS field aliases are used , setting combined with UpdateMode equal to upWhereKeyOnly is sufficient.

If the automatically generated queries are not correct, it is possible to specify the SQL statements to be used in the UpdateSQL, InsertSQL and DeleteSQL properties. The new field values should be specified using params with the same name as the field. The old field values should be specified using the OLD_ prefix to the field name. The following example demonstrates this:

INSERT INTO MYTABLE (MYFIELD,MYFIELD2) VALUES (:MYFIELD,:MYFIELD2); UPDATE MYTABLE SET MYFIELD=:MYFIELD MYFIELD2=:MYFIELD2 WHERE (MYFIELD=:OLD_MYFIELD); DELETE FROM MYTABLE WHERE (MyField=:OLD_MYFIELD);
UpdateSQL InsertSQL DeleteSQL
Retrieving Schema Information

Schema Information (lists of available database objects) can be retrieved using some specialized calls in :

  • retrieves a list of available tables. The system tables can be requested.
  • retrieves a list of available stored procedures.
  • retrieves a list of fields for a given table.

These calls are pretty straightforward and need little explanation. A more versatile system is the schema info query: the method can be used to create a result set (dataset) with schema information. The parameter SchemaType determines the resulting information when the dataset is opened. The following information can be requested:

stTables
Retrieves the list of user Tables in database. This is used internally by .
stSysTables
Retrieves the list of system Tables in database. This is used internally by when the system tables are requested
stProcedures
Retrieves a list of stored procedures in database. This is used internally by .
stColumns
Retrieves the list of columns (fields) in a table. This is used internally by .
stProcedureParams
This retrieves the parameters for a stored procedure.
stIndexes
Retrieves the indexes for one or more tables. (currently not implemented)
stPackages
Retrieves packages for databases that support them. (currently not implemented).
Using the universal TSQLConnector type

The normal procedure when using SQLDB is to use one of the descendent components. When the database backend changes, another descendent of TSQLConnection must be used. When using a lot of different connection types and components, this may be confusing and a lot of work.

There is a universal connector component which can connect to any database supported by SQLDB: it works as a proxy. Behind the scenes it uses a normal TSQLConnection descendent to do the real work. All this happens transparantly to the user code, the universal connector acts and works like any normal connection component.

The type of database can be set in its ConnectorType property. By setting the ConnectorType property, the connector knows which TSQLConnection descendent must be created.

Each TSQLConnection descendent registers itself with a unique name in the initialization section of the unit implementing it: this is the name that should be specified in the ConnectorType of the universal connection. The list of available connections can be retrieved with the call.

From this mechanism it follows that before a particular connection type can be used, its definition must be present in the list of connector types. This means that the unit of the connection type (ibconnection, pqconnection etc.) must be included in the uses clause of the program file: if it is not included, the connection type will not be registered, and it will not be available for use in the universal connector.

The universal connector only exposes the properties common to all connection types (the ones in TSQLConnection). It does not expose properties for all the properties available in specific TSQLConnection descendents. This means that if connection-specific options must be used, they must be included in the Params property of the universal connector in the form Name=Value. When the actual connection instance is created, the connection-specific properties will be set from the specified parameters.

Using SQLDB to access databases

SQLDB can be used to connect to any SQL capable database. It allows to execute SQL statements on any supported database type in a uniform way, and allows to fetch and manipulate result sets (such as returned by a SELECT statement) using a standard TDataset interface. SQLDB takes care that updates to the database are posted automatically to the database, in a cached manner.

When using SQLDB, 3 components are always needed:

  1. A descendent. This represents the connection to the database: the location of the database, and the username and password to authenticate the connection must be specified here. For each supported database type (Firebird, PostgreSQL, MySQL) there is a separate connection component. They all descend from TSQLConnection.
  2. A component. SQLDB allows you to have multiple active but independent transactions in your application. (useful for instance in middle-tier applications). If the native database client library does not support this directly, it is emulated using multiple connections to the database.
  3. A component. This encapsulates an SQL statement. Any kind of SQL statement can be executed. The TSQLQuery component is a TDataset descendent: If the statement returns a result set, then it can be manipulated using the usual TDataset mechanisms.

The 3 components must be linked together: the connection must point to a default transaction (it is used to execute certain queries for metadata), the transaction component must point to a connection component. The TSQLQuery component must point to both a transaction and a database.

So in order to view the contents of a table, typically the procedure goes like this:

{$mode objfpc}{$h+} uses sqldb, ibconnection; Var C : TSQLConnection; T : TSQLTransaction; Q : TSQLQuery; begin // Create a connection. C:=TIBConnection.Create(Nil); try // Set credentials. C.UserName:='MyUSER'; C.Password:='Secret'; C.DatabaseName:='/home/firebird/events.fb'; // Create a transaction. T:=TSQLTransaction.Create(C); // Point to the database instance T.Database:=C; // Now we can open the database. C.Connected:=True; // Create a query to return data Q:=TSQLQuery.Create(C); // Point to database and transaction. Q.Database:=C; Q.Transaction:=T; // Set the SQL select statement Q.SQL.Text:='SELECT * FROM USERS'; // And now use the standard TDataset methods. Q.Open; While not Q.EOF do begin Writeln(Q.FieldByName('U_NAME').AsString); Q.Next end; Q.Close; finally C.Free; end; end.

The above code is quite simple. The connection type is TIBConnection, which is used for Firebird/Interbase databases. To connect to another database (for instance PostgreSQL), the exact same code could be used, but instead of a TIBConnection, a TPQConnection component must be used:

{$mode objfpc}{$h+} uses sqldb, pqconnection; Var C : TSQLConnection; T : TSQLTransaction; Q : TSQLQuery; begin // Create a connection. C:=TPQConnection.Create(Nil);

The rest of the code remains identical.

The above code used an SQL SELECT statement and the Open method to fetch data from the database. Almost the same method applies when trying to execute other kinds of queries, such as DDL queries:

{$mode objfpc}{$h+} uses sqldb, ibconnection; Var C : TSQLConnection; T : TSQLTransaction; Q : TSQLQuery; begin C:=TIBConnection.Create(Nil); try C.UserName:='MyUSER'; C.Password:='Secret'; C.DatabaseName:='/home/firebird/events.fb'; T:=TSQLTransaction.Create(C); T.Database:=C; C.Connected:=True; Q:=TSQLQuery.Create(C); Q.Database:=C; Q.Transaction:=T; // Set the SQL statement. SQL is a tstrings instance. With Q.SQL do begin Add('CREATE TABLE USERS ( '); Add(' U_NAME VARCHAR(50), '); Add(' U_PASSWORD VARCHAR(50) '); Add(' ) '); end; // And now execute the query using ExecSQL // There is no result, so Open cannot be used. Q.ExecSQL; // Commit the transaction. T.Commit; finally C.Free; end; end.

As can be seen from the above example, the setup is the same as in the case of fetching data. Note that can only execute 1 SQL statement during ExecSQL. If many SQL statements must be executed, must be used.

There is much more to TSQLQuery than explained here: it can use parameters (see ) and it can automatically update the data that you edit in it (see ).

Schema type to retrieve TSchemaType describes which schema information to retrieve in the call. Depending on its value, the result set of the dataset will have different fields, describing the requested schema data. The result data will always have the same structure. No schema User Tables in database System tables in database Stored procedures in database Columns in a table Parameters for a stored procedure Indexes for a table Packages (for databases that support them) Connection options This type describes some of the option that a particular connection type supports. The connection type has native support for parameters. Escapes in string literals are done with backslash characters. Escapes in string literals are done by repeating the character. Field names should be quoted in the SQL statements Set of TConnOption TConnOptions describes the full set of options defined by a database. Connection information to be retrieved All information, separated by commas. Server type Server version as a numeric value Server version as a string. Client library name Client library version A type to contain a result row count. An abstract class representing a connection to a SQL Database

TSQLConnection is an abstract class for making a connection to a SQL Database. This class will never be instantiated directly, for each database type a descendent class specific for this database type must be created.

Most of common properties to SQL databases are implemented in this class.

Transaction in which a TSQLQuery is handled TSQLTransaction represents the transaction in which one or more instances are doing their work. It contains the methods for committing or doing a rollback of the results of query. At least one TSQLTransaction must be used for each used in an application. Custom Class to handle SQL commands (with or without result set)

TCustomSQLQuery encapsulates a SQL statement: it implements all the necessary functionality to be able to handle a result set. It can also be used to execute SQL statements that do not return data, using the ExecSQL method.

Do not instantiate a TCustomSQLQuery class directly, instead use the descendent.

Class to handle SQL commands (with or without result set)

TSQLQuery exposes the properties and some methods introduced in . It encapsulates a single SQL statement: it implements all the necessary functionality to be able to handle a result set. It can also be used to execute a single SQL statement that does not return data, using the method.

Typically, the property must be set once, the property as well. Then the property can be set. Depending on the kind of SQL statement, the Open method can be used to retrieve data, or the ExecSQL method can be used to execute the SQL statement (this can be used for DDL statements, or update statements).

Component to execute various SQL statements TSQLScript is a component that can be used to execute many SQL statements using a component. The SQL statements are specified in a script separated by a terminator character (typically a semicolon (;)). Type describing the kind of SQL statement TStatementType describes the kind of SQL statement that was enteredin the SQL property of a component. The statement type could not be detected. The statement is a SQL SELECT statement The statement is a SQL INSERT statement The statement is a SQL UPDATE statement The statement is a SQL DELETE statement The statement is a SQL DDL (Data Definition Language) statement The statement is a SQL get segment statement The statement is a SQL put segment statement The statement executes a stored procedure The statement starts a transaction The statement commits a transaction The statement rolls back a transaction The statement selects data for update Internal object representing a database internal handle

TSQLHandle is an abstract internal object representing a database client handle. It is used by the various connections to implement the connection-specific functionality, and usually represents a low-level handle. It is used by the component to communicate with the descendent.

This object must not be used directly.

Internal object representing a database result set

TSQLCursor is an abstract internal object representing a result set returned by a single SQL select statement (). statement. It is used by the component to handle result sets returned by SQL statements.

This object must not be used directly.

Was the statement prepared Have the field definitions been initialized. Statement type in the SQL property. Array of tokens used to determine the statement type. StatementTokens contains an array of string tokens that are used to detect the type of statement, usually the first SQL keyword of the token. The presence of this token in the SQL statement determines the kind of token. SQLDB specific descendant of the TIndexDefs class. TServerIndexDefs is a simple descendent of TIndexDefs that implements the necessary methods to update the list of definitions using the . It should not be used directly. " Create a new instance of TServerIndexDefs Create will rais an exception if ADataset is not a descendent. An EDatabaseError exception will be raised if ADataset is not a descendent. Dataset for which the index definition collection is created. Updates the list of indexes Update updates the list of indexes, it uses the methods for this. Low level handle used by the connection. Handle represents the low-level handle that the TSQLCOnnection component has received from the client library of the database. Under normal circumstances, this property must not be used. Destroys the instance of the connection. Destroy removes the connection from memory. When a connection is removed, all datasets are closed, and all transactions too. Start the Transaction associated with this Connection

StartTransaction is a convenience method which starts the default transaction (Transaction). It is equivalent to

Connection.Transaction.StartTransaction
If no transaction is assigned, an exception will be raised. EndTransaction
End the Transaction associated with this connection

StartTransaction is a convenience method which ends the default transaction (). It is equivalent to

Connection.Transaction.EndTransaction
If no transaction is assigned, an exception will be raised. StartTransaction
The set of Connection options being used in the Connection ConnOptions is the set of options used by this connection component. It is normally the same value for all connections of the same type Execute a piece of SQL code directly, using a Transaction if specified

ExecuteDirect executes an SQL statement directly. If ATransaction is Nil then the default transaction is used, otherwise the specified transaction is used.

ExecuteDirect does not offer support for parameters, so only statements that do not need parsing and parameters substitution can be handled. If parameter substitution is required, use a component and its ExecSQL method.

If no transaction is assigned, and no transaction is passed, an exception will be raised. ExecSQL
SQL statement to be executed Transaction to be used. The default transaction will be used if none is passed Get a list of the tables in the specified database

GetTableNames will return the names of the tables in the database in List. If SystemTables is True then only the names of system tables will be returned.

List is cleared before adding the names.

Note that the list may depend on the access rights of the user.
String list in which table names will be returned. If True then system table names will also be returned Gets a list of Stored Procedures in the Database

GetProcedureNames will return the names of the stored procedures in the database in List.

List is cleared before adding the names.

String list in which table names will be returned. Gets a list of the field names in the specified table

GetFieldNames will return the names of the fields in TableName in list

List is cleared before adding the names.

If a non-existing tablename is passed, no error will be raised.
Name of the table for to retrieve the field names. Stringlist in which to return the field names. Create a new Database on the server CreateDB will create a new database on the server. Whether or not this functionality is present depends on the type of the connection. The name for the new database is taken from the property, the user credentials are taken from the and properties. If the connection type does not support creating a database, then an EDatabaseError exception is raised. Other exceptions may be raised if the operation fails, e.g. when the user does not have the necessary access rights. Procedure to drop or remove a Database DropDB does the opposite of CreateDB. It removes the database from the server. The database must be connected before this command may be used. Whether or not this functionality is present depends on the type of the connection. If the connection type does not support creating a database, then an EDatabaseError exception is raised. Other exceptions may be raised if the operation fails, e.g. when the user does not have the necessary access rights. Password used when authenticating on the database server

Password is used when authenticating the user specified in UserName when connecting to the database server

This property must be set prior to activating the connection. Changing it while the connection is active has no effect.

Default transaction to be used for this connection Transaction should be set to a instance. It is set as the default transaction when a query is connected to the database, and is used in several metadata operations such as The username for authentication on the database server

UserName is used to to authenticate on the database server when the connection to the database is established.

This property must be set prior to activating the connection. Changing it while the connection is active has no effect.

The character set to be used in this database

Charset can be used to tell the user in which character set the data will be sent to the server, and in which character set the results should be sent to the client. Some connection types will ignore this property, and the data will be sent to the client in the encoding used on the server.

This property must be set prior to activating the connection. Changing it while the connection is active has no effect.

SQLDB will not do anything with this setting except pass it on to the server if a specific connection type supports it. It does not perform any conversions by itself based on the value of this setting.
The name of the host computer where the database resides

HostName is the the name of the host computer where the database server is listening for connection. An empty value means the local machine is used.

This property must be set prior to activating the connection. Changing it while the connection is active has no effect.

Is a connection to the server active or not

Connected indicates whether a connection to the server is active or not. No queries to this server can be activated as long as the value is False

Setting the property to True will attempt a connection to the database DatabaseName on host HostName using the credentials specified in UserName and Password. If the connection or authentication fails, an exception is raised. This has the same effect as calling Open.

Setting the property to False will close the connection to the database. All datasets connected to the database will be closed, all transactions will be closed as well. This has the same effect as calling

Role in which the user is connecting to the database

Role is used to specify the user's role when connecting to the database user. Not all connection types support roles, for those that do not, this property is ignored.

This property must be set prior to activating the connection. Changing it while the connection is active has no effect.

The name of the database to which connection is required.

DatabaseName is the name of the database to which a connection must be made. Some servers need a complete path to a file, others need a symbolic name (an alias): the interpretation of this name depends on the connection type.

This property must be set prior to activating the connection. Changing it while the connection is active has no effect.

Attempt to keep the connection open once it is established. KeepConnection can be used to attempt to keep the connection open once it is established. This property is currently not implemented. Should SQLDB prompt for user credentials when a connection is activated. LoginPrompt can be set to True to force the system to get a username/password pair from the user. How these data are fetched from the used depends on the OnLogin event handler. The UserName and Password properties are ignored in this case. OnLogin Extra connection parameters Params can be used to specify extra parameters to use when establishing a connection to the database. Which parameters can be specified depends on the connection type. Event handler for login process OnLogin will be used when loginPrompt is True. It will be called, and can be used to present a user with a dialog in which the username and password can be asked. Transaction actions (unused) TCommitRollbackAction is currently unused in SQLDB. Do nothing Commit transaction Commit transaction, retaining transaction context Rollback transaction Rollback transaction, retaining transaction context Commit the transaction, end transaction context.

Commit commits an active transaction. The changes will be irreversably written to the database.

After this, the transaction is deactivated and must be reactivated with the StartTransaction method. To commit data while retaining an active transaction, execute CommitRetaining instead.

Executing Commit when no transaction is active will result in an exception. A transaction must be started by calling StartTransaction. If the database backend reports an error, an exception is raised as well. StartTransaction CommitRetaining Rollback RollbackRetaining
Commit the transaction, retain transaction context.

CommitRetaining commits an active transaction. The changes will be irreversably written to the database.

After this, the transaction is still active. To commit data and deactivate the transaction, execute Commit instead.

Executing CommitRetaining when no transaction is active will result in an exception. A transaction must be started by calling StartTransaction. If the database backend reports an error, an exception is raised as well. StartTransaction Retaining Rollback RollbackRetaining
Roll back all changes made in the current transaction.

Rollback undoes all changes in the databack since the start of the transaction. It can only be executed in an active transaction.

After this, the transaction is no longer active. To undo changes but keep an active transaction, execute RollbackRetaining instead.

Changes posted in datasets that are coupled to this transaction will not be undone in memory: these datasets must be reloaded from the database (using Close and Open to reload the data as it is in the database.
Executing Rollback when no transaction is active will result in an exception. A transaction must be started by calling StartTransaction. If the database backend reports an error, an exception is raised as well. StartTransaction CommitRetaining Commit RollbackRetaining
Roll back changes made in the transaction, keep transaction context.

RollbackRetaining undoes all changes in the databack since the start of the transaction. It can only be executed in an active transaction.

After this, the transaction is kept in an active state. To undo changes and close the transaction, execute Rollback instead.

Changes posted in datasets that are coupled to this transaction will not be undone in memory: these datasets must be reloaded from the database (using Close and Open to reload the data as it is in the database.
Executing RollbackRetaining when no transaction is active will result in an exception. A transaction must be started by calling StartTransaction. If the database backend reports an error, an exception is raised as well. StartTransaction Commit Rollback CommitRetaining
Start a new transaction

StartTransaction starts a new transaction context. All changes written to the database must be confirmed with a Commit or can be undone with a Rollback call.

Calling StartTransaction is equivalent to setting Active to True.

If StartTransaction is called while the transaction is still active, an exception will be raised. StartTransaction Commit Rollback CommitRetaining EndTransaction
Create a new transaction Create creates a new TSQLTransaction instance, but does not yet start a transaction context. Owner of the transaction component. Destroy transaction component Destroy will close all datasets connected to it, prior to removing the object from memory. Low-level transaction handle Handle is the low-level transaction handle object. It must not be used in application code. The actual type of this object depends on the type of descendent. End the transaction EndTransaction is equivalent to RollBack. RollBack Currently unused in SQLDB Action is currently unused in SQLDB. Database for which this component is handling connections Database should be set to the particular instance this transaction is handling transactions in. All datasets connected to this transaction component must have the same value for their Database property. Transaction parameters Params can be used to set connection-specific parameters in the form of Key=Value pairs. The contents of this property therefor depends on the type of connection. Prepare a query for execution.

Prepare will prepare the SQL for execution. It will open the database connection if it was not yet open, and will start a transaction if none was started yet. It will then determine the statement type. Finally, it will pass the statement on to the database engine if it supports preparing of queries.

Strictly speaking, it is not necessary to call prepare, the component will prepare the statement whenever it is necessary. If a query will be executed repeatedly, it is good practice to prepare it once before starting to execute it. This will speed up execution, since resources must be allocated only once.

If the SQL server cannot prepare the statement, an exception will be raised.
Unprepare a prepared query

Unprepare will unprepare a prepared query. This means that server resources for this statement are deallocated. After a query was unprepared, any ExecSQL or Open command will prepare the SQL statement again.

Several actions will unprepare the statement: Setting the property, setting the Transaction property or setting the Database property will automaticall call UnPrepare. Closing the dataset will also unprepare the query.

If the SQL server cannot unprepare the statement, an exception may be raised.
Execute a SQL statement that does not return a result set

ExecSQL will execute the statement in , preparing the statement if necessary. It cannot be used to get results from the database (such as returned by a SELECT statement): for this, the Open method must be used.

The SQL property should be a single SQL command. To execute multiple SQL statements, use the component instead.

If the statement is a DML statement, the number of deleted/updated/inserted rows can be determined using .

The Database and Transaction properties must be assigned before calling ExecSQL. Executing an empty SQL statement is also an error.

If the server reports an error, an exception will be raised. TDataset.Open
Create a new instance of TCustomSQLQuery. Create allocates a new instance on the heap and will allocate all resources for the SQL statement. After this it calls the inherited constructor. If not enough memory is available, an exception will be raised. Owner for the new TCustomSQLQuery instance. Destroy instance of TCustomSQLQuery Destroy cleans up the instance, closing the dataset and freeing all allocated resources. SetSchemaInfo prepares the dataset to retrieve schema info.

SetSchemaInfo will prepare the dataset to retrieve schema information from the connection, and represents the schema info as a dataset.

SetSchemaInfo is used internally to prepare a query to retrieve schema information from a connection. It will store the 3 passed parameters, which are then used in the ParseSQL and Prepare stages to optimize the allocated resources. setting the schema type to anything other than stNoSchema will also set (or mimic) the SQL statement as soon as the query is prepared. For connection types that support this, the SQL statement is then set to whatever statement the database connection supports to retrieve schema information.

This is used internally by and to get the necessary schema information from the database.

Schema to use Object name for which to search. May be empty to retrieve all objects Currently unused Is the query prepared ? Prepared is true if Prepare was called for this query, and an UnPrepare was not done after that (take care: several actions call UnPrepare implicitly). Initially, Prepared will be False. Calling Prepare if the query was already prepared has no effect. Return the number of rows (records) affected by the last DML/DDL statement RowsAffected returns the number of rows affected by the last statement executed using ExecSQL. If the connection or database type does not support returning this number, -1 is returned. If the query is not connected to a database, -1 is returned. The number of affected rows or -1 if not supported The TSQLConnection instance on which to execute SQL Statements

Database is the SQL connection (of type ) on which SQL statements will be executed, and from which result sets will be retrieved. This property must be set before any form of SQL command can be executed, just like the Transaction property must be set.

Multiple TSQLQuery instances can be connected to a database at the same time.

Transaction in which to execute SQL statements

Transaction must be set to a SQL transaction (of type ) component. All SQL statements (SQL / InsertSQL / updateSQL / DeleteSQL) etc.) will be executed in the context of this transaction.

The transaction must be connected to the same database instance as the query itself.

Multiple TSQLQuery instances can be connected to a transaction at the same time. If the transaction is rolled back, all changes done by all TSQLQuery instances will be rolled back.

The SQL statement to execute

SQL is the SQL statement that will be executed when ExecSQL is called, or Open is called. It should contain a valid SQL statement for the connection to which the component is connected. SQLDB will not attempt to modify the SQL statement so it is accepted by the SQL engine.

Setting or modifying the SQL statement will call UnPrepare

If ParseSQL is True, the SQL statement will be parsed and the Params property will be updated with the names of the parameters found in the SQL statement.

See also

TDataset.Open
Statement to be used when updating an existing row in the database

UpdateSQL can be used to specify an SQL UPDATE statement, which is used when an existing record was modified in the dataset, and the changes must be written to the database. TSQLQuery can generate an update statement by itself for many cases, but in case it fails, the statement to be used for the update can be specified here.

The SQL statement should be parametrized according to the conventions for specifying parameters. Note that old field values can be specified as :OLD_FIELDNAME

Statement to be used when inserting a new row in the database

InsertSQL can be used to specify an SQL INSERT statement, which is used when a new record was appended to the dataset, and the changes must be written to the database. TSQLQuery can generate an insert statement by itself for many cases, but in case it fails, the statement to be used for the insert can be specified here.

The SQL statement should be parametrized according to the conventions for specifying parameters. Note that old field values can be specified as :OLD_FIELDNAME

Statement to be used when inserting a new row in the database

DeleteSQL can be used to specify an SQL DELETE statement, which is used when an existing record was deleted from the dataset, and the changes must be written to the database. TSQLQuery can generate a delete statement by itself for many cases, but in case it fails, the statement to be used for the insert can be specified here.

The SQL statement should be parametrized according to the conventions for specifying parameters. Note that old field values can be specified as :OLD_FIELDNAME

List of local index Definitions Parameters detected in the SQL statement.

Params contains the parameters used in the SQL statement. This collection is only updated when ParseSQL is True. For each named parameter in the SQL property, a named item will appear in the collection, and the collection will be used to retrieve values from.

When Open or ExecSQL is called, and the Datasource property is not Nil, then for each parameter for which no value was explicitly set (its Bound property is False), the value will be retrieved from the dataset connected to the datasource.

For each parameter, a field with the same name will be searched, and its value and type will be copied to the (unbound) parameter. The parameter remains unbound.

The Update, delete and insert SQL statements are not scanned for parameters.

TParam.Bound
How to create update SQL statements.

UpdateMode determines how the WHERE clause of the UpdateSQL and DeleteSQL statements are auto-generated.

upWhereAll
upWhereChanged
upWhereKeyOnly
Should primary key fields be marked pfInKey

UsePrimaryKeyAsKey can be set to True to let TSQLQuery fetch all server indexes and if there is a primary key, update the ProviderFlags of the fields in the primary key with pfInKey.

The effect of this is that when UpdateMode equals upWhereKeyOnly, then only the fields that are part of the primary key of the table will be used in the update statements. For more information, see .

TField.ProviderFlags pfInKey
Should the SQL statement be parsed or not

ParseSQL can be set to False to prevent TSQLQuery from parsing the SQL property and attempting to detect the statement type or updating the Params or StatementType properties.

This can be used when SQLDB has problems parsing the SQL statement, or when the SQL statement contains parameters that are part of a DDL statement such as a CREATE PROCEDURE statement to create a stored procedure.

Note that in this case the statement will be passed as-is to the SQL engine, no parameter values will be passed on.

SQL statement type

StatementType is determined during the Prepare call when ParseSQL is set to True. It gives an indication of the type of SQL statement that is being executed.

Source for parameter values for unbound parameters

Datasource can be set to a dataset which will be used to retrieve values for the parameters if they were not explicitly specified.

When Open or ExecSQL is called, and the Datasource property is not Nil then for each parameter for which no value was explicitly set (its Bound property is False), the value will be retrieved from the dataset connected to the datasource.

For each parameter, a field with the same name will be searched, and its value and type will be copied to the (unbound) parameter. The parameter remains unbound.

Params ExecSQL TParam.Bound
Append server-side filter to SQL statement

ServerFilter can be set to a valid WHERE clause (without the WHERE keyword). It will be appended to the select statement in SQL, when ServerFiltered is set to True. if ServerFiltered is set to False, ServerFilter is ignored.

If the dataset is active and ServerFiltered is set to true, then changing this property will re-fetch the data from the server.

This property cannot be used when ParseSQL is False, because the statement must be parsed in order to know where the WHERE clause must be inserted: the TSQLQuery class will intelligently insert the clause in an SQL select statement.

Setting this property when ParseSQL is False will result in an exception. ServerFiltered
Should server-side filter be applied ServerFiltered can be set to True to apply ServerFilter. A change in the value for this property will re-fetch the query results if the dataset is active. Setting this property to True when ParseSQL is False will result in an exception. ParseSQL ServerFilter List of indexes on the primary table of the query ServerIndexDefs will be filled - during the Prepare call - with the list of indexes defined on the primary table in the query if UsePrimaryKeyAsKey is True. If a primary key is found, then the fields in it will be marked UsePrimaryKeyAsKey Prepare Create a new TSQLScript instance. Create instantiates a instance which will be used to execute the queries, and then calls the inherited constructor. Owner for the new instance. Remove the TSQLScript instance from memory. Destroy frees the instance that was created during the Create constructor from memory and then calls the inherited destructor. Convenience function, simply calls Execute ExecuteScript is a convenience function, it simply calls Execute. The statements in the script will be executed one by one. The script to execute

Script contains the list of SQL statements to be executed. The statements should be separated by the character specified in the Terminator property. Each of the statement will be executed on the database specified in Database. using the equivalent of the statement. The statements should not return result sets, but other than that all kind of statements are allowed.

Comments will be conserved and passed on in the statements to be executed, depending on the value of the property. If that property is False, comments will be stripped prior to executing the SQL statements.

Database on which to execute the script Database should be set to the descendent. All SQL statements in the Script property will be executed on this database. Transaction to use in the script Transaction is the transaction instance to use when executing statements. If the SQL script contains any COMMIT statements, they will be handled using the method. Universal connection component

TSQLConnector implements a general connection type. When switching database backends, the normal procedure is to replace one instance of descendent with another, and connect all instances of and to the new connection.

Using TSQLConnector avoids this: the type of connection can be set using the ConnectorType property, which is a string property. The TSQLConnector class will (in the background) create the correct descendent to handle all actual operations on the database.

In all other respects, TSQLConnector acts like a regular TSQLConnection instance. Since no access to the actually used TSQLConnection descendent is available, connection-specific calls are not available.

Name of the connection type to use ConnectorType should be set to one of the availabe connector types in the application. The list of possible connector types can be retrieved using call. The ConnectorType property can only be set when the connection is not active. Attempting to change the ConnectorType property while the connection is active will result in an exception. Class of TSQLConnection type TSQLConnectionClass is used when registering a new connection type for use in the universal connector Connection type definition class TConnectionDef is an abstract class. When registering a new connection type for use in the universal connector, a descendent of this class must be made and registered using . A descendent class should override at least the and methods to return the specific name and connection class to use. Name of the connection type

TypeName is overridden by descendent classes to return the unique name for this connection type. It is what the property should be set to select this connection type for the universal connection, and is the name that the call will use when looking for a connection type. It must be overidden by descendents of TConnectionDef.

This name is also returned in the list returned by

This name can be an arbitrary name, no restrictions on the allowed characters exist.

Unique name for the connection type Class to instantiate when this connection is requested

ConnectionClass should return the connection class to use when a connection of this type is reqested. It must be overidden by descendents of TConnectionDef.

It may not be Nil.

The TSQLConnectionClass for this connection type. A descriptive text for this connection type Description should return a descriptive text for this connection type. It is used for display purposes only, so ideally it should be a one-liner. It can be used to provide more information about the particulars of the connection type. A description of the connection type. Apply parameters to an instance of TSQLConnection

ApplyParams must be overridden to apply any params specified in the Params argument to the descendent in AConnection. It can be used to convert Name=Value pairs to properties of the actual connection instance.

When called, AConnection is guaranteed to be of the same type as returned by . Params contains the contents of the property of the connector.

Parameters to apply in Name=Value form Connection instance to which to apply the parameters Class of TConnectionDef TConnectionDefClass is used in the call to register a new instance. Register a new connection type for use in the universal connector

RegisterConnection must be called with a class pointer to a descendent to register the connection type described in the descendent. The connection type is registered with the name as returned by .

The various connection types distributed by Free Pascal automatically call RegisterConnection from the initialization section of their unit, so simply including the unit with a particular connection type is enough to register it.

Connection types registered with this call can be unregistered with .

if Def is Nil, access violations will occur.
The connection type definition to register. Unregister a registered connection type UnRegisterConnection will unregister the connection Def. If a connection with ConnectionName or with name as returned by the TypeName method from Def was previously registered, it will be removed from the list of registered connection types. if Def is Nil, access violations will occur. The connection type definition to unregister. The name of the connection type definition to unregister. Search for a connection definition by name

GetConnectionDef will search in the list of connection type definitions, and will return the one definition with the name that matches ConnectorName. The search is case insensitive.

If no definition is found, Nil is returned.

The connection type definition, Nil if not found. The name of the connection type to search Return a list of connection definition names. GetConnectionList clears List and fills it with the list of currently known connection type names, as registered with . The names are the names as returned by List to fill with connection names. Will be cleared All connection information Server type description Server version as an integer number Server version as a string Client library name Client library version Unknown (other) information Type of database event TDBEventType describes the type of a database event message as generated by through the event. Custom event message SQL prepare message SQLExecute message Fetch data message Transaction Commit message Transaction rollback message Set of database event types TDBEventTypes is a set of values, which is used to filter the set of event messages that should be sent. The property determines which events a particular connection will send. Event handler prototype for handling events TDBLogNotifyEvent is the prototype for the event handler and for the global event handling hook. Sender will contain the instance that caused the event, EventType will contain the event type, and Msg will contain the actual message: the content depends on the type of the message. TSQLConnection instance that sent the event. Event type Event message. Actual content depends on the type of message. Selectable query or not FSelectable exists for internal use. It should not be used by applications. Schema type requested FSchemaType exists for internal use. It should not be used by applications. Type to describe quote characters. TQuoteChars is an array of characters that describes the used delimiters for string values. Single quote delimiters SingleQuotes is the set of delimiters used when using single quotes for string literals. Double quote delimiters DoubleQuotes is the set of delimiters used when using double quotes for string literals. Constant that can be used to select all events. LogAllEvents is a constant that contains the full set of available event types. It can be used to set . Characters used to quote field names. FieldNameQuoteChars can be set to specify the characters that should be used to delimit field names in SQL statements generated by SQLDB. It is normally initialized correctly by the descendent to the default for that particular connection type. Create a new instance of TSQLConnection Create initialized a new instance of . After calling the inherited constructor, it will initialize the FieldNameQuoteChars property and some other fields for internal use. FieldNameQuoteChars Owner for the new TSQLConnectioninstance Return some information about the connection GetConnectionInfo can be used to return some information about the connection. Which information is returned depends on the InfoType parameter. The information is returned as a string. If citAll is passed, then the result will be a comma-separated list of values, each of the values enclosed in double quotes. Requested information as a string value. Connection information to be returned. Event handler for logging events

TSQLConnection can send events for all the actions that it performs: executing SQL statements, committ and rollback of transactions etc. This event handler must be set to react on these events: they can for example be written to a log file. Only events specified in the LogEvents property will be logged.

The events received by this event handler are specific for this connection. To receive events from all active connections in the application, set the global event handler.

Filter for events to log LogEvents can be used to filter the events which should be sent to the OnLog and event handlers. Only event types that are listed in this property will be sent. Schema type to use Name of Object for which to return schema information. Pattern for schema information Return parameter by name

ParamByName is a shortcut for Params.ParamByName. The 2 following pieces of code are completely equivalent:

Qry.ParamByName('id').AsInteger:=123;

and

Qry.Params.ParamByName('id').AsInteger:=123;
Params.ParamByName
Resulting TParam instance. Name of parameter to look for. Case insensitive. Schema type SchemaType is the schema type set by . It determines what kind of schema information will be returned by the TSQLQuery instance. Maximum allowed number of indexes.

MaxIndexesCount determines the number of index entries that the dataset will reserve for indexes. No more indexes than indicated here can be used. The property must be set before the dataset is opened. The minimum value for this property is 1. The default value is 2.

If an index is added and the current index count equals MaxIndexesCount, an exception will be raised.

Attempting to set this property while the dataset is active will raise an exception.
List of field definitions. Execute the script.

Execute will execute the statements specified in Script one by one, till the last statement is processed or an exception is raised.

If an error occurs during execution, normally an exception is raised. If the event handler is set, it may stop the event handler.

Handle errors using . Script
Event handler if a directive is encountered OnDirective is called when a directive is encountered. When parsing the script, the script engine checks the first word of the statement. If it matches one of the words in Directives property then the OnDirective event handler is called with the name of the directive and the rest of the statement as parameters. This can be used to handle all kind of pre-processing actions such as Set term \^ ; Directives List of directives Directives is a stringlist with words that should be recognized as directives. They will be handled using the OnDirective event handler. The list should contain one word per line, no spaces allowed. OnDirective Defined macros Defines contains the list of defined macros for use with the property. Each line should contain a macro name. The names of the macros are case insensitive. The #DEFINE and #UNDEFINE directives will add or remove macro names from this list. Terminator character. Terminator is the character used by TSQLScript to delimit SQL statements. By default it equals the semicolon (;), which is the customary SQL command terminating character. By itself TSQLScript does not recognize complex statements such as Create Procedure which can contain terminator characters such as ";". Instead, TSQLScript will scan the script for the Terminator character. Using directives such as SET TERM the terminator character may be changed in the script. OnDirective Directives Should comments be passed to the SQL engine ?

CommentsInSQL can be set to True to let TSQLScript preserve any comments it finds in the script. The comments will be passed to the SQLConnection as part of the commands. If the property is set to False the comments are discarded.

By default, TSQLScript discards comments.

Should the SET TERM directive be recognized

UseSetTerm can be set to True to let TSQLScript automatically handle the SET TERM directive and set the character based on the value specified in the SET TERM directive. This means that the following directive:

SET TERM ^ ;

will set the terminator to the caret character. Conversely, the

SET TERM ; ^

will then switch the terminator character back to the commonly used semicolon (;).

Control automatic handling of the COMMIT command.

UseCommit can be set to True to let TSQLScript automatically handle the commit command as a directive. If it is set, the COMMIT command is registered as a directive, and the will be commited and restarted at once whenever the COMMIT directive appears in the script.

If this property is set to False then the commit command will be passed on to the SQL engine like any other SQL command in the script.

Automatically handle pre-processor defines

UseDefines will automatically register the following pre-processing directives:

#IFDEF #IFNDEF #ELSE #ENDIF #DEFINE #UNDEF #UNDEFINE

Additionally, these directives will be automatically handled by the TSQLScript component. This can be used to add conditional execution of the SQL script: they are treated as the conditional compilation statements found in the C macro preprocessor or the FPC conditional compilation features. The initial list of defined macros can be specified in the Defines property, where one define per line can be specified.

In the following example, the correct statement to create a sequence is selected based on the presence of the macro FIREBIRD in the list of defines:

#IFDEF FIREBIRD CREATE GENERATOR GEN_MYID; #ELSE CREATE SEQUENCE GEN_MYID; #ENDIF
Exception handling event OnException can be set to handle an exception during the execution of a statement or directive when the script is executed. The exception is passed to the handler in the TheException parameter. On return, the value of the Continue parameter is checked: if it is set to True, then the exception is ignored. If it is set to False (the default), then the exception is re-raised, and script execution will stop. Library loading function prototype TLibraryLoadFunction is the function prototype for dynamically loading a library when the universal connection component is used. It receives the name of the library to load (S), and should return True if the library was succesfully loaded. It is used in the connection definition. True if the library was succesfully loaded Name of the library to load. Library unloading function prototype TLibraryUnLoadFunction is the function prototype for dynamically unloading a library when the universal connection component is used. It has no parameters, and should simply unload the library loaded with Default library name DefaultLibraryName should be set to the default library name for the connection. This can be used to let SQLDB automatically load the library needed when a connection of this type is requested. Name of the library to load Return a function to call when the client library must be loaded LoadFunction must return the function that will be called when the client library for this connection type must be loaded. This method must be overridden by descendent classes to return a function that will correctly load the client library when a connection of this type is used. The function to call when the client library must be loaded Return a function to call when the client library must be unloaded UnLoadFunction must return the function that will be called when the client library for this connection type must be unloaded. This method must be overridden by descendent classes to return a function that will correctly unload the client library when a connection of this type is no longer used. The function to call when the client library must be unloaded Currently loaded library. LoadedLibraryName must be overridden by descendents to return the filename of the currenly loaded client library for this connection type. If no library is loaded, an empty string must be returned. Name of the currently loaded library Global logging hook GlobalDBLogHook can be set in addition to local event handlers. All connections will report events through this global event handler in addition to their OnLog event handlers. The global log event handler can be set only once, so when setting the handler, it is important to set up chaining: saving the previous value, and calling the old handler (if it was set) in the new handler. Default settings to be used in SQL DefaultSQLFormatSettings contains the default settings used when formatting date/time and other special values in Update SQL statements generated by the various descendents. List of schemas in database(s) Record to describe a SQL statement

TSQLStatementInfo is a record used to describe an SQL statement. It is used internally by the and objects to analyse SQL statements.

It is used to be able to modify the SQL statement (for additional filtering) or to determine the table to update when applying dataset updates to the database.

Type of SQL statement Tablename to be used in updates Updateable SQL result set ? Where clause start position Where clause end position Object to execute SQL statements without result set.

TCustomSQLStatement is a light-weight object that can be used to execute SQL statements on a database. It does not support result sets, and has none of the methods that a component has. It can be used to execute SQL statements on a database that update data, execute stored procedures and DDL statements etc.

The TCustomSQLStatement is equivalent to in that it supports transactions (in the Transaction property) and parameters (in the Params property) and as such is a more versatile tool than executing queries using .

To use a TCustomSQLStatement is simple and similar to the use of : set the Database property to an existing connection component, and set the Transaction property. After setting the SQL property and filling Params, the SQL statement can be executed with the method.

TCustomSQLStatement is a parent class. Many of the properties are only made public (or published) in the class, which should be instantiated instead of the TCustomSQLStatement class.

Get database schema names GetSchemaNames returns a list of schemas defined in the database. On return, filled with schema names, one per line Create a new instance of TCustomSQLStatement Create initializes a new instance of TCustomSQLStatement and sets the SQL Params, ParamCheck and ParseSQL to their initial values. Owner of the new TCustomSQLStatement instance. Destroy a TCustomSQLStatement instance. Destroy disconnects the TCustomSQLStatement instance from the transaction and database, and then frees the memory taken by the instance and its properties. Prepare the statement for execution Prepare prepares the SQL statement for execution. It is called automatically if is called and the statement was not yet prepared. Depending on the database engine, it will also allocate the necessary resources on the database server. An exception is raised if there is no SQL statement set or the Database or Transaction properties are empty. Execute the SQL statement. Execute executes the statement on the database. If necessary, it will first open the connection and start a transaction, followed by a call to Prepare.

An exception is raised if there is no SQL statement set or the Database or Transaction properties are empty.

If an error occurs at the database level (the SQL failed to execute properly) then an exception is raised as well.

Unprepare a previously prepared statement Unprepare unprepares a prepared SQL statement. It is called automatically when the SQL statement is changed. Depending on the database engine, it will also de-allocate any allocated resources on the database server. if the statement is not in a prepared state, nothing happens. If an error occurs at the database level (the unprepare operation failed to execute properly) then an exception is raised. Find a parameter by name ParamByName finds the parameter AParamName in the Params property. If no parameter with the given name is found, an exception is raised. The parameter with name AParamName Parameter to search for. Number of rows affected by the SQL statement. RowsAffected is set to the number of affected rows after was called. Not all databases may support this. The number of affected rows by the last executed SQL command. Is the statement prepared or not Prepared equals True if was called (implicitly or explictly), it returns False if not. It can be set to True or False to call or , respectively. Class to execute non-select SQL statements. TSQLStatement is a descendent of which simply publishes the protected properties of that component. Database instance to execute statement on. Database must be set to an instance of a descendent. It must be set, together with in order to be able to call Prepare or Execute. Prepare Execute Datasource to copy parameter values from Datasource can be set to a instance. When Execute is called, any unbound parameters remain empty, but if DataSource is set, the value of these parameters will be searched in the fields of the associated dataset. If a field with a name equal to the parameter is found, the value of that field is copied to the parameter. No such field exists, an exception is raised. Execute Should SQL be checked for parameters

ParamCheck must be set to False to disable the parameter check. The default value True indicates that the SQL statement should be checked for parameter names (in the form :ParamName), and corresponding TParam instances should be added to the Params property.

When executing some DDL statements, e.g. a "create procedure" SQL statement can contain parameters. These parameters should not be converted to TParam instances.

TParam
List of parameters. Params contains an item for each of the parameters in the statement (in the form :ParamName). The collection is filled automatically if the property is True. Parse the SQL statement ParseSQL can be set to False to disable parsing of the property when it is set. The default behaviour (ParseSQL=True) is to parse the statement and detect what kind of SQL statement it is. The SQL statement to execute

SQL must be set to the SQL statement to execute. It must not be a statement that returns a result set. This is the statement that will be passed on to the database engine when Prepare is called.

If equals True (the default), the SQL statement can contain parameter names where literal values can occur, in the form :ParamName. Keywords or table names cannot be specified as parameters. If the underlying database engine supports it, the parameter support of the database will be used to transfer the values from the collection. If not, it will be emulated. The Params collection is automatically populated when the SQL statement is set.

Some databases support executing multiple SQL statements in 1 call. Therefor, no attempt is done to ensure that SQL contains a single SQL statement. However, error reporting and the RowsAffected function may be wrong in such a case.

Prepare RowsAffected
The transaction in which the SQL statement should be executed. Transaction should be set to a transaction connected to the instance of the database set in the property. This must be set before Prepare is called. Prepare Should the SQL statement be checked for parameters

ParamCheck must be set to False to disable the parameter check. The default value True indicates that the SQL statement should be checked for parameter names (in the form :ParamName), and corresponding TParam instances should be added to the Params property.

When executing some DDL statements, e.g. a "create procedure" SQL statement can contain parameters. These parameters should not be converted to TParam instances.

TParam