我正在使用预设语句将之前使用mysql_
的脚本转换为 PDO ,无论是否可行。使用旧学校mysql_
,使用mysql_real_escape_string
进行此类动态查询很容易,并将所有查询连接成一个长查询。
似乎PDO的预备声明要困难得多。我在下面这个脚本中对这个动态查询感到不满。
<?php
$filter_day=$_GET['filter_day'];
$filter_month=$_GET['filter_month'];
$filter_year=$_GET['filter_year'];
$search=$_GET['search'];
try{
$db=new PDO("mysql:host=localhost;dbname=dbname;charset=utf8", 'dbuser', 'dbpassword');
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
}catch(PDOException $pe){
die("Could not connect to the database dbname :" . $pe->getMessage());
}
$datecondition='';
if(strlen($filter_day)>0){ $datecondition.=" AND DAY(registration_date)=:filter_day ";}
if(strlen($filter_month)>0){ $datecondition.=" AND MONTH(registration_date)=:filter_month ";}
if(strlen($filter_year)>0){ $datecondition.=" AND YEAR(registration_date)=:filter_year ";}
$searchcondition='';
if(strlen($search)>2){ $searchcondition.=" AND (first_name LIKE :search OR last_name LIKE :search OR department LIKE :search OR position LIKE :search) "; }
$param=array('filter_day'=>$filter_day, 'filter_month'=>$filter_month, 'filter_year'=>$filter_year, 'search'=>"%$search%");
$q=$db->prepare("SELECT * FROM Users WHERE user_status='ENABLED' $datecondition $searchcondition LIMIT 0,30");
$q->execute($param);
?>
:search
参数只会被绑定一次,其余的:search
仍会出现在最终查询中。
SELECT *
FROM Users
WHERE user_status='ENABLED'
AND DAY(registration_date)=:filter_day AND MONTH(registration_date)=:filter_month AND YEAR(registration_date)=:filter_year
AND (first_name LIKE :search OR last_name LIKE :search OR department LIKE :search OR position LIKE :search)
LIMIT 0,30
SELECT *
FROM Users
WHERE user_status='ENABLED'
AND (first_name LIKE :search OR last_name LIKE :search OR department LIKE :search OR position LIKE :search)
LIMIT 0,30
以上查询仅搜索某些字符串,但不过滤任何日期。但是,未使用的:filter_day
:filter_month
和:filter_year
包含在绑定数组中。它无法执行并返回此错误消息:
警告:PDOStatement :: execute()[pdostatement.execute]: SQLSTATE [HY093]:参数号无效:绑定变量数 与令牌数量不匹配
我可能会在代码中添加更多if / elses以逃避这一点,但我意识到只有1个查询才会有太多代码。
这不是最佳的流程/查询,但我不知道如何解决它。请帮我优化它或提供一些例子。非常感谢!