我有一个小的Web sql编辑器,但当用户写一个查询,如:
SELECT * FROM users;
SELECT * FROM references;| <-- here is the caret, i want to run only this query
SELECT * FROM settings
并提交该字符串,只执行第一个查询。我想只运行用户插入符所在的查询。
显然,该示例看起来很简单,但考虑在真实环境中使用的更真实的查询,例如:
SELECT col1,col2,col3
FROM users
WHERE id IN (1,2,3,4);
SELECT * FROM references WHERE status = 1
;
SELECT
a.col1
, a.col2
, b.col1
FROM table_a a | <--- Here is the caret, run this query
INNER JOIN table_b b ON b.id_table_a = a.id
WHERE a.id = 5
;
UPDATE table_a SET col1 = 'demo' WHERE id = 3;
-- etc, etc, etc
到目前为止,我有插入位置:行和列,并将字符串分为两部分:插入符号之前和插入符号之后。然后我在第一个字符串的最后一个分号出现后得到子字符串,并在第一个出现在第二个字符串之前得到子字符串。
但我想知道是否有其他方法可以更有效地解决这个问题。
尝试这样的正则表达式语句:/(?<=;)(.*)(?=\|)/
您可以使用正则表达式或非正则表达式方法。如果您的查询将包含|
(管道),那么更适合提名不同/唯一标记。
代码:(Demo)
$queries="
SELECT col1,col2,col3
FROM users
WHERE id IN (1,2,3,4);
SELECT * FROM references WHERE status = 1
;
SELECT
a.col1
, a.col2
, b.col1
FROM table_a a | <--- Here is the caret, run this query
INNER JOIN table_b b ON b.id_table_a = a.id
WHERE a.id = 5
;
UPDATE table_a SET col1 = 'demo' WHERE id = 3;
-- etc, etc, etc";
$rtrimmed=substr($queries,0,strpos($queries,'|')); // remove substr following pipe
$ltrimmed=substr($rtrimmed,strrpos($rtrimmed,';')+1); // remove substr upto latest semicolon
echo trim($ltrimmed); // remove whitespace on either side
echo "\n---\n";
echo preg_match('~;\s*\K[^;|]*?(?= *\|)~',$queries,$out) ? $out[0] : '';
输出:
SELECT
a.col1
, a.col2
, b.col1
FROM table_a a
---
SELECT
a.col1
, a.col2
, b.col1
FROM table_a a
模式细分:
~ #pattern delimiter
;\s* #match semicolon followed by zero or more whitespace characters
\K #restart the fullstring match (release previous matched characters)
[^;|]*? #match zero or more (lazily) non-semicolon and non-pipe characters
(?= *\|) #look ahead for zero or more spaces followed by a pipe (so that the output is trimmed)
~ #pattern delimiter