【问题标题】:why oci_bind_by_name not working if inside oracle function如果在 oracle 函数中,为什么 oci_bind_by_name 不起作用
【发布时间】:2020-09-04 04:18:51
【问题描述】:

对不起,我的英语不好。我认为如果我把我的代码放在这里会更容易。所以这是我尝试过的:

//这是有效的

$sql = "select ID, NAME, BDATE from EMPLOYEES where BDATE >= DATE '2020-01-01'"; 

//但是当我尝试这样做时,它失败了:

$sql = "select ID, NAME, BDATE from EMPLOYEES where BDATE >= DATE :bdate"; //this is 
$compiled = oci_parse($conn, $sql);
oci_bind_by_name($compiled, ":bdate", "2020-01-01");

上面会引发这个错误:

"code":936,"message":"ORA-00936: 缺少表达式"

我尝试过其他类似的方法:

//失败

$sql = "select ID, NAME, BDATE from EMPLOYEES where BDATE >= TO_DATE(:bdate, 'YYYY-MM-DD')"; 
oci_bind_by_name($conn, ':bdate', '2020-01-01');

上面会引发这个错误:

"code":1847,"message":"ORA-01847: 日期必须介于 1 和 一个月的最后一天”

//当我放入 DATE、TO_DATE、UPPER 等函数时总是失败

$sql = "select ID, NAME, BDATE, STATUS from EMPLOYEES where upper(STATUS) = upper(:status)"; 

//In 子句中的事件也会失败

$sql = "select ID, NAME, BDATE, STATUS from EMPLOYEES where upper(STATUS) in (:status1, :status2)"; 
oci_bind_by_name($compiled, ":status1", "SINGLE");
oci_bind_by_name($compiled, ":status2", "MARRIED");

谁能告诉我如何解决这个问题? 我遵循了文档中的许多教程,以及另一个 stackoverflow 答案。但没有任何效果。

或者是我错过了在我的网络服务器上设置的东西吗?还是在我的数据库服务器上?

仅供参考,我使用的是 PHP7.2、OCI8、Oracle 11g。

非常感谢。

【问题讨论】:

  • 不确定,但尝试在变量中设置值 - $date = "2020-01-01";,然后将变量放入绑定 oci_bind_by_name($compiled, ":bdate", $date);
  • 谢谢。我已经做到了。我事件直接将其放入 oci_bind_by_name 中,不带变量。像这样:oci_bind_by_name($conn, ':bdate', '2020-01-01');

标签: php oracle oracle11g oracle-call-interface


【解决方案1】:

这在 php 7.4、Oci8/Oracle 19c 数据库上对我有用。(我从来没有在 php 上工作过,只是到处搜索)

    $sql = "SELECT ename FROM emp WHERE hiredate > TO_DATE(:hdate,'YYYY-MM-DD')";
    $stid = oci_parse($conn, $sql);
    $hdate = "1980-01-01";
     oci_bind_by_name($stid,':hdate', $hdate);
   // oci_bind_by_name($stid,":hdate", $hdate);  //this line also works i.e double quotes

编辑:- IN 子句也适用于我。这是我了解到的,您不能在 OCI_BIND 中传递文字值,即首先将文字分配给变量

$sql = "SELECT ename FROM emp WHERE job IN (:job1,:job2)";
$stid = oci_parse($conn, $sql);
$job1 ='CLERK';
$job2 = 'SALESMAN';
oci_bind_by_name($stid,':job1', $job1);
oci_bind_by_name($stid,':job2',$job2);
oci_execute($stid);

查看这些link1link2 了解适用于 Oracle 数据库的示例

【讨论】:

  • 啊我不知道我们不能在 oci_bind 中传递文字值。让我试试。谢谢
  • 哇!!!我从来没有想过这是问题所在。我们只是不能传递文字值,必须使用变量。在我将它们放入变量后,它现在可以工作了。这个 PHP 的行为多么奇怪 :) 非常感谢 Sam。我选择了该笔记接受的答案。
  • 更新:经过更多研究。我发现关键是我们必须通过引用变量传递值。因为它是 oci_bind_by_name 函数的定义。
【解决方案2】:

DATE '2020-01-01' 是 ANSI date literal 语法。这是一种在代码中键入原始日期的机制,它对变量或占位符没有意义,因此会出现错误。

如前所述,您可以使用TO_DATE() function 作为替代。

【讨论】:

  • 感谢您提到它是日期文字语法。我不知道。我一直在使用它,因为它有效:)。我将再次尝试使用带有变量的 TO_DATE 函数,因为 Sam 下面说我们不应该使用文字值,必须使用变量。谢谢
【解决方案3】:

这应该可行:

where BDATE >= TO_DATE(:bdate, 'YYYY-MM-DD')

但前提是您提供的日期值完全与您指定的格式相同:YYYY-MM-DD。你得到的错误:

ORA-01847: 日期必须介于 1 和最后一天之间

表示您提供了无效的字符串,例如2020-05-38 - 任何一个月都没有 38 天,Oracle 预计数字在 1 到 31 之间(因为 5 月有 31 天)。


使用检查默认日期格式

SQL> select * From nls_session_parameters where parameter = 'NLS_DATE_FORMAT';

PARAMETER            VALUE
-------------------- --------------------
NLS_DATE_FORMAT      DD.MM.RR

SQL>

这意味着您将 - 在我的数据库中 - 将值作为 18.05.20 传递给今天的日期。

【讨论】:

  • 谢谢,但实际上我通过了 '2020-01-01' 的值。但不知何故,它引发了这个错误。
  • 对不起,我误解了错误信息;固定的。作为你传递的价值:那不应该发生;每个月都有“01”日,所以......也许它与您使用的环境有关(PHP7.2、OCI8、Oracle 11g)。查看数据库中的默认 NLS 设置和日期格式。然后尝试使用该格式的日期。我编辑了我的消息并添加了您可能使用的查询。
  • 我的 NLS_DATE_FORMAT=DD-MON-RR 我试过这个:oci_bind_by_date($conn, ":end_date", '01-JAN-2020');它引发此错误:“code”:936,“message”:“ORA-00936:缺少表达式”我怀疑我在服务器设置上缺少某些东西。
  • 也许……我不懂 PHP,所以帮不上什么忙。谷歌搜索提到像date("d-M-Y H:i:s") 这样的东西 - 也许date ("01-01-20") 会有所帮助?如果没有,恐怕我没有其他想法。
猜你喜欢
  • 2022-06-15
  • 2019-11-13
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多