【问题标题】:Query returns different results between PL/SQL Developer and PHP查询在 PL/SQL Developer 和 PHP 之间返回不同的结果
【发布时间】:2013-08-19 19:02:22
【问题描述】:

我创建了一个小型 Intranet 网站来收集和存储数据,以用于加快我们的物流流程。我现在正在添加搜索功能,如果找到与该条件匹配的记录,将允许用户快速选择部分数据以使用数据预填充新的运输请求(例如,用户键入“收件人姓名输入文本框中的 Mar' 和街道地址输入文本框中的 '109',查询返回两条记录:{"Mary Smith", "1090 South Central St"} 和 {"Mark Swanson", "109 E. 31st"圣”})。

目前,当输入并提交搜索条件时,当且仅当输入单个条件(例如收件人姓名)时,从 PHP 查询返回的数据是 100% 准确的。当我尝试在 PHP 中使用两个不同的搜索条件时,记录结果与在 Oracle PL/SQL Developer 中运行相同查询时的结果不匹配。如果使用三种不同的搜索条件,在 PHP 中运行的查询将返回 0 条记录。在上述所有三个场景中,查询在 Oracle PL/SQL Developer 中执行时都没有错误。

以下代码来自我的 PHP 搜索功能。此函数的输入数据是字段名称的关联数组和用户为该字段输入的搜索条件数据。

     public function Search()
     {
        if($this->dbcon)
        {
            $query = "SELECT * FROM ship_request ";
            $postCount = count($this->post_data);
            $counter = 0;

            if ($postCount > 0) 
            {
                $query .= "WHERE ";
            }

            foreach ($this->post_data as $k => $v)
            {
                $counter++;
                if (strlen($v) > 0)
                {
                    if ($k == 'SR_DATE') 
                    {
                        $query .= $k . " = :" . $k . " AND ";
                    } else {
                        $query .= "upper(" . $k . ") like upper(:" . $k . ") AND ";
                    }
                }
            } 

            if (substr($query,-4) == "AND ")
            {
                $query = substr($query, 0, strlen($query) - 4);
            }

            $stid = oci_parse($this->ifsdb, $query);

             foreach ($this->post_data as $k => $v)
            {
                if (strlen($v) > 0)
                {
                    if ($k == 'SR_DATE') 
                    {
                        $this->post_data[$k] = date("d-M-y", strtotime($this->post_data[$k]));
                        $placeHolder = $this->post_data[$k];
                    } else {
                        $placeHolder = '%' . $this->post_data[$k] . '%';

                    }
                    oci_bind_by_name($stid, $k, $placeHolder);
                }
            }
            oci_execute($stid);
            $nrows = oci_fetch_all($stid, $recordsFound);
            $recordsFound = json_encode($recordsFound);
            oci_free_statement($stid);
            echo $recordsFound;
        } else {
            die("Could not connect to database!");
        }
    }
}

我已经对 $query 进行了 var_dump,以查看当我输入多个搜索条件值时我的查询实际上是什么样子。这是我看到的一个例子:

select * from HOL_SHIP_REQUEST where upper(sr_shipper_name) like upper(:sr_shipper_name) and upper(sr_recipient_name) like upper(:sr_recipient_name) and sr_recipient_phone like upper(:sr_recipient_phone)

当我输入“a”作为发件人姓名、“m”作为收件人姓名、“2”作为电话号码时,该查询返回 0 条记录。

但是,当在 Oracle PL/SQL Developer 中执行此查询时,会返回 27 条记录。

select * from HOL_SHIP_REQUEST where upper(sr_shipper_name) like upper('%a%') and upper(sr_recipient_name) like upper('%m%') and sr_recipient_phone like upper('%2%')

我尝试在 PHP 中绑定参数的方式有问题吗?使用多个 like 语句时我需要做些什么不同的事情吗?

【问题讨论】:

    标签: php oracle plsql


    【解决方案1】:

    您忘记了构建的查询字符串中的% 通配符。 DB 接口库不会解析您正在构建的查询,也不会寻找LIKE 子句——猜测您要进行哪种匹配不是他们的工作。例如你在干吗

    WHERE a LIKE 'b'
    WHERE a LIKE 'b%'
    WHERE a LIKE '%b'
    WHERE a LIKE '%b%'
    

    提供适当的通配符由您决定,并且由于您使用占位符,因此您必须自己做,例如

    WHERE UPPER(sr_shipper_name) LIKE CONCAT('%', :sr_shipper_name, '%')
    

    如果你要这样做:

    $shipper = '%foo%';
    
    WHERE  ... LIKE :shipper
    

    你会得到相当于:

    WHERE ... LIKE '\%foo\%'
    

    占位符系统也不会解析您提供的文本并尝试确定您是否真的在尝试使用通配符或只是传入文字 % 字符。这就是为什么您必须使用 CONCAT hack 来构建适当的通配符构造。

    【讨论】:

    • 感谢您的意见。你是对的 - 我忘记了通配符。但是,当我尝试通过在参数之间使用CONCAT|| 来修复此功能时,我仍然得到相同的结果。使用一个搜索条件/LIKE 语句在 PHP 中返回准确结果,在 PHP 中使用两个搜索条件/LIKE 语句时返回与搜索条件不匹配的记录,使用三个或多个搜索条件/LIKE 语句返回零记录。跨度>
    • 您将AND 用于您的各种like 子句,因此如果它们全部与and 绑定在一起,您将获得所有子句匹配的唯一记录。您可能想要 OR 代替,即使 ONE 字段匹配,您也会在其中获得结果。
    • 您对OR 部分的看法是正确的——以这种方式进行搜索确实更有意义。不过,在比较 PHP 和 Oracle PL/SQL Developer 之间的查询时,我仍然没有得到正确的结果。有趣的是,当我使用直接比较(例如SR_RECIPIENT_COMPANY = :sr_recipient_company)时,查询结果是正确的,但我真的很想使用通配符(除非你能提出更好的方法)。
    • 可能想改用全文索引,虽然我从来没有处理过 oracle,所以不知道它的功能是什么样的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多