【问题标题】:Oracle inner join headache oci_execute(): ORA-00920: invalid relational operatorOracle 内连接头痛 oci_execute(): ORA-00920: 无效的关系运算符
【发布时间】:2016-01-08 21:22:16
【问题描述】:

我正在尝试使用两个表完成内部联接(Oracle 称它们为等联接),但我只是缺少一些东西,因为它与 MySQL 内部联接不同。我也是 PHP 的新手(来自 Lasso),所以为了我自己的理智,我试图严格使用我的语法。我查看了有关此错误的所有其他帖子,但没有帮助。

使用 PHP 5.5.29 连接到 Oracle 12c 数据库,OCI8 已安装并在 php 信息页面中进行验证。

Oracle's explanation of inner joins

$login 是明文,$pw 在这个 sn-p 之前被散列:

// separate the login types by the "_" character
if (strpos($login, "_") == true) {
    $fieldname = 'web_password_hash';
    $dynfield = 'web_id';
    $dynfield1 = 's.web_id';
} else {
    $fieldname = 'student_web_password_hash';
    $dynfield = 'student_web_id';
    $dynfield1 = 's.student_web_id';
}

$schoolid = '(pcs.schoolid=4 OR pcs.schoolid=5)';

// search custom table for a field with the correct password (parent/student)
$dbc = oci_connect($psusername, $pspassword, $psconnection);

if(!$dbc) {
    echo "Oracle Not connected";
} else {

$stmt = oci_parse($dbc, 'SELECT pcs.student_number AS snumber, :dynfield1 AS loginid, s.ID AS sid, s.family_ident AS famid, s.firstname AS fname, s.last_name AS lname, s.grade_level AS gradelevel 
    FROM pvsis_custom_students pcs, students s 
        WHERE pcs.student_number=s.student_number 
            AND :schoolid 
            AND pcs.field_name=:fieldname 
            AND pcs.string_value=:pw 
            AND s.enroll_status=0;');

// bind parameters to prevent SQL injection         
oci_bind_by_name($stmt, ':dynfield1', $dynfield1);          
oci_bind_by_name($stmt, ':fieldname', $fieldname);
oci_bind_by_name($stmt, ':schoolid', $schoolid);
oci_bind_by_name($stmt, ':pw', $pw);

// execute statement
oci_execute($stmt);

然后我得到的错误是:警告: oci_execute(): ORA-00920: invalid relational operator in /path/to/file line XXX

【问题讨论】:

  • 您需要选择s.student_number
  • 好的。有两种不同的选择用于两种不同的目的。此外,请包含执行并引发错误的 实际 选择。

标签: php oracle


【解决方案1】:

您无法像在此处那样绑定字段名称。您需要动态构建查询:

$stmt = oci_parse($dbc, 'SELECT pcs.student_number AS snumber, ' . $dynfield1 . ' AS loginid, s.ID AS sid, s.family_ident AS famid, s.firstname AS fname, s.last_name AS lname, s.grade_level AS gradelevel 
    FROM pvsis_custom_students pcs, students s 
        WHERE pcs.student_number=s.student_number 
            AND ' . $schoolid . '
            AND pcs.field_name=' . $fieldname . '
            AND pcs.string_value=:pw 
            AND s.enroll_status=0;');

删除对:dynfield1:fieldname:schoolidbind_by_name 调用。

祝你好运。

【讨论】:

  • 我认为绑定是防止 SQL 注入的最佳方法?
  • 当您接受来自用户输入值之类的输入时,您确实需要关注这一点。但是,在这种情况下,您的值都是例程中的字符串常量,因此不可能进行注入。更重要的是,您不能绑定列名 - 它只是行不通。您可以绑定,但不能绑定列名、表名、where 子句的片段等。
  • 您错过的 :pw 字段,也就是密码,是用户输入字段。
  • 如果你注意到的话,我把它作为一个绑定值而不是将它连接到 SQL 查询中,因为我无法确定连接是安全的 - 也是因为在这种情况下绑定很好,因为绑定的是一个值而不是字段名。另请注意,我没有说要删除:pwbind_by_name。谢谢。
  • 哦,我明白了,谢谢鲍勃。我正在学习所有这些 PHP 的细微差别:)
猜你喜欢
  • 2014-09-17
  • 2018-08-07
  • 2014-03-25
  • 2020-02-07
  • 1970-01-01
  • 2014-07-07
  • 1970-01-01
  • 2019-11-20
相关资源
最近更新 更多