[关闭]
@liyuj 2017-04-04T14:54:14.000000Z 字数 18012 阅读 1601

Apache-Ignite-1.9.0-中文开发手册

13.ODBC驱动

13.1.入门

13.1.1.摘要

Ignite包括一个ODBC驱动,可以通过标准SQL查询和原生ODBC API查询和修改存储于分布式缓存中的数据。
要了解ODBC的细节,可以参照ODBC开发者参考
Apache Ignite的ODBC驱动实现了ODBC API的3.0版。

13.1.2.集群配置

ODBC驱动在Windows中被视为一个动态库,在Linux中被视为一个共享对象,应用不会直接加载它。作为替代,必要时它会使用一个驱动加载器API来加载和卸载ODBC驱动。
Ignite的ODBC驱动在内部使用TCP协议来接入Ignite集群,这个连接在Ignite中是通过一个叫做OdbcProcessor的组件来处理的。当节点启动时,OdbcProcessor默认是不开启的,要开启这个处理器,需要在IgniteConfiguration中配置OdbcConfiguration
XML:

  1. <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
  2. ...
  3. <!-- Enabling ODBC. -->
  4. <property name="odbcConfiguration">
  5. <bean class="org.apache.ignite.configuration.OdbcConfiguration"/>
  6. </property>
  7. ...
  8. </bean>

Java:

  1. IgniteConfiguration cfg = new IgniteConfiguration();
  2. ...
  3. OdbcConfiguration odbcCfg = new OdbcConfiguration();
  4. cfg.setOdbcConfiguration(odbcCfg);
  5. ...

配置了OdbcProcessor之后,就会以默认的配置启动,部分列举如下:

可以通过如下方式修改参数:
XML:

  1. <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
  2. ...
  3. <!-- Enabling ODBC. -->
  4. <property name="odbcConfiguration">
  5. <bean class="org.apache.ignite.configuration.OdbcConfiguration">
  6. <property name="endpointAddress" value="127.0.0.1:12345..12346"/>
  7. <property name="maxOpenCursors" value="512"/>
  8. <property name="socketSendBufferSize" value="65536"/>
  9. <property name="socketReceiveBufferSize" value="131072"/>
  10. <property name="threadPoolSize" value="4"/>
  11. </bean>
  12. </property>
  13. ...
  14. </bean>

Java:

  1. IgniteConfiguration cfg = new IgniteConfiguration();
  2. ...
  3. OdbcConfiguration odbcCfg = new OdbcConfiguration();
  4. odbcCfg.setEndpointAddress("127.0.0.1:12345..12346");
  5. odbcCfg.setMaxOpenCursors(512);
  6. odbcCfg.setSocketSendBufferSize(65536);
  7. odbcCfg.setSocketReceiveBufferSize(131072);
  8. odbcCfg.setThreadPoolSize(4);
  9. cfg.setOdbcConfiguration(odbcCfg);
  10. ...

通过OdbcProcessor从ODBC驱动端建立的到集群的连接也是可以配置的,关于如何从驱动端修改连接的配置,可以看这里

13.1.3.线程安全

Ignite ODBC驱动的当前实现仅仅在连接层提供了线程的安全,这意味着如果没有额外的同步化,无法从多个线程访问同一个连接。不过可以为每个线程创建独立的连接,然后同时使用。

13.1.4.先决条件

Ignite的ODBC驱动官方在如下环境中进行了测试:

OS Windows(XP及以上,32位和64位版本)
Windows Server(2008及以上,32位和64位版本)
Ubuntu(14.x和15.x,64位)
C++编译器 MS Visual C++ (10.0及以上), g++ (4.4.0及以上)
Visual Studio 2010及以上

13.1.5.构建ODBC驱动

Ignite的ODBC驱动作为Ignite发行版的一部分,以源代码的形式提供,因此在使用之前需要进行构建。关于如何获取和设置Ignite本身,可以参照1.基本概念章节。
因为ODBC驱动是用C++编写的,因此它是作为Ignite C++的一部分提供的,并且依赖于一些C++库,更具体的就是它依赖于utilsbinaryIgnite库,这就意味着,在构建ODBC驱动本身之前,需要先构建它们。
在Windows上构建
如果要在Windows上构建ODBC驱动,需要MS Visual Studio 2010及以后的版本,一旦打开了Ignite方案%IGNITE_HOME%\platforms\cpp\project\vs\ignite.sln(或者ignite_86.sln,32位平台),在方案浏览器中左击Ignite项目,然后选择“Build”,Visual Studio会自动地检测并且构建所有必要的依赖。

如果使用VS 2015及以后的版本(MSVC14.0及以后),需要将legacy_stdio_definitions.lib作为额外的库加入odbc项目的链接器配置以构建项目,要在IDE中将库文件加入链接器,可以打开项目节点的上下文菜单,选择Properties,然后在Project Properties对话框中,选择Linker,然后编辑Linker Input,这时就可以将legacy_stdio_definitions.lib加入分号分割的列表中。

构建过程结束之后,就可以在%IGNITE_HOME%\platforms\cpp\project\vs\x64\Release中找到ignite.odbc.dll文件。
在Linux上构建
在一个基于Linux的操作系统中,如果要构建及使用Ignite ODBC驱动,需要安装选择的ODBC驱动管理器,Ignite ODBC驱动已经使用UnixODBC进行了测试。
要构建驱动及其依赖,还需要额外的GCC,G++以及Make
如果所有必需的都安装好了,可以通过如下方式构建Ignite ODBC驱动:

  1. d $IGNITE_HOME/platforms/cpp
  2. libtoolize && aclocal && autoheader && automake --add-missing && autoreconf
  3. ./configure --enable-odbc --disable-node --disable-core
  4. make
  5. #The following step will most probably require root privileges:
  6. make install

构建过程完成后,可以通过如下命令找到ODBC驱动位于何处:

  1. whereis libignite-odbc

路径很可能是:/usr/local/lib/libignite-odbc.so

13.1.6.安装ODBC驱动

要使用ODBC驱动,首先要在系统中进行注册,因此ODBC驱动管理器必须能找到它。
在Windows上安装
在32位的Windows上需要使用32位版本的驱动,而在64位的Windows上需要使用64位版本的驱动,也可以在64位的Windows上同时安装32位和64位版本的驱动,这样32位和64位的应用都可以使用驱动。
要在Windows上安装驱动,首先要为驱动在文件系统中选择一个目录,选择一个位置后就可以把驱动放在哪并且确保所有的驱动依赖可以被解析,也就是说,他们要么位于%PATH%,要么和驱动位于同一个目录。
之后,就需要使用%IGNITE_HOME%/platforms/cpp/odbc/install目录下的安装脚本之一,注意,要执行这些脚本,很可能需要管理员权限。
X86:

  1. install_x86 <absolute_path_to_32_bit_driver>

AMD64:

  1. install_amd64 <absolute_path_to_64_bit_driver> [<absolute_path_to_32_bit_driver>]

在Linux上安装
要在Linux上构建和安装ODBC驱动,首先需要安装ODBC驱动管理器,Ignite ODBC驱动已经使用UnixODBC进行了测试。
如果已经构建完成并且执行了make install命令,libignite-odbc.so很可能会位于/usr/local/lib,要在ODBC驱动管理器中安装ODBC驱动并且可以使用,需要按照如下的步骤进行操作:

到现在为止,Ignite的ODBC驱动已经安装好了并且可以用了,可以像其它ODBC驱动一样,连接、使用。

13.2.连接串和DSN

13.2.1.连接串格式

Ignite的ODBC驱动支持标准的连接串格式,下面是正常的语法:

  1. connection-string ::= empty-string[;] | attribute[;] | attribute; connection-string
  2. empty-string ::=
  3. attribute ::= attribute-keyword=attribute-value | DRIVER=[{]attribute-value[}]
  4. attribute-keyword ::= identifier
  5. attribute-value ::= character-string

简单来说,连接串就是分号分割的键值条目列表,在下面可以看到连接串的示例。

13.2.2.支持的参数

Ignite的ODBC驱动可以使用一些连接串/DSN参数,所有的参数都是大小写不敏感的,因此ADDRESSAddressaddress都是有效的参数名,并且指向的是同一个参数。如果参数未指定,会使用默认值,其中的一个例外是ADDRESS属性,如果未指定,会使用SERVERPORT属性代替:

属性关键字 描述 默认值
ADDRESS 要连接的远程节点的地址,格式为:<host>[:<port>]。比如:localhost, example.com:12345, 127.0.0.1, 192.168.3.80:5893,如果指定了这个属性,SERVERPORT将会被忽略。
SERVER 要连接的节点地址,如果指定了ADDRESS属性,本属性会被忽略。
PORT 节点的OdbcProcessor监听的端口,如果指定了ADDRESS属性,本属性会被忽略。 10800
CACHE 缓存名,如果未定义会使用默认的缓存,注意,缓存名是区分大小写的。
DSN 要连接的DSN名
PAGE_SIZE 数据源的响应中返回的行数,默认值会适用于大多数场景,小些的值会导致获取数据变慢,大些的值会导致驱动的额外内存占用,以及获取下一页时的额外延迟。 1024
DISTRIBUTED_JOINS 为在ODBC连接上执行的所有查询开启非并置的分布式关联特性。 false
ENFORCE_JOIN_ORDER 强制SQL查询中表关联顺序,如果设置为true,查询优化器在关联时就不会对表进行再排序。 false
PROTOCOL_VERSION 用于指定使用的ODBC协议版本,目前只有两个版本:1.6.0和1.8.0,如果Ignite版本<1.8.0,需要使用1.6.0协议版本。 1.8.0

13.2.3.连接串示例

下面的串,可以用于SQLDriverConnectODBC调用,来建立与Ignite节点的连接。
指定缓存:

  1. DRIVER={Apache Ignite};SERVER=localhost;PORT=10800;CACHE=MyCache

默认缓存:

  1. DRIVER={Apache Ignite};SERVER=localhost;PORT=10800

DSN:

  1. DSN=MyIgniteDSN

Legacy节点:

  1. DRIVER={Apache Ignite};ADDRESS=example.com:12901;CACHE=SomeCache;PROTOCOL_VERSION=1.6.0

自定义页面大小:

  1. DRIVER={Apache Ignite};ADDRESS=example.com:12901;CACHE=MyCache;PAGE_SIZE=4096

13.2.4.配置DSN

如果要使用DSN(数据源名)来进行连接,可以使用同样的参数。
要在Windows上配置DSN,需要使用一个叫做odbcad32的系统工具,这是一个ODBC数据源管理器,要启动这个工具,打开控制面板->管理工具->数据源(ODBC),当ODBC数据源管理器启动后,选择添加...->pache Ignite,然后以正确的方式配置DSN。

在Linux上配置DSN,需要找到odbc.ini文件,这个文件的位置各个发行版有所不同,依赖于发行版使用的特定驱动管理器,比如,如果使用unixODBC,那么可以执行如下的命令来输出系统级的ODBC相关信息:

  1. odbcinst -j

文件的路径会显示在SYSTEM DATA SOURCESUSER DATA SOURCES属性之间。
找到odbc.ini文件之后,可以用喜欢的任意编辑器打开它,然后像下面这样添加DSN片段:

  1. [DSN Name]
  2. description=<Insert your description here>
  3. driver=Apache Ignite
  4. <Other arguments here...>

13.3.查询和修改数据

像数据库一样访问Ignite。

13.3.1.摘要

本章会详细描述如何接入Ignite集群,如何使用ODBC驱动执行各种SQL查询。
在实现层,Ignite的ODBC驱动使用SQL字段查询来获取Ignite缓存中的数据,这意味着通过ODBC只可以访问这些集群配置中定义的字段。
另外,从Ignite的1.8.0版本开始,ODBC驱动支持DML,这意味着通过ODBC连接不仅仅可以访问数据,还可以修改网格中的数据。

这里是完整的ODBC示例

13.3.2.配置Ignite集群

第一步,需要对集群节点进行配置,这个配置需要包含缓存的配置以及定义了QueryEntities的属性。如果应用(当前场景是ODBC驱动)要通过SQL语句进行数据的查询和修改,QueryEntities是必须的。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:util="http://www.springframework.org/schema/util"
  5. xsi:schemaLocation="
  6. http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/util
  9. http://www.springframework.org/schema/util/spring-util.xsd">
  10. <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
  11. <!-- Enabling ODBC. -->
  12. <property name="odbcConfiguration">
  13. <bean class="org.apache.ignite.configuration.OdbcConfiguration"/>
  14. </property>
  15. <!-- Configuring cache. -->
  16. <property name="cacheConfiguration">
  17. <list>
  18. <bean class="org.apache.ignite.configuration.CacheConfiguration">
  19. <property name="name" value="Person"/>
  20. <property name="cacheMode" value="PARTITIONED"/>
  21. <property name="atomicityMode" value="TRANSACTIONAL"/>
  22. <property name="writeSynchronizationMode" value="FULL_SYNC"/>
  23. <property name="queryEntities">
  24. <list>
  25. <bean class="org.apache.ignite.cache.QueryEntity">
  26. <property name="keyType" value="java.lang.Long"/>
  27. <property name="valueType" value="Person"/>
  28. <property name="fields">
  29. <map>
  30. <entry key="firstName" value="java.lang.String"/>
  31. <entry key="lastName" value="java.lang.String"/>
  32. <entry key="salary" value="java.lang.Double"/>
  33. </map>
  34. </property>
  35. <property name="indexes">
  36. <list>
  37. <bean class="org.apache.ignite.cache.QueryIndex">
  38. <constructor-arg value="salary"/>
  39. </bean>
  40. </list>
  41. </property>
  42. </bean>
  43. </list>
  44. </property>
  45. </bean>
  46. <bean class="org.apache.ignite.configuration.CacheConfiguration">
  47. <property name="name" value="Organization"/>
  48. <property name="cacheMode" value="PARTITIONED"/>
  49. <property name="atomicityMode" value="TRANSACTIONAL"/>
  50. <property name="writeSynchronizationMode" value="FULL_SYNC"/>
  51. <property name="queryEntities">
  52. <list>
  53. <bean class="org.apache.ignite.cache.QueryEntity">
  54. <property name="keyType" value="java.lang.Long"/>
  55. <property name="valueType" value="Organization"/>
  56. <property name="fields">
  57. <map>
  58. <entry key="name" value="java.lang.String"/>
  59. </map>
  60. </property>
  61. <property name="indexes">
  62. <list>
  63. <bean class="org.apache.ignite.cache.QueryIndex">
  64. <constructor-arg value="name"/>
  65. </bean>
  66. </list>
  67. </property>
  68. </bean>
  69. </list>
  70. </property>
  71. </bean>
  72. </list>
  73. </property>
  74. </bean>
  75. </beans>

从上述配置中可以看出,定义了两个缓存,包含了PersonOrganization类型的数据,它们都列出了使用SQL可以读写的特定字段和索引。

预定义字段
除了显式配置的字段外,每个表都有两个特别的预定义字段:_key_val,它们表示到整个键和值对象的链接。这非常有用,比如,当它们中的一个是基本类型并且希望通过它们的值进行过滤时,要实现这一点,可以执行像SELECT * FROM Person WHERE _key = 100这样的查询。
OdbcConfiguration
确保在配置中显式地配置了OdbcConfiguration

13.3.3.接入集群

配置好然后启动集群,就可以从ODBC驱动端接入了。如何做呢?准备一个有效的连接串然后连接时将其作为一个参数传递给ODBC驱动就可以了。
另外,也可以像下面这样使用一个预定义的DSN来接入。

  1. SQLHENV env;
  2. // Allocate an environment handle
  3. SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
  4. // Use ODBC ver 3
  5. SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*>(SQL_OV_ODBC3), 0);
  6. SQLHDBC dbc;
  7. // Allocate a connection handle
  8. SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
  9. // Prepare the connection string
  10. SQLCHAR connectStr[] = "DSN=My Ignite DSN";
  11. // Connecting to Ignite Cluster.
  12. SQLRETURN ret = SQLDriverConnect(dbc, NULL, connectStr, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
  13. if (!SQL_SUCCEEDED(ret))
  14. {
  15. SQLCHAR sqlstate[7] = { 0 };
  16. SQLINTEGER nativeCode;
  17. SQLCHAR errMsg[BUFFER_SIZE] = { 0 };
  18. SQLSMALLINT errMsgLen = static_cast<SQLSMALLINT>(sizeof(errMsg));
  19. SQLGetDiagRec(SQL_HANDLE_DBC, dbc, 1, sqlstate, &nativeCode, errMsg, errMsgLen, &errMsgLen);
  20. std::cerr << "Failed to connect to Apache Ignite: "
  21. << reinterpret_cast<char*>(sqlstate) << ": "
  22. << reinterpret_cast<char*>(errMsg) << ", "
  23. << "Native error code: " << nativeCode
  24. << std::endl;
  25. // Releasing allocated handles.
  26. SQLFreeHandle(SQL_HANDLE_DBC, dbc);
  27. SQLFreeHandle(SQL_HANDLE_ENV, env);
  28. return;
  29. }

13.3.4.查询数据

都准备好后,就可以使用ODBC API执行SQL查询了。

  1. SQLHSTMT stmt;
  2. // Allocate a statement handle
  3. SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
  4. SQLCHAR query[] = "SELECT firstName, lastName, salary, Organization.name FROM Person "
  5. "INNER JOIN \"Organization\".Organization ON Person.orgId = Organization._key";
  6. SQLSMALLINT queryLen = static_cast<SQLSMALLINT>(sizeof(queryLen));
  7. SQLRETURN ret = SQLExecDirect(stmt, query, queryLen);
  8. if (!SQL_SUCCEEDED(ret))
  9. {
  10. SQLCHAR sqlstate[7] = { 0 };
  11. SQLINTEGER nativeCode;
  12. SQLCHAR errMsg[BUFFER_SIZE] = { 0 };
  13. SQLSMALLINT errMsgLen = static_cast<SQLSMALLINT>(sizeof(errMsg));
  14. SQLGetDiagRec(SQL_HANDLE_DBC, dbc, 1, sqlstate, &nativeCode, errMsg, errMsgLen, &errMsgLen);
  15. std::cerr << "Failed to perfrom SQL query upon Apache Ignite: "
  16. << reinterpret_cast<char*>(sqlstate) << ": "
  17. << reinterpret_cast<char*>(errMsg) << ", "
  18. << "Native error code: " << nativeCode
  19. << std::endl;
  20. }
  21. else
  22. {
  23. // Printing the result set.
  24. struct OdbcStringBuffer
  25. {
  26. SQLCHAR buffer[BUFFER_SIZE];
  27. SQLLEN resLen;
  28. };
  29. // Getting a number of columns in the result set.
  30. SQLSMALLINT columnsCnt = 0;
  31. SQLNumResultCols(stmt, &columnsCnt);
  32. // Allocating buffers for columns.
  33. std::vector<OdbcStringBuffer> columns(columnsCnt);
  34. // Binding colums. For simplicity we are going to use only
  35. // string buffers here.
  36. for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
  37. SQLBindCol(stmt, i + 1, SQL_C_CHAR, columns[i].buffer, BUFFER_SIZE, &columns[i].resLen);
  38. // Fetching and printing data in a loop.
  39. ret = SQLFetch(stmt);
  40. while (SQL_SUCCEEDED(ret))
  41. {
  42. for (size_t i = 0; i < columns.size(); ++i)
  43. std::cout << std::setw(16) << std::left << columns[i].buffer << " ";
  44. std::cout << std::endl;
  45. ret = SQLFetch(stmt);
  46. }
  47. }
  48. // Releasing statement handle.
  49. SQLFreeHandle(SQL_HANDLE_STMT, stmt);

列绑定
在上例中,所有的列都绑定到SQL_C_CHAR,这意味着获取时所有的值都会被转换成字符串,这样做是为了简化,获取时进行值转换是非常慢的,因此默认的做法应该是与存储采用同样的方式进行获取。
关联和并置
就像直接通过Java、.NET或者C++API进行SQL查询一样,在分区缓存上进行的关联,只有在关联的对象以并置模式存储时才能正常运行,
跨缓存查询
驱动连接的缓存会被视为默认的模式,要跨越多个缓存进行查询,可以使用跨缓存查询功能。
复制和分区缓存
复制缓存上的查询只会在一个节点上执行,而在分区缓存上的查询会在所有缓存节点上分布式地执行。

13.3.5.插入数据

要将新的数据插入集群,ODBC端可以使用INSERT语句。

  1. SQLHSTMT stmt;
  2. // Allocate a statement handle
  3. SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
  4. SQLCHAR query[] =
  5. "INSERT INTO Person (_key, orgId, firstName, lastName, resume, salary) "
  6. "VALUES (?, ?, ?, ?, ?, ?)";
  7. SQLPrepare(stmt, query, static_cast<SQLSMALLINT>(sizeof(query)));
  8. // Binding columns.
  9. int64_t key = 0;
  10. int64_t orgId = 0;
  11. char name[1024] = { 0 };
  12. SQLLEN nameLen = SQL_NTS;
  13. double salary = 0.0;
  14. SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
  15. SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &orgId, 0, 0);
  16. SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(name), sizeof(name), name, 0, &nameLen);
  17. SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &salary, 0, 0);
  18. // Filling cache.
  19. key = 1;
  20. orgId = 1;
  21. strncpy(name, "John", sizeof(firstName));
  22. salary = 2200.0;
  23. SQLExecute(stmt);
  24. SQLMoreResults(stmt);
  25. ++key;
  26. orgId = 1;
  27. strncpy(name, "Jane", sizeof(firstName));
  28. salary = 1300.0;
  29. SQLExecute(stmt);
  30. SQLMoreResults(stmt);
  31. ++key;
  32. orgId = 2;
  33. strncpy(name, "Richard", sizeof(firstName));
  34. salary = 900.0;
  35. SQLExecute(stmt);
  36. SQLMoreResults(stmt);
  37. ++key;
  38. orgId = 2;
  39. strncpy(name, "Mary", sizeof(firstName));
  40. salary = 2400.0;
  41. SQLExecute(stmt);
  42. // Releasing statement handle.
  43. SQLFreeHandle(SQL_HANDLE_STMT, stmt);

下面,是不使用预编译语句插入Organization数据:

  1. SQLHSTMT stmt;
  2. // Allocate a statement handle
  3. SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
  4. SQLCHAR query1[] = "INSERT INTO \"Organization\".Organization (_key, name)
  5. VALUES (1L, 'Some company')";
  6. SQLExecDirect(stmt, query1, static_cast<SQLSMALLINT>(sizeof(query1)));
  7. SQLFreeStmt(stmt, SQL_CLOSE);
  8. SQLCHAR query2[] = "INSERT INTO \"Organization\".Organization (_key, name)
  9. VALUES (2L, 'Some other company')";
  10. SQLExecDirect(stmt, query2, static_cast<SQLSMALLINT>(sizeof(query2)));
  11. // Releasing statement handle.
  12. SQLFreeHandle(SQL_HANDLE_STMT, stmt);

错误检查
为了简化,上面的代码没有进行错误检查,但是在生产环境中不要这样做。

13.3.6.更新数据

下面使用UPDATE语句更新存储在集群中的部分人员的工资信息:

  1. void AdjustSalary(SQLHDBC dbc, int64_t key, double salary)
  2. {
  3. SQLHSTMT stmt;
  4. // Allocate a statement handle
  5. SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
  6. SQLCHAR query[] = "UPDATE Person SET salary=? WHERE _key=?";
  7. SQLBindParameter(stmt, 1, SQL_PARAM_INPUT,
  8. SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &salary, 0, 0);
  9. SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG,
  10. SQL_BIGINT, 0, 0, &key, 0, 0);
  11. SQLExecDirect(stmt, query, static_cast<SQLSMALLINT>(sizeof(query)));
  12. // Releasing statement handle.
  13. SQLFreeHandle(SQL_HANDLE_STMT, stmt);
  14. }
  15. ...
  16. AdjustSalary(dbc, 3, 1200.0);
  17. AdjustSalary(dbc, 1, 2500.0);

13.3.7.删除数据

最后,使用DELETE语句删除部分记录:

  1. void DeletePerson(SQLHDBC dbc, int64_t key)
  2. {
  3. SQLHSTMT stmt;
  4. // Allocate a statement handle
  5. SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
  6. SQLCHAR query[] = "DELETE FROM Person WHERE _key=?";
  7. SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT,
  8. 0, 0, &key, 0, 0);
  9. SQLExecDirect(stmt, query, static_cast<SQLSMALLINT>(sizeof(query)));
  10. // Releasing statement handle.
  11. SQLFreeHandle(SQL_HANDLE_STMT, stmt);
  12. }