---
description: "SQL to C: Numeric"
title: "SQL to C: Numeric | Microsoft Docs"
ms.custom: ""
ms.date: "01/19/2019"
ms.prod: sql
ms.prod_service: connectivity
ms.reviewer: ""
ms.technology: connectivity
ms.topic: reference
helpviewer_keywords:
- "data conversions from SQL to C types [ODBC], numeric"
- "numeric data type [ODBC], converting"
- "converting data from SQL to C types [ODBC], numeric"
ms.assetid: 76f8b5d5-4bd0-4dcb-a90a-698340e0d36e
author: David-Engel
ms.author: v-daenge
---
# SQL to C: Numeric
The identifiers for the numeric ODBC SQL data types are the following:
- SQL_DECIMAL
- SQL_BIGINT
- SQL_NUMERIC
- SQL_REAL
- SQL_TINYINT
- SQL_FLOAT
- SQL_SMALLINT
- SQL_DOUBLE SQL_INTEGER
The following table shows the ODBC C data types to which numeric SQL data may be converted. For an explanation of the columns and terms in the table, see [Converting Data from SQL to C Data Types](../../../odbc/reference/appendixes/converting-data-from-sql-to-c-data-types.md).
|C type identifier|Test|**TargetValuePtr*|**StrLen_or_IndPtr*|SQLSTATE|
|-----------------------|----------|------------------------|----------------------------|--------------|
|SQL_C_CHAR|Character byte length < *BufferLength*
Number of whole (as opposed to fractional) digits < *BufferLength*
Number of whole (as opposed to fractional) digits >= *BufferLength*|Data
Truncated data
Undefined|Length of data in bytes
Length of data in bytes
Undefined|n/a
01004
22003|
|SQL_C_WCHAR|Character length < *BufferLength*
Number of whole (as opposed to fractional) digits < *BufferLength*
Number of whole (as opposed to fractional) digits >= *BufferLength*|Data
Truncated data
Undefined|Length of data in characters
Length of data in characters
Undefined|n/a
01004
22003|
|SQL_C_STINYINT
SQL_C_UTINYINT
SQL_C_TINYINT
SQL_C_SBIGINT
SQL_C_UBIGINT
SQL_C_SSHORT
SQL_C_USHORT
SQL_C_SHORT
SQL_C_SLONG
SQL_C_ULONG
SQL_C_LONG
SQL_C_NUMERIC|Data converted without truncation[a]
Data converted with truncation of fractional digits[a]
Conversion of data would result in loss of whole (as opposed to fractional) digits[a]|Data
Truncated data
Undefined|Size of the C data type
Size of the C data type
Undefined|n/a
01S07
22003|
|SQL_C_FLOAT
SQL_C_DOUBLE|Data is within the range of the data type to which the number is being converted[a]
Data is outside the range of the data type to which the number is being converted[a]|Data
Undefined|Size of the C data type
Undefined|n/a
22003|
|SQL_C_BIT|Data is 0 or 1[a]
Data is greater than 0, less than 2, and not equal to 1[a]
Data is less than 0 or greater than or equal to 2[a]|Data
Truncated data
Undefined|1[b]
1[b]
Undefined|n/a
01S07
22003|
|SQL_C_BINARY|Byte length of data <= *BufferLength*
Byte length of data > *BufferLength*|Data
Undefined|Length of data
Undefined|n/a
22003|
|SQL_C_INTERVAL_MONTH[c] SQL_C_INTERVAL_YEAR[c] SQL_C_INTERVAL_DAY[c] SQL_C_INTERVAL_HOUR[c] SQL_C_INTERVAL_MINUTE[c] SQL_C_INTERVAL_SECOND[c]|Data not truncated
Fractional seconds portion truncated
Whole part of number truncated|Data
Truncated data
Undefined|Length of data in bytes
Length of data in bytes
Undefined|n/a
01S07
22015|
|SQL_C_INTERVAL_YEAR_TO_MONTH SQL_C_INTERVAL_DAY_TO_HOUR SQL_C_INTERVAL_DAY_TO_MINUTE SQL_C_INTERVAL_DAY_TO_SECOND SQL_C_INTERVAL_HOUR_TO_MINUTE SQL_C_INTERVAL_HOUR_TO_SECOND|Whole part of number truncated|Undefined|Undefined|22015|
[a] The value of *BufferLength* is ignored for this conversion. The driver assumes that the size of **TargetValuePtr* is the size of the C data type.
[b] This is the size of the corresponding C data type.
[c] This conversion is supported only for the exact numeric data types (SQL_DECIMAL, SQL_NUMERIC, SQL_TINYINT, SQL_SMALLINT, SQL_INTEGER, and SQL_BIGINT). It is not supported for the approximate numeric data types (SQL_REAL, SQL_FLOAT, or SQL_DOUBLE).
## SQL_C_NUMERIC and SQLSetDescField
The [SQLSetDescField Function](../../../odbc/reference/syntax/sqlsetdescfield-function.md) is required to perform manual binding with SQL_C_NUMERIC values. (Note that SQLSetDescField was added in ODBC 3.0.) To perform manual binding, you must first get the descriptor handle.
```cpp
if (fCType == SQL_C_NUMERIC) {
// special processing required for NUMERIC to get right scale & precision
// Modify the fields in the implicit application parameter descriptor
SQLHDESC hdesc=NULL;
// Use SQL_ATTR_APP_ROW_DESC for calls to SQLBindCol()
// Use SQL_ATTR_APP_PARAM_DESC for calls to SQLBindParameter()
//
// retcode = SQLGetStmtAttr(hstmt, SQL_ATTR_APP_ROW_DESC, &hdesc, 0, NULL);
retcode = SQLGetStmtAttr(hstmt, SQL_ATTR_APP_PARAM_DESC, &hdesc, 0, NULL);
if (!ODBC_CALL_SUCCESS(retcode)) {
printf ("\nSQLGetStmtAttr failed");
i = 1;
sqlstate[7] = '\0';
while (SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, sqlstate, &NativeError, wrkbuf, sizeof(wrkbuf), &len) != SQL_NO_DATA) {
printf("\niTestCase = %d Failed...Precision = %d, Scale = %d\nNativeError=%d, State=%s, \n Message=%s",
iTestCase, Precision, Scale, NativeError, sqlstate, wrkbuf);
i++;
}
continue;
}
retcode = SQLSetDescField(hdesc, iCol, SQL_DESC_TYPE, (SQLPOINTER) SQL_C_NUMERIC, 0);
if (!ODBC_CALL_SUCCESS(retcode))
goto error;
retcode = SQLSetDescField(hdesc, iCol, SQL_DESC_PRECISION, (SQLPOINTER)num.precision, 0);
if (!ODBC_CALL_SUCCESS(retcode))
goto error;
retcode = SQLSetDescField(hdesc, iCol, SQL_DESC_SCALE, (SQLPOINTER)num.scale, 0);
if (!ODBC_CALL_SUCCESS(retcode))
goto error;
retcode = SQLSetDescField(hdesc, iCol, SQL_DESC_DATA_PTR, (SQLPOINTER) &(num), sizeof(num));
```