网易首页 > 网易号 > 正文 申请入驻

ODBC开放数据库互连

0
分享至

ODBC

ODBC(Open Database Connectivity,开放数据库互连)是由Microsoft公司基于X/OPEN CLI提出的用于访问数据库的应用程序编程接口。应用程序通过ODBC提供的API与数据库进行交互,增强了应用程序的可移植性、扩展性和可维护性。

ODBC的系统结构参见图1。

图 1ODBC系统机构



openGauss目前在以下环境中提供对ODBC的支持。

表 1ODBC支持平台

操作系统

平台

CentOS 6.4/6.5/6.6/6.7/6.8/6.9/7.0/7.1/7.2/7.3/7.4

x86_64位

CentOS 7.6

ARM64位

EulerOS 2.0 SP2/SP3

x86_64位

EulerOS 2.0 SP8

ARM64位

windows7/8/10

x86_32位

Windows系统自带ODBC驱动程序管理器,在控制面板->管理工具中可以找到数据源(ODBC)选项,可以参考odbc文档。

Linux下的ODBC包

从发布包中获取,包名为openGauss-*.*.0-ODBC.tar.gz。Linux环境下,开发应用程序要用到unixODBC提供的头文件(sql.h、sqlext.h等)和库libodbc.so。这些头文件和库可从unixODBC-2.3.0的安装包中获得。

配置数据源

将openGauss提供的ODBC DRIVER(psqlodbcw.so)配置到数据源中便可使用。配置数据源需要配置“odbc.ini”和“odbcinst.ini”两个文件(在编译安装unixODBC过程中生成且默认放在“/usr/local/etc”目录下),并在服务器端进行配置。

  1. 获取unixODBC-2.3.9源码包。
  2. 获取参考地址:http://www.unixodbc.org/download.html
  3. 安装unixODBC。如果机器上已经安装了其他版本的unixODBC,可以直接覆盖安装。
  4. 目前不支持unixODBC-2.2.1版本。以unixODBC-2.3.0版本为例,在客户端执行如下命令安装unixODBC。默认安装到“/usr/local”目录下,生成数据源文件到 “/usr/local/etc”目录下,库文件生成在“/usr/local/lib”目录。
  5. tar zxvf unixODBC-2.3.9.tar.gzcd unixODBC-2.3.9#修改configure文件(如果不存在,那么请修改configure.ac),找到LIB_VERSION#将它的值修改为"1:0:0",这样将编译出*.so.1的动态库,与psqlodbcw.so的依赖关系相同。vim configure./configure --enable-gui=no #如果要在ARM服务器上编译,请追加一个configure参数: --build=aarch64-unknown-linux-gnu make#安装可能需要root权限make install
  6. 替换客户端openGauss驱动程序。
    1. 将openGauss-x.x.x-ODBC.tar.gz解压到“/usr/local/lib”目录下。解压会得到“psqlodbcw.la”和“psqlodbcw.so”两个文件。
    2. 将openGauss-x.x.x-ODBC.tar.gz解压后lib目录中的库拷贝到“/usr/local/lib”目录下。
  7. 配置数据源。
  8. 配置ODBC驱动文件。
  9. 在“/xxx/odbc/etc/odbcinst.ini”文件中追加以下内容。
  10. [GaussMPP]Driver64=/xxx/odbc/lib/psqlodbcw.sosetup=/xxx/odbc/lib/psqlodbcw.so
  11. odbcinst.ini文件中的配置参数说明如表2所示。
  12. 表 2odbcinst.ini文件配置参数
  13. 参数
  14. 描述
  15. 示例
  16. [DriverName]
  17. 驱动器名称,对应数据源DSN中的驱动名。
  18. [DRIVER_N]
  19. Driver64
  20. 驱动动态库的路径。
  21. Driver64=/xxx/odbc/lib/psqlodbcw.so
  22. setup
  23. 驱动安装路径,与Driver64中动态库的路径一致。
  24. setup=/xxx/odbc/lib/psqlodbcw.so
  25. 配置数据源文件。
  26. 在“/usr/local/etc/odbc.ini”文件中追加以下内容。
  27. [MPPODBC]Driver=GaussMPPServername=10.145.130.26(数据库Server IP)Database=postgres (数据库名)Username=omm (数据库用户名)Password= (数据库用户密码)Port=8000 (数据库侦听端口)Sslmode=allow
  28. odbc.ini文件配置参数说明如表3所示。
  29. 表 3odbc.ini文件配置参数
  30. 参数
  31. 描述
  32. 示例
  33. [DSN]
  34. 数据源的名称。
  35. [MPPODBC]
  36. Driver
  37. 驱动名,对应odbcinst.ini中的DriverName。
  38. Driver=DRIVER_N
  39. Servername
  40. 服务器的IP地址。
  41. Servername=10.145.130.26
  42. Database
  43. 要连接的数据库的名称。
  44. Database=postgres
  45. Username
  46. 数据库用户名称。
  47. Username=omm
  48. Password
  49. 数据库用户密码。
  50. Password=
  51. ODBC驱动本身已经对内存密码进行过清理,以保证用户密码在连接后不会再在内存中保留。
  52. 但是如果配置了此参数,由于UnixODBC对数据源文件等进行缓存,可能导致密码长期保留在内存中。
  53. 推荐在应用程序连接时,将密码传递给相应API,而非写在数据源配置文件中。同时连接成功后,应当及时清理保存密码的内存段。
  54. Port
  55. 服务器的端口号。
  56. Port=8000
  57. Sslmode
  58. 开启SSL模式
  59. Sslmode=allow
  60. Debug
  61. 设置为1时,将会打印psqlodbc驱动的mylog,日志生成目录为/tmp/。设置为0时则不会生成。
  62. Debug=1
  63. UseServerSidePrepare
  64. 是否开启数据库端扩展查询协议。
  65. 可选值0或1,默认为1,表示打开扩展查询协议。
  66. UseServerSidePrepare=1
  67. UseBatchProtocol
  68. 是否开启批量查询协议(打开可提高DML性能);可选值0或者1,默认为1。
  69. 当此值为0时,不使用批量查询协议(主要用于与早期数据库版本通信兼容)。
  70. 当此值为1,并且数据库support_batch_bind参数存在且为on时,将打开批量查询协议。
  71. UseBatchProtocol=1
  72. ForExtensionConnector
  73. 这个开关控制着savepoint是否发送,savepoint相关问题可以注意这个开关。
  74. ForExtensionConnector=1
  75. UnamedPrepStmtThreshold
  76. 每次调用SQLFreeHandle释放Stmt时,ODBC都会向server端发送一个Deallocate plan_name语句,业务中存在大量这类语句。为了减少这类语句的发送,我们将 stmt->plan_name置空,从而使得数据库识别这个为unamed stmt。增加这个参数对unamed stmt的阈值进行控制。
  77. UnamedPrepStmtThreshold=100
  78. ConnectionExtraInfo
  79. GUC参数connection_info中显示驱动部署路径和进程属主用户的开关。
  80. ConnectionExtraInfo=1
  81. 默认值为0。当设置为1时,ODBC驱动会将当前驱动的部署路径、进程属主用户上报到数据库中,记录在connection_info参数里;同时可以在PG_STAT_ACTIVITY中查询到。
  82. BoolAsChar
  83. 设置为Yes是,Bools值将会映射为SQL_CHAR。如不设置将会映射为SQL_BIT。
  84. BoolsAsChar = Yes
  85. RowVersioning
  86. 当尝试更新一行数据时,设置为Yes会允许应用检测数据有没有被其他用户进行修改。
  87. RowVersioning=Yes
  88. ShowSystemTables
  89. 驱动将会默认系统表格为普通SQL表格。
  90. ShowSystemTables=Yes
  91. 其中关于Sslmode的选项的允许值,具体信息见下表:
  92. 表 4Sslmode的可选项及其描述
  93. Sslmode
  94. 是否会启用SSL加密
  95. 描述
  96. disable
  97. 不使用SSL安全连接。
  98. allow
  99. 可能
  100. 如果数据库服务器要求使用,则可以使用SSL安全加密连接,但不验证数据库服务器的真实性。
  101. prefer
  102. 可能
  103. 如果数据库支持,那么建议使用SSL安全加密连接,但不验证数据库服务器的真实性。
  104. require
  105. 必须使用SSL安全连接,但是只做了数据加密,而并不验证数据库服务器的真实性。
  106. verify-ca
  107. 必须使用SSL安全连接,并且验证数据库是否具有可信证书机构签发的证书。
  108. verify-full
  109. 必须使用SSL安全连接,在verify-ca的验证范围之外,同时验证数据库所在主机的主机名是否与证书内容一致。openGauss不支持此模式。
说明:SSL模式: 保证client.key*系列文件为600权限: 退回根目录,创建.postgresql目录,并将root.crt,client.crt,client.key,client.key.cipher,client.key.rand,client.req,server.crt,server.key,server.key.cipher,server.key.rand,server.req放在此路径下。 Unix系统下,server.crt、server.key的权限设置必须禁止任何外部或组的访问,请执行如下命令实现这一点。

chmod 0600 server.key
将root.crt以及server开头的证书相关文件全部拷贝进数据库install/data目录下(与postgresql.conf文件在同一路径)。 修改postgresql.conf文件:
ssl = onssl_cert_file = 'server.crt'ssl_key_file = 'server.key'ssl_ca_file = 'root.crt'
修改完参数后需重启数据库。 修改配置文件odbc.ini中的sslmode参数(require或verify-ca)。
  1. 配置数据库服务器。
  2. 以操作系统用户omm登录数据库主节点。
  3. 执行如下命令增加对外提供服务的网卡IP或者主机名(英文逗号分隔),其中NodeName为当前节点名称:
  4. gs_guc reload -N NodeName -I all -c "listen_addresses='localhost,192.168.0.100,10.11.12.13'"
  5. 在DR(Direct Routing,LVS的直接路由DR模式)模式中需要将虚拟IP地址(10.11.12.13)加入到服务器的侦听地址列表中。
  6. listen_addresses也可以配置为“*”或“0.0.0.0”,此配置下将侦听所有网卡,但存在安全风险,不推荐用户使用,推荐用户按照需要配置IP或者主机名,打开侦听。
  7. 执行如下命令在数据库主节点配置文件中增加一条认证规则。(这里假设客户端IP地址为10.11.12.13,即远程连接的机器的IP地址)
  8. gs_guc reload -N all -I all -h "host all jack 10.11.12.13/32 sha256"

  • -N all表示openGauss中的所有主机。
  • -I all表示主机中的所有实例。
  • -h表示指定需要在“pg_hba.conf”增加的语句。
  • all表示允许客户端连接到任意的数据库。
  • jack表示连接数据库的用户。
  • 10.11.12.13/_32_表示只允许IP地址为10.11.12.13的主机连接。在使用过程中,请根据用户的网络进行配置修改。32表示子网掩码为1的位数,即255.255.255.255。
  • sha256表示连接时jack用户的密码使用sha256算法加密。
  1. 如果将ODBC客户端配置在和要连接的数据库主节点在同一台机器上,则可使用local trust认证方式,如下:
  2. local all all trust
  3. 如果将ODBC客户端配置在和要连接的数据库主节点在不同机器上,则需要使用sha256认证方式,如下:
  4. host all all xxx.xxx.xxx.xxx/32 sha256
  5. 重启openGauss。
  6. gs_om -t stopgs_om -t start
  7. 在客户端配置环境变量。
  8. vim ~/.bashrc
  9. 在配置文件中追加以下内容。
  10. export LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATHexport ODBCSYSINI=/usr/local/etcexport ODBCINI=/usr/local/etc/odbc.ini
  11. 执行如下命令使设置生效。
  12. source ~/.bashrc

测试数据源配置

执行./isql -v MPPODBC(数据源名称)命令。

  • 如果显示如下信息,表明配置正确,连接成功。
  • +---------------------------------------+| Connected! || || sql-statement || help [tablename] || quit || |+---------------------------------------+SQL>
  • 若显示ERROR信息,则表明配置错误。请检查上述配置是否正确。

开发流程

图 2ODBC开发应用程序的流程



常用接口

表 5相关API说明

功能

API

申请句柄资源

SQLAllocHandle:申请句柄资源,可替代如下函数:

  • SQLAllocEnv:申请环境句柄
  • SQLAllocConnect:申请连接句柄
  • SQLAllocStmt:申请语句句柄

设置环境属性

SQLSetEnvAttr

设置连接属性

SQLSetConnectAttr

设置语句属性

SQLSetStmtAttr

连接数据源

SQLConnect

绑定缓冲区到结果集的列中

SQLBindCol

绑定SQL语句的参数标志和缓冲区

SQLBindParameter

查看最近一次操作错误信息

SQLGetDiagRec

为执行SQL语句做准备

SQLPrepare

执行一条准备好的SQL语句

SQLExecute

直接执行SQL语句

SQLExecDirect

结果集中取行集

SQLFetch

返回结果集中某一列的数据

SQLGetData

获取结果集中列的描述信息

SQLColAttribute

断开与数据源的连接

SQLDisconnect

释放句柄资源

SQLFreeHandle:释放句柄资源,可替代如下函数:

  • SQLFreeEnv:释放环境句柄
  • SQLFreeConnect:释放连接句柄
  • SQLFreeStmt:释放语句句柄
说明:数据库中收到的一次执行请求(不在事务块中),如果含有多条语句,将会被打包成一个事务,同时如果其中有一个语句失败,那么整个请求都将会被回滚。

连接数据库

#include #include #include #ifdef WIN32#include #endif SQLHENV V_OD_Env; // Handle ODBC environmentSQLHDBC V_OD_hdbc; // Handle connection SQLINTEGER V_OD_erg;int main(int argc,char *argv[]) { // 1. 申请环境句柄 V_OD_erg = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&V_OD_Env); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error AllocHandle\n"); exit(0); } // 2. 设置环境属性(版本信息) SQLSetEnvAttr(V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); // 3. 申请连接句柄 V_OD_erg = SQLAllocHandle(SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } // 4. 设置连接属性 SQLSetConnectAttr(V_OD_hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_ON, 0); // 5. 连接数据源,这里的“userName”与“password”分别表示连接数据库的用户名和用户密码,请根据实际情况修改。 // 如果odbc.ini文件中已经配置了用户名密码,那么这里可以留空("");但是不建议这么做,因为一旦odbc.ini权限管理不善,将导致数据库用户密码泄露。 V_OD_erg = SQLConnect(V_OD_hdbc, (SQLCHAR*) "gaussdb", SQL_NTS, (SQLCHAR*) "userName", SQL_NTS, (SQLCHAR*) "password", SQL_NTS); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error SQLConnect %d\n",V_OD_erg); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } printf("Connected !\n"); // 6. 断开数据源连接并释放句柄资源 SQLDisconnect(V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); return(0);}

创建表

#include #include #include #ifdef WIN32#include #endif SQLHENV V_OD_Env; // Handle ODBC environment SQLHSTMT V_OD_hstmt; // Handle statement SQLHDBC V_OD_hdbc; // Handle connection SQLINTEGER V_OD_erg;int main(int argc,char *argv[]) { V_OD_erg = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&V_OD_Env); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error AllocHandle\n"); exit(0); } SQLSetEnvAttr(V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); V_OD_erg = SQLAllocHandle(SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } SQLSetConnectAttr(V_OD_hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_ON, 0); V_OD_erg = SQLConnect(V_OD_hdbc, (SQLCHAR*) "gaussdb", SQL_NTS, (SQLCHAR*) "userName", SQL_NTS, (SQLCHAR*) "password", SQL_NTS); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error SQLConnect %d\n",V_OD_erg); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } printf("Connected !\n"); // 1. 设置语句属性 SQLSetStmtAttr(V_OD_hstmt,SQL_ATTR_QUERY_TIMEOUT,(SQLPOINTER *)3,0); // 2. 申请语句句柄 SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt); // 3. 创建表格。 SQLExecDirect(V_OD_hstmt,"drop table IF EXISTS customer_t1",SQL_NTS); SQLExecDirect(V_OD_hstmt,"CREATE TABLE customer_t1(c_customer_sk INTEGER, c_customer_name VARCHAR(32));",SQL_NTS); printf("Done !\n"); // 4. 断开数据源连接并释放句柄资源 SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt); SQLDisconnect(V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); return(0); }

插入操作

#include #include #include #ifdef WIN32#include #endif SQLHENV V_OD_Env; // Handle ODBC environment SQLHSTMT V_OD_hstmt; // Handle statement SQLHDBC V_OD_hdbc; // Handle connection SQLINTEGER value = 100;SQLINTEGER V_OD_erg;int main(int argc,char *argv[]) { V_OD_erg = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&V_OD_Env); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error AllocHandle\n"); exit(0); } SQLSetEnvAttr(V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); V_OD_erg = SQLAllocHandle(SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } SQLSetConnectAttr(V_OD_hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_ON, 0); V_OD_erg = SQLConnect(V_OD_hdbc, (SQLCHAR*) "gaussdb", SQL_NTS, (SQLCHAR*) "userName", SQL_NTS, (SQLCHAR*) "password", SQL_NTS); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error SQLConnect %d\n",V_OD_erg); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } printf("Connected !\n"); SQLSetStmtAttr(V_OD_hstmt,SQL_ATTR_QUERY_TIMEOUT,(SQLPOINTER *)3,0); SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt); // 1. 直接插入 SQLExecDirect(V_OD_hstmt,"insert into customer_t1 values(25,li)",SQL_NTS); // 2. pbe方法插入 // 2.1 插入占位符 SQLPrepare(V_OD_hstmt,"insert into customer_t1 values(?)",SQL_NTS); // 2.2 绑定参数 SQLBindParameter(V_OD_hstmt,1,SQL_PARAM_INPUT,SQL_C_SLONG,SQL_INTEGER,0,0, &value,0,NULL); // 2.3 执行准备好的插入语句 SQLExecute(V_OD_hstmt); // 3. 断开数据源连接并释放句柄资源 SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt); SQLDisconnect(V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); return(0); }

SELECT操作

#include #include #include #ifdef WIN32#include #endif SQLHENV V_OD_Env; // Handle ODBC environment SQLHSTMT V_OD_hstmt; // Handle statement SQLHDBC V_OD_hdbc; // Handle connection char typename[100];SQLINTEGER V_OD_erg, V_OD_buffer, V_OD_err, V_OD_id;int main(int argc,char *argv[]) { V_OD_erg = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&V_OD_Env); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error AllocHandle\n"); exit(0); } SQLSetEnvAttr(V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); V_OD_erg = SQLAllocHandle(SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } SQLSetConnectAttr(V_OD_hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_ON, 0); V_OD_erg = SQLConnect(V_OD_hdbc, (SQLCHAR*) "gaussdb", SQL_NTS, (SQLCHAR*) "userName", SQL_NTS, (SQLCHAR*) "password", SQL_NTS); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error SQLConnect %d\n",V_OD_erg); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } printf("Connected !\n"); SQLSetStmtAttr(V_OD_hstmt,SQL_ATTR_QUERY_TIMEOUT,(SQLPOINTER *)3,0); SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt); // 1. 执行select语句 SQLExecDirect(V_OD_hstmt,"select c_customer_sk from customer_t1",SQL_NTS); // 2. 获取结果集某一列的属性 SQLColAttribute(V_OD_hstmt,1,SQL_DESC_TYPE,typename,100,NULL,NULL); printf("SQLColAtrribute %s\n",typename); // 3. 绑定结果集 SQLBindCol(V_OD_hstmt,1,SQL_C_SLONG, (SQLPOINTER)&V_OD_buffer,150, (SQLLEN *)&V_OD_err); // 4. 通过SQLFetch取结果集中数据 V_OD_erg=SQLFetch(V_OD_hstmt); // 5. 通过SQLGetData获取并返回数据。 while(V_OD_erg != SQL_NO_DATA) { SQLGetData(V_OD_hstmt,1,SQL_C_SLONG,(SQLPOINTER)&V_OD_id,0,NULL); printf("SQLGetData ----ID = %d\n",V_OD_id); V_OD_erg=SQLFetch(V_OD_hstmt); }; printf("Done !\n"); // 6. 断开数据源连接并释放句柄资源 SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt); SQLDisconnect(V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); return(0); }

更新操作

#include #include #include #ifdef WIN32#include #endif SQLHENV V_OD_Env; // Handle ODBC environment SQLHSTMT V_OD_hstmt; // Handle statement SQLHDBC V_OD_hdbc; // Handle connection SQLINTEGER V_OD_erg;int main(int argc,char *argv[]) { V_OD_erg = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&V_OD_Env); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error AllocHandle\n"); exit(0); } SQLSetEnvAttr(V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); V_OD_erg = SQLAllocHandle(SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } SQLSetConnectAttr(V_OD_hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_ON, 0); V_OD_erg = SQLConnect(V_OD_hdbc, (SQLCHAR*) "gaussdb", SQL_NTS, (SQLCHAR*) "userName", SQL_NTS, (SQLCHAR*) "password", SQL_NTS); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error SQLConnect %d\n",V_OD_erg); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } printf("Connected !\n"); SQLSetStmtAttr(V_OD_hstmt,SQL_ATTR_QUERY_TIMEOUT,(SQLPOINTER *)3,0); SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt); // 1. 执行更新操作 SQLExecDirect(V_OD_hstmt,"update customer_t1 set c_customer_sk = 1000 where c_customer_name = 'li' ",SQL_NTS); // 16. 断开数据源连接并释放句柄资源 SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt); SQLDisconnect(V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); return(0); }

删除操作

#include #include #include #ifdef WIN32#include #endif SQLHENV V_OD_Env; // Handle ODBC environment SQLHSTMT V_OD_hstmt; // Handle statement SQLHDBC V_OD_hdbc; // Handle connection SQLINTEGER V_OD_erg;int main(int argc,char *argv[]) { V_OD_erg = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&V_OD_Env); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error AllocHandle\n"); exit(0); } SQLSetEnvAttr(V_OD_Env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); V_OD_erg = SQLAllocHandle(SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } SQLSetConnectAttr(V_OD_hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_ON, 0); V_OD_erg = SQLConnect(V_OD_hdbc, (SQLCHAR*) "gaussdb", SQL_NTS, (SQLCHAR*) "userName", SQL_NTS, (SQLCHAR*) "password", SQL_NTS); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO)) { printf("Error SQLConnect %d\n",V_OD_erg); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } printf("Connected !\n"); SQLSetStmtAttr(V_OD_hstmt,SQL_ATTR_QUERY_TIMEOUT,(SQLPOINTER *)3,0); SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt); // 1. 执行删除操作 SQLExecDirect(V_OD_hstmt,"delete from customer_t1 where c_customer_name = 'li'",SQL_NTS); // 2. 断开数据源连接并释放句柄资源 SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt); SQLDisconnect(V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); return(0); }

声明:个人原创,仅供参考

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
全球近140万粉丝追随,她在世界各地拍下裸照,却没有一张是色情的!

全球近140万粉丝追随,她在世界各地拍下裸照,却没有一张是色情的!

国际艺术大观
2024-07-01 00:07:03
林葳被郭士强封杀细节!如果是杜锋,估计会更狠吧?

林葳被郭士强封杀细节!如果是杜锋,估计会更狠吧?

体坛狗哥
2024-06-30 11:47:18
陈思诚和24岁女友匈牙利旅游,入住2k一晚酒店,女友晒照好漂亮!

陈思诚和24岁女友匈牙利旅游,入住2k一晚酒店,女友晒照好漂亮!

古希腊掌管月桂的神
2024-06-30 11:31:34
进球功臣全部换下!凯恩、贝林厄姆加时赛下半场被换下,孔萨登场

进球功臣全部换下!凯恩、贝林厄姆加时赛下半场被换下,孔萨登场

直播吧
2024-07-01 02:30:21
普华永道,“大败局”

普华永道,“大败局”

中国基金报
2024-06-30 12:58:43
笑死,终于知道为什么韩国生育率低了,韩疑似七月起取消生孩麻醉

笑死,终于知道为什么韩国生育率低了,韩疑似七月起取消生孩麻醉

奇特短尾矮袋鼠
2024-06-30 22:59:31
太恶心了!到底是谁在教小孩这些东西,这些才应该下架!

太恶心了!到底是谁在教小孩这些东西,这些才应该下架!

奇特短尾矮袋鼠
2024-06-28 17:01:53
霍思燕代孕女儿近照曝光!8岁女儿颜值逆天,身穿裙子戴近视眼镜

霍思燕代孕女儿近照曝光!8岁女儿颜值逆天,身穿裙子戴近视眼镜

八卦王者
2024-06-29 16:30:58
深中通道通车,30分钟深圳到中山,专家:中山住宅短期大涨可能性不大,应更关注经济机会

深中通道通车,30分钟深圳到中山,专家:中山住宅短期大涨可能性不大,应更关注经济机会

华夏时报
2024-07-01 00:02:13
再读鲁迅的《祝福》:为什么专制社会中的底层民众总是互相伤害?

再读鲁迅的《祝福》:为什么专制社会中的底层民众总是互相伤害?

颜威说历史官方号
2024-06-29 14:57:11
胡友平为救日本籍母子被刺伤身亡,事发公交站安保措施大大加强

胡友平为救日本籍母子被刺伤身亡,事发公交站安保措施大大加强

西虹市闲话
2024-06-30 10:14:44
徐江谈申花外援:要是争冠还是换马莱莱吧,路易斯也状态下坡

徐江谈申花外援:要是争冠还是换马莱莱吧,路易斯也状态下坡

直播吧
2024-06-30 22:25:13
峰回路转!公牛竟然用一份5年9000万大额合同签回了昔日四号秀?

峰回路转!公牛竟然用一份5年9000万大额合同签回了昔日四号秀?

稻谷与小麦
2024-06-30 22:05:30
某网友建议:如果爆发战争,每人捐少则1万元,多则5万,筹集军费

某网友建议:如果爆发战争,每人捐少则1万元,多则5万,筹集军费

十三级台阶
2024-06-30 19:39:29
深圳一海滩三人游泳,不幸被海浪卷走造成悲剧,一死一活一失踪

深圳一海滩三人游泳,不幸被海浪卷走造成悲剧,一死一活一失踪

辉哥说动漫
2024-07-01 00:33:41
激动过度!武磊上演帽子戏法:穆斯卡特场边庆祝时突然抽筋!

激动过度!武磊上演帽子戏法:穆斯卡特场边庆祝时突然抽筋!

中超球评
2024-06-30 18:00:37
杨幂被偷拍私处,照片一夜传遍全网,网友炸了:不要低估人性的恶…

杨幂被偷拍私处,照片一夜传遍全网,网友炸了:不要低估人性的恶…

二胡的岁月如歌
2024-06-30 18:10:18
广西明晚到后天降雨将进入最强阶段

广西明晚到后天降雨将进入最强阶段

界面新闻
2024-06-30 21:15:47
三甲专家下班直播唱歌火了,本人发声

三甲专家下班直播唱歌火了,本人发声

环球时报新闻
2024-06-30 11:34:40
他官至副国级,受审时放狠话:谁敢判我死刑!入狱后不久患癌病逝

他官至副国级,受审时放狠话:谁敢判我死刑!入狱后不久患癌病逝

诗意世界
2024-03-20 10:15:03
2024-07-01 08:08:49
倾城豆腐
倾城豆腐
倾城豆腐
85文章数 0关注度
往期回顾 全部

科技要闻

河南火箭坠落爆炸?商业航天公司回应了

头条要闻

俄空天军屡遭乌无人机袭击 美媒担心中国未来也用这招

头条要闻

俄空天军屡遭乌无人机袭击 美媒担心中国未来也用这招

体育要闻

欧洲杯8强已定4席:英格兰战瑞士 西德PK

娱乐要闻

白玉兰明星反应精彩 胡歌获奖唐嫣激动

财经要闻

副行长坠楼 西安银行业绩到底怎么样?

汽车要闻

小鹏MONA M03 7月3日首发 15万紧凑级

态度原创

房产
家居
艺术
健康
手机

房产要闻

20亿!又有国企要卖海南资产!

家居要闻

美式风格 呈现田园风格

艺术要闻

穿越时空的艺术:《马可·波罗》AI沉浸影片探索人类文明

人类为何至今无法攻克渐冻症?

手机要闻

三大升级点被确认!三星S25 Ultra:能否回归机皇定位?

无障碍浏览 进入关怀版