我们使用 Oracle 12c 数据库和带有 OCCI 的 CentOS7 进行连接。我们试图在数据库中插入一个 char 数组,但是这个 char 数组中间有一个 NUL 字符。当我们使用 statement->setString 函数时,更新是成功的,但是一旦它看到 NUL 字符,它只会将 NUL 字符放在那里。请参阅此示例代码及其输出。
使用 setString 的示例代码:
static void Run(const std::string &connectionString, const std::string &user, const std::string &pwd)
{
Environment *env = Environment::createEnvironment();
Connection *conn = env->createConnection(user, pwd, connectionString);
Statement *stmt = conn->createStatement("UPDATE my_customers SET first_name = :1 WHERE customer_id = :2");
stmt->setString(1, std::string("GEO\0RGE ", 20));
stmt->setInt(2, 10);
stmt->setString(1, std::string(adrs_first_name, sizeof(adrs_first_name)));
oracle::occi::Statement::Status status = stmt->execute();
conn->terminateStatement(stmt);
conn->commit();
}
更新后访问数据库:
SELECT first_name FROM my_customers WHERE customer_id = 10;
GEO
SELECT rawtohex(first_name) FROM my_customers WHERE customer_id = 10;
47454F0000000000000000000000000000000000
但是我本来希望它是
47454F0047452032322020202020202020202020
所以我尝试使用 oracle::occi::Bytes——这个错误
ORA - 12899: 列“MAIN_USER”.“MY_CUSTOMERS”.“FIRST_NAME”的值太大(实际:40,最大值:20)
使用 setBytes 的示例代码:
static void Run(const std::string &connectionString, const std::string &user, const std::string &pwd)
{
Environment *env = Environment::createEnvironment();
Connection *conn = env->createConnection(user, pwd, connectionString);
Statement *stmt = conn->createStatement("UPDATE my_customers SET first_name = :1 WHERE customer_id = :2");
std::string s("GEO\0RGE ", 20);
oracle::occi::Bytes bytes((unsigned char *)s.c_str(), 20, 0, env);
stmt->setBytes(1, bytes);
stmt->setInt(2, 10);
try
{
oracle::occi::Statement::Status status = stmt->execute();
}
catch (oracle::occi::SQLException &e)
{
std::cout << "Error " << e.getErrorCode() << ": " << e.what() << std::endl;
}
conn->terminateStatement(stmt);
conn->commit();
}
输出:
Error 12899 : ORA - 12899 : value too large for column "MAIN_USER"."MY_CUSTOMERS"."FIRST_NAME" (actual : 40, maximum : 20)
因此,我尝试通过将 oracle::occi::Bytes 构造函数的第二个参数更改为 10 来发送一半字节,但它成功了,但是在从数据库中读取值后,我意识到它是十六进制值的字符串表示形式字符。所以我此时的问题是,当我通过 oracle::occi:Bytes 时,为什么 Oracle12c 将十六进制值作为字符串。
使用一半实际长度和 setBytes 的示例代码:
static void Run(const std::string &connectionString, const std::string &user, const std::string &pwd)
{
Environment *env = Environment::createEnvironment();
Connection *conn = env->createConnection(user, pwd, connectionString);
Statement *stmt = conn->createStatement("UPDATE my_customers SET first_name = :1 WHERE customer_id = :2");
std::string s("GEO\0RGE ", 20);
oracle::occi::Bytes bytes((unsigned char *)s.c_str(), 10, 0, env);
stmt->setBytes(1, bytes);
stmt->setInt(2, 10);
try
{
oracle::occi::Statement::Status status = stmt->execute();
}
catch (oracle::occi::SQLException &e)
{
std::cout << "Error " << e.getErrorCode() << ": " << e.what() << std::endl;
}
conn->terminateStatement(stmt);
conn->commit();
}
更新后访问数据库:SELECT first_name FROM my_customers WHERE customer_id = 10;
47454F00524745202020
注意:这个查询没有用 rawtohex 包装——这是数据库中实际的 char 数组值。
这是表定义:
DESCRIBE MAIN_USER.MY_CUSTOMERS
Name Null Type
------------------------------ ---- --------------
CUSTOMER_ID NUMBER(10)
FIRST_NAME CHAR(20 CHAR)
以下是我们的 Oracle 实例信息:Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64 位生产,具有分区、真正应用程序集群、自动存储管理、OLAP、高级分析和真正应用程序测试选项
我们正在使用 Oracle occi 客户端 12.1 64bit