Conformance
Version Introduced:ODBC 1.0
Standards Compliance:ISO 92
Summary
SQLPutData allows an application to send data for a parameter or column to the driver at statement execution time. This function can be used to send character or binary data values in parts to a column with a character, binary, or data source – specific data type (for example, parameters of the SQL_LONGVARBINARY or SQL_LONGVARCHAR types). SQLPutData supports binding to a Unicode C data type, even if the underlying driver does not support Unicode data.
Syntax
SQLRETURN SQLPutData(
SQLHSTMTStatementHandle,
SQLPOINTERDataPtr,
SQLINTEGERStrLen_or_Ind);
Arguments
StatementHandle
[Input]
Statement handle.
DataPtr
[Input]
Pointer to a buffer containing the actual data for the parameter or column. The data must be in the C data type specified in the ValueType argument of SQLBindParameter (for parameter data) or the TargetType argument of SQLBindCol (for column data).
StrLen_or_Ind
[Input]
Length of *DataPtr. Specifies the amount of data sent in a call to SQLPutData. The amount of data can vary with each call for a given parameter or column. StrLen_or_Ind is ignored unless it is one of the following:
For all other types of C data, if StrLen_or_Ind is not SQL_NULL_DATA or SQL_DEFAULT_PARAM, the driver assumes that the size of the *DataPtr buffer is the size of the C data type specified with ValueType or TargetType and sends the entire data value. For more information, see “Converting Data from C to SQL Data Types" in Appendix D, “Data Types.”
Returns
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_STILL_EXECUTING, SQL_ERROR, or SQL_INVALID_HANDLE.
Diagnostics
When SQLPutData returns SQL_ERROR or SQL_SUCCESS_WITH_INFO, an associated SQLSTATE value can be obtained by calling SQLGetDiagRec with a HandleType of SQL_HANDLE_STMT and a Handle of StatementHandle. The following table lists the SQLSTATE values commonly returned by SQLPutData and explains each one in the context of this function; the notation “(DM)” precedes the descriptions of SQLSTATEs returned by the Driver Manager. The return code associated with each SQLSTATE value is SQL_ERROR, unless noted otherwise.
SQLSTATE | Error | Description |
01000 | General warning | Driver-specific informational message. (Function returns SQL_SUCCESS_WITH_INFO.) |
01004 | String data, right truncated | String or binary data returned for an output parameter resulted in the truncation of non-blank character or non-NULL binary data. If it was a string value, it was right truncated. (Function returns SQL_SUCCESS_WITH_INFO.) |
07006 | Restricted data type attribute violation |
The data value identified by the ValueType argument in SQLBindParameter for the bound parameter could not be converted to the data type identified by the ParameterType argument in SQLBindParameter. |
07S01 | Invalid use of default parameter | A parameter value, set with SQLBindParameter, was SQL_DEFAULT_PARAM, and the corresponding parameter did not have a default value. |
08S01 | Communication link failure | The communication link between the driver and the data source to which the driver was connected failed before the function completed processing. |
22001 | String data, right truncation | The assignment of a character or binary value to a column resulted in the truncation of non-blank (character) or non-null (binary) characters or bytes. The SQL_NEED_LONG_DATA_LEN information type in SQLGetInfo was “Y” and more data was sent for a long parameter (the data type was SQL_LONGVARCHAR, SQL_LONGVARBINARY, or a long, data source – specific data type) than was specified with the StrLen_or_IndPtr argument in SQLBindParameter. The SQL_NEED_LONG_DATA_LEN information type in SQLGetInfo was “Y” and more data was sent for a long column (the data type was SQL_LONGVARCHAR, SQL_LONGVARBINARY, or a long, data source – specific data type) than was specified in the length buffer corresponding to a column in a row of data that was added or updated with SQLBulkOperations, or updated with SQLSetPos. |
22003 | Numeric value out of range | The data sent for a bound numeric parameter or column caused the whole (as opposed to fractional) part of the number to be truncated when assigned to the associated table column. Returning a numeric value (as numeric or string) for one or more input/output or output parameters would have caused the whole (as opposed to fractional) part of the number to be truncated. |
22007 | Invalid datetime format | The data sent for a parameter or column that was bound to a date, time, or timestamp structure was, respectively, an invalid date, time, or timestamp. An input/output or output parameter was bound to a date, time, or timestamp C structure, and a value in the returned parameter was, respectively, an invalid date, time, or timestamp. (Function returns SQL_SUCCESS_WITH_INFO.) |
22008 | Datetime field overflow | A datetime expression computed for an input/output or output parameter resulted in a date, time, or timestamp C structure that was invalid. |
22012 | Division by zero | An arithmetic expression calculated for an input/output or output parameter resulted in division by zero. |
22015 | Interval field overflow | The data sent for an exact numeric or interval column or parameter to an interval SQL data type caused a loss of significant digits. Data was sent for an interval column or parameter with more than one field, and was converted to a numeric data type, and had no representation in the numeric data type. The data sent for column or parameter data was assigned to an interval SQL type, and there was no representation of the value of the C type in the interval SQL type. The data sent for an exact numeric or interval C column or parameter to an interval C type caused a loss of significant digits. The data sent for column or parameter data was assigned to an interval C structure, and there was no representation of the data in the interval data structure. |
22018 | Invalid character value for cast specification | The C type was an exact or approximate numeric, a datetime, or an interval data type; the SQL type of the column was a character data type; and the value in the column or parameter was not a valid literal of the bound C type. The SQL type was an exact or approximate numeric, a datetime, or an interval data type; the C type was SQL_C_CHAR; and the value in the column or parameter was not a valid literal of the bound SQL type. |
HY000 | General error | An error occurred for which there was no specific SQLSTATE and for which no implementation-specific SQLSTATE was defined. The error message returned by SQLGetDiagRec in the *MessageText buffer describes the error and its cause. |
HY001 | Memory allocation error | The driver was unable to allocate memory required to support execution or completion of the function. |
HY008 | Operation canceled | Asynchronous processing was enabled for the StatementHandle. The function was called and, before it completed execution, SQLCancel was called on the StatementHandle. Then the function was called again on the StatementHandle. The function was called and, before it completed execution, SQLCancel was called on the StatementHandle from a different thread in a multithread application. |
HY009 | Invalid use of null pointer | (DM) The argument DataPtr was a null pointer and the argument StrLen_or_Ind was not 0, SQL_DEFAULT_PARAM, or SQL_NULL_DATA. |
HY010 | Function sequence error | (DM) The previous function call was not a call to SQLPutData or SQLParamData. |
(DM) An asynchronously executing function (not this one) was called for the StatementHandle and was still executing when this function was called. | ||
HY013 | Memory management error | The function call could not be processed because the underlying memory objects could not be accessed, possibly because of low memory conditions. |
HY019 | Non-character and non-binary data sent in pieces | SQLPutData was called more than once for a parameter or column and it was not being used to send character C data to a column with a character, binary, or data source – specific data type or to send binary C data to a column with a character, binary, or data source – specific data type. |
HY020 | Attempt to concatenate a null value | SQLPutData was called more than once since the call that returned SQL_NEED_DATA, and in one of those calls, the StrLen_or_Ind argument contained SQL_NULL_DATA or SQL_DEFAULT_PARAM. |
HY090 | Invalid string or buffer length | The argument DataPtr was not a null pointer and the argument StrLen_or_Ind was less than 0, but not equal to SQL_NTS or SQL_NULL_DATA. |
HYT01 | Connection timeout expired | The connection timeout period expired before the data source responded to the request. The connection timeout period is set through SQLSetConnectAttr, SQL_ATTR_CONNECTION_TIMEOUT. |
IM001 | Driver does not support this function | (DM) The driver associated with the StatementHandle does not support the function. |
If SQLPutData is called while sending data for a parameter in an SQL statement, it can return any SQLSTATE that can be returned by the function called to execute the statement (SQLExecute or SQLExecDirect). If it is called while sending data for a column being updated or added with SQLBulkOperations, or updated with SQLSetPos, it can return any SQLSTATE that can be returned by SQLBulkOperations or SQLSetPos.
Comments
SQLPutData can be called to supply data-at-execution data for two uses: parameter data to be used in a call to SQLExecute or SQLExecDirect, or column data to be used when a row is updated or added by a call to SQLBulkOperations, or updated by a call to SQLSetPos.
When an application calls SQLParamData to determine which data it should send, the driver returns an indicator that the application can use to determine which parameter data to send, or where column data can be found. It also returns SQL_NEED_DATA, which is an indicator to the application that it should call SQLPutData to send the data. In the DataPtr argument to SQLPutData, the application passes a pointer to the buffer containing the actual data for the parameter or column.
When the driver returns SQL_SUCCESS for SQLPutData, the application calls SQLParamData again. SQLParamData returns SQL_NEED_DATA if more data needs to be sent, in which case the application calls SQLPutData again. It returns SQL_SUCCESS if all data-at-execution data has been sent. The application then calls SQLParamData again. If the driver returns SQL_NEED_DATA and another indicator in *ValuePtrPtr, it requires data for another parameter or column, and SQLPutData is called again. If the driver returns SQL_SUCCESS, then all data-at-execution data has been sent, and the SQL statement can be executed or the SQLBulkOperations or SQLSetPos call can be processed.
For more information on how data-at-execution parameter data is passed at statement execution time, see “Passing Parameter Values” in SQLBindParameter and “Sending Long Data” in Chapter 9, “Executing Statements.” For more information on how data-at-execution column data is updated or added, see the section “Using SQLSetPos” in SQLSetPos, “Performing Bulk Updates Using Bookmarks” in SQLBulkOperations, and “Long Data and SQLSetPos and SQLBulkOperations” in Chapter 12, “Updating Data.”
Note An application can use SQLPutData to send data in parts only when sending character C data to a column with a character, binary, or data source – specific data type or when sending binary C data to a column with a character, binary, or data source – specific data type. If SQLPutData is called more than once under any other conditions, it returns SQL_ERROR and SQLSTATE HY019 (Non-character and non-binary data sent in pieces).
Code Example
In the following example, an application prepares an SQL statement to insert data into the PICTURES table. The statement contains parameters for the PARTID and PICTURE columns. For each parameter, the application calls SQLBindParameter to specify the C and SQL data types of the parameter. It also specifies that the data for the second parameter will be passed at execution time, and passes the value 2 for later retrieval by SQLParamData. This value will identify the parameter that is being processed.
The application calls GetNextID to get the next available part ID number. It then calls SQLExecute to execute the statement. SQLExecute returns SQL_NEED_DATA when it needs data for the second parameter. The application calls SQLParamData to retrieve the value it stored with SQLBindParameter; it uses this value to determine which parameter to send data for. For each parameter, the application calls InitUserData to initialize the data routine. It repeatedly calls GetUserData and SQLPutData to get and send the parameter data. Finally, it calls SQLParamData to indicate it has sent all the data for the parameter, at which point it returns SQL_SUCCESS.
For the second parameter, InitUserData calls a routine to prompt the user for the name of a file containing a bitmap photo of the part and opens the file. GetUserData retrieves the next MAX_DATA_LEN bytes of photo data from the file. After it has retrieved all the photo data, it closes the photo file.
Note that some application routines are omitted for clarity.
#define MAX_DATA_LEN 1024
SQLINTEGER cbPartID = 0, cbPhotoParam, cbData;
SQLUINTEGER sPartID;
szPhotoFile;
SQLPOINTER pToken, InitValue;
SQLCHAR Data[MAX_DATA_LEN];
SQLRETURN retcode;
SQLHSTMT hstmt;
retcode = SQLPrepare(hstmt,
"INSERT INTO PICTURES (PARTID, PICTURE) VALUES
(?, ?)", SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
/* Bind the parameters. For parameter 2, pass */
/* the parameter number in ParameterValuePtr instead of a buffer */
/* address. */
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG,
SQL_INTEGER, 0, 0, &sPartID, 0, &cbPartID);
SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT,
SQL_C_BINARY, SQL_LONGVARBINARY,
0, 0, (SQLPOINTER) 2, 0, &cbPhotoParam);
/* Set values so data for parameter 2 will be */
/* passed at execution. Note that the length parameter in */
/* the macro SQL_LEN_DATA_AT_EXEC is 0. This assumes that */
/* the driver returns "N" for the SQL_NEED_LONG_DATA_LEN */
/* information type in SQLGetInfo. */
cbPhotoParam = SQL_LEN_DATA_AT_EXEC(0);
sPartID = GetNextID(); /* Get next available employee ID */
/* number. */
retcode = SQLExecute(hstmt);
/* For data-at-execution parameters, call SQLParamData to */
/* get the parameter number set by SQLBindParameter. */
/* Call InitUserData. Call GetUserData and SQLPutData */
/* repeatedly to get and put all data for the parameter. */
/* Call SQLParamData to finish processing this parameter */
while (retcode == SQL_NEED_DATA) {
retcode = SQLParamData(hstmt, &pToken);
if (retcode == SQL_NEED_DATA) {
InitUserData((SQLSMALLINT)pToken, InitValue);
while (GetUserData(InitValue, (SQLSMALLINT)pToken, Data,
&cbData))
SQLPutData(hstmt, Data, cbData);
}
}
}
VOID InitUserData(sParam, InitValue)
SQLPOINTER InitValue;
{
SQLCHAR szPhotoFile[MAX_FILE_NAME_LEN];
/* Prompt user for bitmap file containing employee */
/* photo. OpenPhotoFile opens the file and returns the */
/* file handle. */
PromptPhotoFileName(szPhotoFile);
OpenPhotoFile(szPhotoFile, (FILE *)InitValue);
break;
}
BOOL GetUserData(InitValue, sParam, Data, cbData)
SQLPOINTER InitValue;
SQLCHAR *Data;
SQLINTEGER *cbData;
BOOL Done;
{
/* GetNextPhotoData returns the next piece of photo */
/* data and the number of bytes of data returned */
/* (up to MAX_DATA_LEN). */
Done = GetNextPhotoData((FILE *)InitValue, Data,
MAX_DATA_LEN, &cbData);
if (Done) {
ClosePhotoFile((FILE *)InitValue);
return (TRUE);
}
return (FALSE);
}
Related Functions
For information about | See |
Binding a buffer to a parameter | SQLBindParameter |
Canceling statement processing | SQLCancel |
Executing an SQL statement | SQLExecDirect |
Executing a prepared SQL statement | SQLExecute |
Returning the next parameter to send data for | SQLParamData |