【问题标题】:OCI Statements and bind variablesOCI 语句和绑定变量
【发布时间】:2018-02-21 22:00:39
【问题描述】:

我们遇到了一个 C 程序使用 OCI 将值插入到 oracle 数据库中的问题
表结构为:
desc 表员工;

 Name                       Null?     Type

 EMPLOYEE_ID                          NUMBER
 SALARY                               NUMBER
 DEPARTMENT_ID                        NUMBER

我们对表使用的查询是:

Insert into employee(employee_ID, salary, department_id) values ( :1, DECODE(:2,  4294967295, -1, :2), :3);

我们打算在带有解码的插入语句中做的是if the value of "salary" (:2) is equal to 4294967295 然后insert the value -1 into the database otherwise insert the original value (:2)
在 C 程序中,查询绑定了三个值。

在执行查询时,我们会收到以下错误消息:

错误 - OCI_ERROR ORA-01008:并非所有变量都绑定

同一个绑定变量能否在使用 DECODE 的 OCI 语句调用中使用两次?有没有办法可以修改查询,仍然实现工资值的翻译?

【问题讨论】:

  • 插入时可以使用触发器检查数据吗?你能在插入之前在c中做检查吗?
  • 是否允许在查询中多次使用相同的绑定值编号?即(:2)?只需使用不同的数字并相应地更改绑定语句。 Oracle 不知道变量在哪里使用的含义,它只是将绑定语句中的数字与准备好的查询中的相应数字进行匹配。
  • 我不确定 C 中的 OCI,但在 PHP + OCI 中,允许多次使用同一个占位符(并且只绑定一次)。但无论如何,我认为 Ryan 的建议值得一试:使用多个占位符并多次绑定。
  • FWIW,我们过去在使用相同的绑定变量两次(尽管在完全不同的上下文中)时遇到了 Oracle 的问题。我同意@RyanVincent - 使用不同的数字,更改绑定语句,并检查它是否有效。
  • 这也可能是 C 程序中的一个简单错误(例如,将错误的索引传递给 OCIBindByPos()) - 能否请您也发布相关的 C 代码?

标签: sql oracle oracle-call-interface


【解决方案1】:

把你的sql语句改成:

Insert into employee(employee_ID, salary, department_id) values ( :1, DECODE(:2,  4294967295, -1, :3), :4);

并按以下顺序传递绑定变量

employee_ID, salary, salary, department_id

请注意,工资需要通过两次才能满足您的要求

【讨论】:

  • 更具体地说,OCI 在这里具有误导性,因为您可以在冒号后放置任何数字,并且只要您按照绑定占位符的顺序进行绑定,它仍然有效。不直观,我知道...
  • 这绝对正确,编号只是让代码看起来更容易,最后你知道需要绑定多少变量。此外,您还可以使用字符和字符串(不带空格)。
  • 当然,这样的推论是不能重用与 OP 尝试相同的绑定,如果你想在多个占位符中使用相同的 C/C++ 变量,则必须多次绑定相同的 C/C++ 变量。正如 OP 发现的那样,将占位符命名相同并没有帮助。
【解决方案2】:

我愿意:

Insert into employee(employee_ID, salary, department_id) values ( :employee_ID, DECODE(:salary,  4294967295, -1, :salary), :department_id);

并使用:

OCIBindByName()

然后只绑定

employee_ID, salary, department_id (order wouldn't matter anymore)

所有同名占位符都绑定到单个绑定变量(节省空间和性能)

【讨论】:

    【解决方案3】:

    又快又脏。

    模仿你期望 OCI 做的事情编写你的 C 代码:

    class OracleQuery{
    public:
      OracleQuery(std::string aQuery) : query_(aQuery){}
      size_t setString(size_t aPlaceHolder, const std::string& aSubS);
      std::string getSQL(){ return query_; }
    private:
      std::string query_;
    };
    
    size_t OracleQuery::setString(size_t aPlaceHolder, const std::string& aSubS)
    {
      std::string toReplace = "'" + aSubS + "'";
      size_t countReplace = 0;
      std::string myPlaceHolder = ":" + std::to_string(aPlaceHolder);
      size_t len = myPlaceHolder.size();
      std::string myNewQuery;
      size_t pos = 0;
      while (true){
        pos = query_.find(myPlaceHolder, pos);
        if (pos == std::string::npos)
          break;
        ++countReplace;
        query_.replace(pos, len, toReplace);
      }
      return countReplace;
    }
    

    当您需要它时,您可以使用 setInt() 方法对其进行扩展。等等等等……

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-07
      • 2019-01-28
      • 1970-01-01
      • 1970-01-01
      • 2011-06-09
      • 2019-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多