我必须根据某些条件构建查询。有没有比我在下面做的更好的方式呢?它工作正常,但是如果有更多的条件,我可以看到它相当快地失控,因为我检查每次检查新的条件是否满足任何先前的条件。
$sql = "SELECT DISTINCT fkRespondentID FROM tblRespondentDayTime";
if (!empty($day) || !empty($time) || !empty($sportID)) {
$sql .= " WHERE";
if (!empty($day)) {
$sql .= " fldDay='$day'";
}
if (!empty($time)) {
if (!empty($day)) {
$sql .= " AND";
}
$sql .= " fldTime='$time'";
}
if (!empty($sportID)) {
if (!empty($day) || !empty($time)) {
$sql .= " AND";
}
$sql .= " fkRespondentID IN (SELECT fkRespondentID FROM tblRespondentSport WHERE fkSportID='$sportID')";
}
}
答案 0 :(得分:6)
我会使用旧的"WHERE 1=1"
技巧;将此作为第一个条件添加,然后您可以对随后的每个语句采用“AND”条件。
答案 1 :(得分:4)
$sql = "SELECT DISTINCT fkRespondentID FROM tblRespondentDayTime WHERE 1=1";
if (!empty($day))
$sql .= "AND fldDay='$day'";
if (!empty($time)) {
$sql .= "AND fldTime='$time'";
if (!empty($sportID))
$sql .= "AND fkRespondentID IN (SELECT fkRespondentID FROM tblRespondentSport WHERE fkSportID='$sportID')";
答案 2 :(得分:1)
构建条件列表/数组,其中每个条件都是可选的(即如果条件有效,则将其推送到列表中)。
如果此列表是> 0,添加“where”,然后添加“and”加入的列表。
答案 3 :(得分:1)
您可以创建一个if (!empty($day) || !empty($time))
变量并像这样检查,而不是像$whereClause
这样的检查:
$sql = "SELECT DISTINCT fkRespondentID
FROM tblRespondentDayTime";
$whereClause = '';
// fldDay
if (!empty($day)) {
$whereClause .= " fldDay='$day'";
}
// fldTime
if (!empty($time)) {
if (!empty($whereClause)) {
$whereClause .= ' AND ';
}
$whereClause .= " fldTime='$time'";
}
// fkRespondentID
if (!empty($sportID)) {
if (!empty($whereClause)) {
$whereClause .= ' AND ';
}
$whereClause .= " fkRespondentID IN (SELECT fkRespondentID
FROM tblRespondentSport
WHERE fkSportID='$sportID')";
}
if (!empty($whereClause)) {
$whereClause = ' WHERE '.$whereClause;
}
$sql .= $whereClause;
如果您需要将某些更改为OR
(1 = 1技巧在这种情况下不起作用,甚至可能证明非常危险),这也会有效。
答案 4 :(得分:0)
您可以尝试将变量放在一个数组中,并使用一个布尔值来告诉您是否需要在下一个短语之前添加“AND”。这会将您的控制语句缩短为foreach和嵌套if。
答案 5 :(得分:0)
这是我的解决方案:
$sql = "SELECT * FROM table";
$conditions = array(
'fldDay' => $day,
'fldTime' => $time,
);
if (count(array_filter($conditions))) {
$sql .= ' WHERE ';
$sql .= implode(' AND ', array_map(function($field, $value) {
return $field . '=\'' . pg_escape_string($value) . '\'';
}, array_keys($conditions), $conditions));
}
请注意,由于关闭,这在PHP 5.3下无效。如果您使用较旧的PHP,请将闭包作为单独的函数使用,或者将其替换为foreach
。
答案 6 :(得分:0)
不幸的是,构建动态SQL是一种乏味的体验,即使你可以在你的逻辑中改变一些东西(实际上看起来相当干净),它仍然会很难看。
幸运的是,Object-relational mapping存在。我不太熟悉PHP,但是Perl有几个CPAN模块,比如SQL :: Abstract,它允许你使用基本数据结构构建相当复杂的SQL语句。
答案 7 :(得分:0)
如果您使用存储过程,则可以执行以下操作:
CREATE PROCEDURE `FindRespondents` (
IN `_day` varchar(255),
...
)
BEGIN
SELECT DISTINCT fkRespondentID
FROM tblRespondentDayTime
WHERE (_day Is Null OR fldDay = _day)
AND ...
END;
|
传递null
_day
表示任何fldDay
都可以。 _day
的任何其他值,必须匹配。我假设fldDay
是文本,但当然你可以在这里正确输入所有内容。
我知道有些人不是存储过程的粉丝,但它可以通过这种方式方便地封装查询逻辑。