查询在PL/SQL Developer和PHP之间返回不同的结果


Query returns different results between PL/SQL Developer and PHP

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

目前,当输入并提交搜索条件时,如果并且仅当输入了单个条件(如收件人姓名),则PHP中的查询返回的数据是100%准确的。当我尝试在PHP中使用两种不同的搜索标准时,在OraclePL/SQLDeveloper中运行同一查询时,记录结果与结果不匹配。如果使用三种不同的搜索标准,则在PHP中运行的查询将返回0条记录。在上述三种场景中,在OraclePL/SQLDeveloper中执行查询时都不会出现错误。

以下代码来自我的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语句时,我需要做什么不同的事情吗?

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

占位符系统也不会解析您提供的文本,并试图弄清楚您是否真的在尝试使用wilcard或只是传递一个文本%字符。这就是为什么你必须使用CONCAT破解来构建一个合适的通配符结构。