ODBC Introduction and API Usage

ODBC Introduction and API Usage

提示:这里可以添加本文要记录的大概内容:

For example: With the continuous development of artificial intelligence, the technology of machine learning is becoming more and more important. Many people have started to learn machine learning. This article introduces the basic content of machine learning.


提示:以下是本篇文章正文内容,下面案例可供参考

1. Overview of ODBC

Open Database Connectivity (ODBC) is a widely accepted application programming interface (API) for database access that uses Structured Query Language (SQL) as its database access language. ODBC can be used to connect to many common databases, among which, it is mainly used for SQL Server.

2. Basic knowledge and official website

This part mainly includes: 句柄, 缓冲区, ODBC中的数据类型, 一致性级别.

2.1 handle

句柄Is an opaque 32-bit value that identifies a specific item; in ODBC, an item can be an environment, connection, statement, or descriptor. The application calls SQLAllocHandle to apply for related types of handles.

Environment handle: The environment is a global context for accessing data; associated with the environment is information of a global nature, such as: the state of the environment, diagnostic information at the current environment level, the connection handle allocated in the current environment, and the current properties set by each environment .

Connection handle: A connection handle identifies each connection. A connection handle defines not only which driver to use, but also the data source to use with that driver. Contains information about the state of the connection, current connection-level diagnostics, handles to statements and descriptors currently allocated on the connection, and current settings for each connection attribute. When connecting to a data source, primarily use the connection handle (SQLConnect, SQLDriverConnect, or SQLBrowseConnect), disconnect from the data source (SQLDisconnect), obtain information about the driver and data source (SQLGetInfo), retrieve diagnostics (SQLGetDiagField and SQLGetDiagRec), and (SQLEndTran) Executes the transaction. They are also used when setting and getting connection attributes (SQLSetConnectAttr and SQLGetConnectAttr), and when getting SQL statements in their native format (SQLNativeSql).

Statement handle: Statements are most easily viewed as SQL statements, such as SELECT * FROM Employee. However, a statement is not just an SQL statement, it contains all the information associated with the SQL statement, such as the result set created by the statement and the parameters used in the execution of the statement. A statement doesn't even need to have an application-defined SQL statement. Each statement is identified by a statement handle. A statement is associated with a single connection, and there can be multiple statements on that connection. Some drivers limit the number of active statements they support; the SQL_MAX_CONCURRENT_ACTIVITIES option in SQLGetInfo specifies the number of active statements a driver supports on a single connection. A statement is defined as active if it has pending results, where the result is a result set or count of rows affected by an INSERT, UPDATE, or DELETE statement, or if data is sent through multiple calls to SQLPutData. Information included is: the state of the statement, current statement-level diagnostics, addresses of application variables bound to the statement's parameters and result set columns, and the current settings of each statement property. They are used in functions to bind parameters and result set columns (SQLBindParameter and SQLBindCol), prepare and execute sqlPrepare, SQLExecute and SQLExecDirect) (statements, (SQLColAttribute and SQLDescribeCol) retrieve metadata, (SQLFetch) fetch results, and (SQLGetDiagField and SQLGetDiagRec) to retrieve diagnostics. They are also used in catalog functions (SQLColumns, SQLTables, etc.) and many others.

Descriptor handle: A descriptor is 元数据a collection of parameters or result set columns that describe an SQL statement. Descriptors can fill any one of the following four roles:
(1) Application Parameter Descriptor (APD). Contains information about an application buffer bound to a parameter in an SQL statement, such as its address, length, and C data type.
(2) Implement parameter descriptor (IPD). Contains information about a parameter in an SQL statement, such as its SQL data type, length, and nullability.
(3) Application Row Descriptor (ARD). Contains information about the application buffer bound to a column in the result set, such as its address, length, and C data type.
(4) Implements IRD) (Row Descriptor. Contains information about the columns in the result set, such as their SQL data type, length, and nullability. When a statement is assigned, four descriptors are automatically assigned (one for each
role) . These descriptors are called automatically allocated descriptors and are always associated with the statement. An application can also allocate descriptors using SQLAllocHandle. These descriptors are called explicitly allocated descriptors. They are allocated on a connection and can be used with One or more statements on the connection are associated to fulfill the role of APD or ARD on those statements.
Most operations in ODBC can be performed without explicit use of descriptors by the application. However, descriptors are Provides a convenient shortcut. For example, suppose an application wants to insert data from two different sets of buffers. To use the first set of buffers, it will repeatedly call SQLBindParameter to bind them to the parameters in the INSERT statement, The statement is then executed. To use the second set of buffers, it will repeat the process. Alternatively, it can set bindings to the first set of buffers in one descriptor and the second set of buffers in another .To switch between binding sets, an application simply calls SQLSetStmtAttr and associates the correct descriptor with the statement as an APD.

2.2 Buffer

2.2.1 Concept

Buffers are all pieces of application memory used to pass data between the application and the driver.

The length of the data buffer and the data it contains is measured in bytes, not characters. This distinction is not important to programs that use ANSI strings, because bytes and characters are the same length.

Applications do this by setting the length parameter in any function call that sets the field or property to one of the following values.

  • If the function argument indicating the field or property value is a pointer to a string, the length argument is the length of the string or SQL_NTS.
  • If the function parameter indicating the field or attribute value is a pointer to a binary buffer, the application places the SQL_LEN_BINARY_ATTR (result of length) macro in the length parameter. This places a negative value in the length parameter.
  • If the function parameter indicating the field or property value is a pointer to a value other than a string or binary string, the value of the length parameter shall be SQL_IS_POINTER.
  • If the function parameter indicating a field or property value contains a fixed-length value, the length parameter is SQL_IS_INTEGER, SQL_IS_UINTEGER, SQL_IS_SMALLINT, or SQL_ISI_USMALLINT (as appropriate).

2.2.1 Delayed buffers

A delayed buffer is a buffer that is used at some point in a function call when a value is specified. For example, SQLBindParameter is used to associate or bind a data buffer with a parameter in an SQL statement. The application specifies the number of parameters and passes the buffer's address, byte length, and type. The driver saves this information, but does not check the contents of the buffer. Later, when the application executes the statement, the driver retrieves the information and uses it to retrieve parameter data and send it to the data source.

2.3 Data types in ODBC

ODBC uses two sets of data types: SQL 数据类型and C 数据类型. SQL data types are used in the data source and C data types are used in the C code in the application. There is also an ODBC-defined data type that we will not use in our program.

SQLCHAR:ODBC定义的数据类型
SOL_C_CHAR:C语言的数据类型编码
SQL_CHAR:SQL数据类型编码

2.3.1 Data types defined by ODBC

Such as SQLCHAR, beginning with SQL, followed by a series of uppercase characters, but no underscore. This data type is defined in sqltypes.h. This data type can be used to define variables, and the variable types of ODBC API are all of this type. The advantage of doing this is that ODBC provides a set of its own variable types, which is equivalent to encapsulating a layer, and users do not need to care about the implementation details of the underlying specific variable types. Even if the underlying variable type is modified, the user's code does not need to make any changes. The mapping between this data type and the C language data type is as follows:
insert image description here

2.3.2 C data types in ODBC

Such as SQL_C_CHAR, they are not real data types, but encodings for the data types defined by ODBC mentioned above, so they cannot be used to define variables. They can be used as parameters of ODBC API. This data type is defined in sqlext.h, for example:
insert image description here
the mapping between this data type and ODBC data type is as follows:
insert image description here

2.3.3 SQL data types in ODBC

Such as SQL_CHAR, the third is SQL data type encoding. Like the second type, they are not real data types, but provide the association between SQL data types and programming language data types. Because they are also digital codes, they cannot be used to define variables. They can be used as parameters of ODBC API. This data type is defined in sqlext.h. The mapping between this data type and the SQL data type is as follows:
insert image description here

2.4 Conformance Levels

To help applications discover driver and data source capabilities, two conformance aspects are provided: ODBC interface and SQL syntax. See the official website for details.

2.5 Frequently used links

ODBC official manual

3. ODBC API reference

For detailed API instructions, please refer to the official website manual. Here, only C language is used as an example to record the problems and solutions encountered during use in alphabetical order.

3.1 Commonly used interfaces may encounter problems and solutions (continuously adding and supplementing...)

3.1.1 SQLBindParameter & SQLPutData

Function: parameter binding.
Note: Any parameter input error may affect the binding result. Even if the binding is returned successfully, subsequent operations may be affected. Here, the binding of large fields is taken as an example, and precautions are explained in comments.
Errors:
(1) "driver out of bounds" error may be returned: the input C type parameter is wrong: SQL_C_.
(2) Return HY010 function sequence error: the sequence of API calls is wrong.

SQLCHAR     b[5000], *b = &b[0];  /* The blob to be sent */
int         i;                    /* Loop counter */
SQLINTEGER  len;                  /* Segment length */
RETCODE     rc = SQL_SUCCESS;     /* Return code */
SQLPOINTER  pToken = NULL;        /* Column indicator */
SQLHSTMT    hstmt;                /* Statement handle */

/*
** Fill the blob buffer with test data.
*/
for ( i = 0; i < 5000; i++ )
    b[i] = 'x ';
    
/*
** Bind the blob, indicating that the length will be provided at untime.
*/
SQLBindParameter(hstmt,   /* Statement handle */
    1,                    /* Column number,start from 1 */
    SQL_PARAM_INPUT,      /* This is an input parameter */
    SQL_C_CHAR,           /* Parameter is a string */
    SQL_LONGVARBINARY,    /* Destination type is long varchar */
    0,                    /* No length required */
    0,                    /* No precision required */
    (PTR)1,               /* Long parameter number 1, 此处可以传入一个地址,如:申请一个句柄lob_hstmt用于大字段的存放,后面将从该句柄取数据,则此处可填:&lob_hstmt */
    0,                    /* No max length required */
    &len );               /* Variable blob length,此处的len值需为一个不为0的数,若为0则后续取到的数据长度为0。此处使用的值可能为一个传入的参数,为确保该值不为0,可以使用:len = SQL_LEN_DATA_AT_EXEC( len );提前对值进行处理 */
    
/*
** This macro definition tells the ODBC when to expect the end of
** data for the blob.
*/
len = SQL_LEN_DATA_AT_EXEC( 5000 );  // 不确定长度可以不用这句

/*
** Execute the insert query.
*/
rc = SQLExecDirect( hstmt,
     "insert into longv values ( ? )", SQL_NTS );
     
/*
** Loop, sending the data in segments of 1000.
*/
while ( rc == SQL_NEED_DATA )
{
    
    
    /*
    ** Check for EOD marker.
    */
    rc = SQLParamData( hstmt, pToken );
    if ( rc == SQL_NEED_DATA )
    {
    
    
        /*
        ** If more data to send, send it.
        */
        if ( pToken == 1 )
        {
    
    
            SQLPutData( hstmt, blob, 1000 );
            blob += 1000;
        }
    }
}
rc = SQLParamData( hstmt, pToken );  // 使用SQLPutData()要注意API调用顺序:1.exec并返回NEED_DATA; 2.SQLParamData并返回NEED_DATA; 3.SQLPutData; 4.SQLParamData并返回SUCCESS; 5.提交。

Example reference link

3.1.2 SQLRowCount

Function: SQLRowCount returns the number of rows affected by an UPDATE, INSERT, or DELETE statement.
NOTE: May return an incorrect number of affected rows (eg a very large value). Before calling this function, use SQLSetStmtAttr to set the parameter attribute SQL_ATTR_PARAMSET_SIZE to get the correct number of affected rows.

4. Conceptual understanding (to be supplemented)

Guess you like

Origin blog.csdn.net/qq_39030233/article/details/130142837