我得到了一些由我的脚本动态构建的查询。它们通常适合以下模板:
SELECT ...
FROM ...
JOIN ...
WHERE ... (lots of filters, search conditions, etc. here) ...
ORDER BY (optional) ...
LIMIT (optional) ... OFFSET (optional)
我想从查询中删除限制和偏移部分。我用了
$sql_entitati = implode("LIMIT", explode("LIMIT", $sql_entitati, -1));
这样做,但后来它击中了我:如果查询中没有 LIMIT 怎么办,如果唯一的 LIMIT 在 where 子句中的某个地方怎么办?
所以我要问你的问题是:如果没有 LIMIT 和/或 where 子句中的某个地方有"限制",我如何安全地删除 LIMIT 关键字之后的所有内容而不会搞砸它?所有这些都是在 php 中完成的。
为清楚起见,进行了一些编辑:
我使用的算法:
$sql = implode("LIMIT", explode("LIMIT", $sql, -1));
将适用于 99% 的案例。当末尾缺少"LIMIT"关键字,并且在条件中的某处写有"LIMIT"时,就会出现问题。例如:
SELECT * FROM table WHERE bla = 'SPEED LIMIT' ORDER BY table.a
这是我需要解决的问题。
使用以下算法解决(归功于techfoobar):
$p = strrpos($sql, "LIMIT");
if($p !== false) {
$q = strpos($sql, ")", $p);
$r = strpos($sql, "'", $p);
$s = strpos($sql, "'"", $p);
if($q === false && $r === false && $s === false)
$sql = substr($sql, 0, $p);
}
你应该做这样的事情:
- 获取最后一个"LIMIT"的位置 - 将此位置存储在
p
- 确保在
p
之后没有")"
字符 - 如果是这样,它是条件等内部查询的一部分。 - 确保
p
后没有"'"
字符 - 如果是,则它是某些用户输入字符串的一部分 - 如果步骤 2 和 3 已通过,请在
p
后剥离所有内容
更多提示:
- 对于步骤 1 - 使用
strrpos
表示最后一次出现LIMIT
- 对于步骤 2 和 3,请使用带有
p
的strpos
作为搜索开始偏移量 - 对于步骤 4,使用
substr
剥离p
后的所有内容
获取 LIMIT 的位置,使用 !==FALSE 然后子字符串检查它是否存在。
$str = "SELECT X FROM Y JOIN WHERE CONDITIONS ORDER BY ORDERS LIMIT OFFSET";
$pos = strrpos($str,"LIMIT");
if ($pos!==false)
{
$newStr = substr($str,0,$pos);
echo $newStr;
}
试试这个 aproach
$query = '';
$query .= 'SELECT...';
$query .= 'FROM ...';
$query .= 'JOIN ...';
$query .= 'WHERE...';
if ($limit)
{
$query .= " LIMIT $limit";
}
这可能会帮助你...
$str = " SELECT * FROM table WHERE bla = 'SPEED LIMIT' ORDER BY table.a";
$pos = strrpos($str,"LIMIT");
if ($pos!==false)
{
$ok = 1;
if(substr_count($str, '"', $pos) % 2 != 0)
{
$ok = 0;
}
if(substr_count($str, "'", $pos) % 2 != 0)
{
$ok = 0;
}
if(substr_count($str, ")", $pos) > 0)
{
$ok = 0;
}
if($ok == 1)
$str = substr($str,0,$pos);
}
echo $str;