我们正在使用Oracle 12c数据库和CentOS7与OCCI进行连接。我们试图在数据库中插入一个char数组,但是这个char数组在中间有一个NUL字符。当我们使用statement-> setString函数时,更新成功,但是一旦它看到NUL char,它只会在之后放置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:值太大而无法列#34; 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企业版12.1.0.2.0版 - 64位生产 使用分区,Real Application Clusters,自动存储管理,OLAP, 高级分析和实际应用程序测试选项
我们正在使用Oracle occi客户端12.1 64位
答案 0 :(得分:0)
对于那些可能偶然发现的人,我最终与Oracle支持人员交谈,他们告诉我没有办法做我想要的事情(正如预期的那样)但是Byte的解决方法让我们更接近我们能够采取由setBytes传入的十六进制字符串,并将其转换为原始数据,然后将原始数据转换为varchar2,最终“工作” - 但我不知道我们将在以后遇到什么影响,但到目前为止它似乎工作。
<强>代码:强>
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 = utl_raw.cast_to_varchar2(hextoraw(: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();
}
然后检查数据库:
SELECT rawtohex(first_name) FROM my_customers WHERE customer_id = 10;
47454F0052474520202020202020202020202020
所以它似乎有用