Reputation: 653
I have made a small intranet website to collect and store data to be used to expedite our logistics processes. I'm now in the process of adding search functionality which, if records are found that match that criteria, will allow the user to quickly select parts of that data to pre-populate a new shipping request with data (e.g, the user types 'Mar' in the Recipient Name input textbox and '109' in the Street Address input textbox and the query returns two records: {"Mary Smith", "1090 South Central St"} and {"Mark Swanson", "109 E. 31st St."}).
At the moment, when search criteria is entered and submitted, the data returned from the query in PHP is 100% accurate if and only if a single criteria is entered (such as Recipient Name). When I attempt to use two different search criterias in PHP, the record results do not match the results when running the same query in Oracle PL/SQL Developer. If three different search criterias are used, the query ran in PHP will return 0 records. In all three of the aforementioned scenarios, the query is executed without error in Oracle PL/SQL Developer.
The following code is from my PHP search function. The input data to this function is an associate array of field names and the user inputted search criteria data for that field.
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!");
}
}
}
I've done a var_dump on $query to see what my query actually looks like when I enter multiple search criteria values. This is an example of what I see:
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)
That query returns 0 records when I enter "a" for Shipper Name, "m" for Recipient Name, and "2" for Phone Number.
This query, when executed in Oracle PL/SQL Developer, however, returns 27 records.
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%')
Is there something wrong with the way that I'm trying to bind the parameters in PHP? Is there something different I have to do when using multiple like
statements?
Upvotes: 0
Views: 1394
Reputation: 360762
You've forgotten the %
wildcard chars in your built query string. The DB interface libraries do NOT parse the query you're building, and do NOT look for LIKE
clauses - it's not their job to guess what kind of match you're trying to do. e.g. are you doing
WHERE a LIKE 'b'
WHERE a LIKE 'b%'
WHERE a LIKE '%b'
WHERE a LIKE '%b%'
It's up to you to provide the appropriate wildcards, and since you're using placeholders, you'll have to do it yourself, e.g.
WHERE UPPER(sr_shipper_name) LIKE CONCAT('%', :sr_shipper_name, '%')
If you were to do it something like this:
$shipper = '%foo%';
WHERE ... LIKE :shipper
you'd end up with the equivalent of:
WHERE ... LIKE '\%foo\%'
The placeholder system also doesn't parse your provided text and try to figure out if you're really trying to use a wilcard or just passing in a literal %
char. That's why you have to use the CONCAT
hack to build a proper wildcarded construct.
Upvotes: 3