0

我制作了一个小型内部网站来收集和存储用于加快物流流程的数据。我现在正在添加搜索功能,如果找到与该条件匹配的记录,将允许用户快速选择部分数据以使用数据预填充新的运输请求(例如,用户键入“收件人姓名输入文本框中的 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使用多个语句时我需要做些什么不同的事情吗?

4

1 回答 1

3

您忘记了%构建的查询字符串中的通配符。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\%'

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

于 2013-08-19T19:09:24.193 回答