Building and executing dynamic SQL statements v16
The following examples show four techniques for building and executing dynamic SQL statements. Each example shows processing a different combination of statement and input types:
- The first example shows processing and executing a SQL statement that doesn't contain a
SELECT
statement and doesn't require input variables. This example corresponds to the techniques used by Oracle Dynamic SQL Method 1. - The second example shows processing and executing a SQL statement that doesn't contain a
SELECT
statement and contains a known number of input variables. This example corresponds to the techniques used by Oracle Dynamic SQL Method 2. - The third example shows processing and executing a SQL statement that might contain a
SELECT
statement and includes a known number of input variables. This example corresponds to the techniques used by Oracle Dynamic SQL Method 3. - The fourth example shows processing and executing a SQL statement that might contain a
SELECT
statement and includes an unknown number of input variables. This example corresponds to the techniques used by Oracle Dynamic SQL Method 4.
Example: Executing a nonquery statement without parameters
This example shows how to use the EXECUTE IMMEDIATE
command to execute a SQL statement, where the text of the statement isn't known until you run the application. You can't use EXECUTE IMMEDIATE
to execute a statement that returns a result set. You can't use EXECUTE IMMEDIATE
to execute a statement that contains parameter placeholders.
The EXECUTE IMMEDIATE
statement parses and plans the SQL statement each time it executes, which can have a negative impact on the performance of your application. If you plan to execute the same statement repeatedly, consider using the PREPARE/EXECUTE
technique described in Example: Executing a nonquery statement with a specified number of placeholders.
The code sample begins by including the prototypes and type definitions for the C stdio
, string
, and stdlib
libraries and providing basic infrastructure for the program:
The example then sets up an error handler. ECPGPlus calls the handle_error()
function whenever a SQL error occurs:
Then, the example connects to the database using the credentials specified on the command line:
Next, the program uses an EXECUTE IMMEDIATE
statement to execute a SQL statement, adding a row to the dept
table:
If the EXECUTE IMMEDIATE
command fails, ECPGPlus invokes the handle_error()
function, which terminates the application after displaying an error message to the user. If the EXECUTE IMMEDIATE
command succeeds, the application displays a message (ok
) to the user, commits the changes, disconnects from the server, and terminates the application:
ECPGPlus calls the handle_error()
function whenever it encounters a SQL error. The handle_error()
function prints the content of the error message, resets the error handler, rolls back any changes, disconnects from the database, and terminates the application:
Example: Executing a nonquery statement with a specified number of placeholders
To execute a nonquery command that includes a known number of parameter placeholders, you must first PREPARE
the statement (providing a statement handle) and then EXECUTE
the statement using the statement handle. When the application executes the statement, it must provide a value for each placeholder found in the statement.
When an application uses the PREPARE/EXECUTE
mechanism, each SQL statement is parsed and planned once but might execute many times, providing different values each time.
ECPGPlus converts each parameter value to the type required by the SQL statement, if possible. Otherwise, ECPGPlus reports an error.
The code sample begins by including the prototypes and type definitions for the C stdio
, string
, stdlib
, and sqlca
libraries and providing basic infrastructure for the program:
The example then sets up an error handler. ECPGPlus calls the handle_error()
function whenever a SQL error occurs.
Then, the example connects to the database using the credentials specified on the command line:
Next, the program uses a PREPARE
statement to parse and plan a statement that includes three parameter markers. If the PREPARE
statement succeeds, it creates a statement handle that you can use to execute the statement. (In this example, the statement handle is named stmtHandle
.) You can execute a given statement multiple times using the same statement handle.
After parsing and planning the statement, the application uses the EXECUTE
statement to execute the statement associated with the statement handle, substituting user-provided values for the parameter markers:
If the EXECUTE
command fails, ECPGPlus invokes the handle_error()
function, which terminates the application after displaying an error message to the user. If the EXECUTE
command succeeds, the application displays a message (ok
) to the user, commits the changes, disconnects from the server, and terminates the application:
ECPGPlus calls the handle_error()
function whenever it encounters a SQL error. The handle_error()
function prints the content of the error message, resets the error handler, rolls back any changes, disconnects from the database, and terminates the application:
Example: Executing a query with a known number of placeholders
This example shows how to execute a query with a known number of input parameters and with a known number of columns in the result set. This method uses the PREPARE
statement to parse and plan a query and then opens a cursor and iterates through the result set.
The code sample begins by including the prototypes and type definitions for the C stdio
, string
, stdlib
, stdbool
, and sqlca
libraries and providing basic infrastructure for the program:
The example then sets up an error handler. ECPGPlus calls the handle_error()
function whenever a SQL error occurs:
Then, the example connects to the database using the credentials specified on the command line:
Next, the program uses a PREPARE
statement to parse and plan a query that includes a single parameter marker. If the PREPARE
statement succeeds, it creates a statement handle that you can use to execute the statement. (In this example, the statement handle is named stmtHandle
.) You can execute a given statement multiple times using the same statement handle.
The program then declares and opens the cursor empCursor
, substituting a user-provided value for the parameter marker in the prepared SELECT
statement. The OPEN
statement includes a USING
clause, which must provide a value for each placeholder found in the query:
The program iterates through the cursor and prints the employee number and name of each employee in the selected department:
The program then closes the cursor, commits any changes, disconnects from the server, and terminates the application:
The application calls the handle_error()
function whenever it encounters a SQL error. The handle_error()
function prints the content of the error message, resets the error handler, rolls back any changes, disconnects from the database, and terminates the application:
Example: Executing a query with an unknown number of variables
This example shows executing a query with an unknown number of input parameters or columns in the result set. This type of query might occur when you prompt the user for the text of the query or when a query is assembled from a form on which the user chooses from a number of conditions (i.e., a filter).
The code sample begins by including the prototypes and type definitions for the C stdio
and stdlib
libraries. In addition, the program includes the sqlda.h
and sqlcpr.h
header files. sqlda.h
defines the SQLDA structure used throughout this example. sqlcpr.h
defines a small set of functions used to interrogate the metadata found in an SQLDA structure.
Next, the program declares pointers to two SQLDA structures. The first SQLDA structure (params
) is used to describe the metadata for any parameter markers found in the dynamic query text. The second SQLDA structure (results
) contains both the metadata and the result set obtained by executing the dynamic query.
The program then declares two helper functions, which are defined near the end of the code sample:
Next, the program declares three host variables. The first two (username
and password
) are used to connect to the database server. The third host variable (stmtTxt
) is a NULL-terminated C string containing the text of the query to execute. The values for these three host variables are derived from the command-line arguments. When the program begins to execute, it sets up an error handler and then connects to the database server:
Next, the program calls the sqlald()
function to allocate the memory required for each descriptor. Each descriptor contains pointers to arrays of:
- Column names
- Indicator names
- Data types
- Lengths
- Data values
When you allocate an SQLDA
descriptor, you specify the maximum number of columns you expect to find in the result set (for SELECT
-list descriptors) or the maximum number of parameters you expect to find the dynamic query text (for bind-variable descriptors). In this case, we specify that we expect no more than 20 columns and 20 parameters. You must also specify a maximum length for each column or parameter name and each indicator variable name. In this case, we expect names to be no more than 64 bytes long.
See SQLDA structure for a complete description of the SQLDA
structure.
After allocating the SELECT
-list and bind descriptors, the program prepares the dynamic statement and declares a cursor over the result set.
Next, the program calls the bindParams()
function. The bindParams()
function examines the bind descriptor (params)
and prompts the user for a value to substitute in place of each parameter marker found in the dynamic query.
Finally, the program opens the cursor (using any parameter values supplied by the user) and calls the displayResultSet()
function to print the result set produced by the query:
The bindParams()
function determines whether the dynamic query contains any parameter markers. If so, it prompts the user for a value for each parameter and then binds that value to the corresponding marker. The DESCRIBE BIND VARIABLE
statement populates the params
SQLDA structure with information describing each parameter marker:
If the statement contains no parameter markers, params->F
contains 0. If the statement contains more parameters than fit into the descriptor, params->F
contains a negative number. In this case, the absolute value of params->F
indicates the number of parameter markers found in the statement. If params->F
contains a positive number, that number indicates how many parameter markers were found in the statement.
Next, the program executes a loop that prompts the user for a value, iterating once for each parameter marker found in the statement:
After prompting the user for a value for a given parameter, the program binds that value to the parameter by setting:
params->T[i]
to indicate the data type of the valueparams->L[i]
to the length of the value (we subtract one to trim off the trailing new-line character added byfgets()
)params->V[i]
to point to a copy of the NULL-terminated string provided by the user
The displayResultSet()
function loops through each row in the result set and prints the value found in each column. displayResultSet()
starts by executing a DESCRIBE SELECT LIST
statement. This statement populates an SQLDA descriptor (results
) with a description of each column in the result set.
If the dynamic statement returns no columns (that is, the dynamic statement is not a SELECT
statement), results->F
contains 0. If the statement returns more columns than fit into the descriptor, results->F
contains a negative number. In this case, the absolute value of results->F
indicates the number of columns returned by the statement. If results->F
contains a positive number, that number indicates how many columns were returned by the query.
Next, the program enters a loop, iterating once for each column in the result set: