0

MySQL query is

SELECT CompanyName, RegistrationNumber, VatCode 
FROM 18_6_TransactionPartners 
WHERE (CompanyName = ? OR RegistrationNumber = ? OR VatCode = ?) 

? replace with $data_show_existing_records. But initially $data_show_existing_records is in form of string (user input).

At first decided to create such $data_show_existing_records = $data_show_existing_records. $data_a[$i]. ','. $data_b[$i]. ','. $data_d[$i]. ','; (this is created within foreach, because $i may be only 0, but may also be 100)

And convert to array in such way

$data_show_existing_records = substr($data_show_existing_records, 0, -1);

$data_show_existing_records = explode(",", $data_show_existing_records);

But for example for CompanyName user may input My, company or leave some input empty.

In such case I will get error SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens. Because there would be more $data in array than ?.

Then decided replace , with | (because suppose | is less used than ,).

But this seems not good solution. What would be better (what to use as string/user input separator)? May be just need to escape , (but how)? Please, advice

Update Found solution for empty input: $data_show_existing_records = $data_show_existing_records. "$data_a[$i]". ','. "$data_b[$i]". ','. "$data_d[$i]". ',';

But what to do with ,?

Next update

Create initial query(shortened code) and data for the query

foreach ($num_row_1 as $i => $row) {//$num_row_1 is number of rows in user input
$query_to_show = $query_to_show. 'WHERE (CompanyName = ? OR RegistrationNumber = ? OR VatCode = ?) ';
$data_show_existing_records = $data_show_existing_records. "$data_a[$i]". '"|"'. "$data_b[$i]". '"|"'. "$data_d[$i]". '"|"';
}

Get for example:

$query_to_show =

WHERE (CompanyName = ? OR RegistrationNumber = ? OR VatCode = ?) OR (CompanyName = ? OR RegistrationNumber = ? OR VatCode = ?)

and

$data_show_existing_records =

first name"|"123"|"112233"|"second name"|"456"|"445566"|"

Then convert to array

$data_show_existing_records = substr($data_show_existing_records, 0, -1);
$data_show_existing_records = explode('"|"', $data_show_existing_records);

And then final query

$query_show_existing_records = "
SELECT CompanyName, RegistrationNumber, VatCode 
FROM 18_6_TransactionPartners 
$query_to_show
";

And prepare/execute

$sql_show_existing_records = $db->prepare($query_show_existing_records);
$sql_show_existing_records->execute($data_show_existing_records);
$data_show_existing_records1 = $sql_show_existing_records->fetchAll(PDO::FETCH_ASSOC);

Solution

Changed preparation for query and data to following:

$flag = 0;//Set as WHERE
$data_show_existing_records = array();

foreach ($num_row_1 as $i => $row) {

if($flag == 0) {
$query_to_show = $query_to_show. 'WHERE (CompanyName = ? OR RegistrationNumber = ? OR VatCode = ?) ';
$flag = 1;
}
else {
$query_to_show = $query_to_show. 'OR (CompanyName = ? OR RegistrationNumber = ? OR VatCode = ?) ';
}

$data_show_existing_records[] = $data_a[$i];
$data_show_existing_records[] = $data_b[$i];
$data_show_existing_records[] = $data_d[$i];

}
4

1 回答 1

1

SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens means that you supplied more variables than there are ? that can be bound to them. Looking at your code and explanation, you are making a comma seperated list that can contain 3 values, but can also contain 300 values if it happens to contain 100 rows.

To answer your question: Choose a character, or a serie of characters as seperator that cannot be in the data. Choosing a seperator that is in the data, or 'unlikely' in the data can cause a security issue.

In your specific situation, there is no reason to transform the data to a comma seperated string, then explode it again into an array. Just add it directly to your final format (most likely a 2-dimensional array if you want to perform multiple queries):

$output = Array();
for( $i = 0; $i < count( $data_a ); $i++ ) {
  $output[] = Array( $data_a[$i], $data_b[$i], $data_d[$i] );
}

/*** var_dump( $output );
   * Array(
   *   Array( 1, 2, 3 ),
   *   Array( 4, 5, 6 ),
   *   Array( 7, 8, 9 ), etc...
   * );
 ***/

foreach( $output as $k => $row ) {
  /*** Do your query
     * $row contains 3 values for this query; next loop it contains the next 3 values
   ***/
}
于 2013-08-10T09:19:22.817 回答