我正在处理包含多个SQL查询的字符串:
ALTER TABLE _version ADD test1 INT NOT NULL;
ALTER TABLE _version ADD test2 INT NOT NULL;
CREATE PROCEDURE test3 ()
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A procedure'
BEGIN
SELECT 'Hello World !';
END;
我希望将此字符串拆分为三个单独查询的数组,如下所示:
ALTER TABLE _version ADD test1 INT NOT NULL;
ALTER TABLE _version ADD test5 INT NOT NULL;
CREATE PROCEDURE test3 ()
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A procedure'
BEGIN
SELECT 'Hello World !';
END;
这将允许我使用PDO进行多个查询。因为不幸(据我所知),您不能使用PDO从一个语句中进行多个事务查询。那,你不能在PDO查询中使用DELIMITER $$
SQL命令。
但是,请注意;
和BEGIN
之间的END
分隔符。这导致了问题!如果我只是使用;
分隔符来爆炸字符串,它就不会正确地分离出过程。
我一直在使用正则表达式来查找BEGIN
和END
之间的所有内容,然后用其他内容替换这些分隔符(例如$$
分隔符) - 然后从$$
分隔符进行爆炸 - 但似乎没有任何工作。
这是对我在PHP和正则表达式中尝试过的一个(坏)的抨击,其中$sqlString
是包含多个查询的字符串:
$sqlString = preg_replace("#(?<!BEGIN.+);(?!.+END)#",'$$',$sqlString);
$splitQueries = explode("$$",$sqlString);
但我不能让负面的前瞻/后视工作。请帮我弄清楚正确的正则表达式或正确的方向!
答案 0 :(得分:2)
免责声明:这完全符合您的要求并在;
之后拆分输入,除非在BEGIN
/ END
语句之间(会因WHERE column = ';'
。
这个PHP语句将完全按照您的要求执行(RegEx demo):
$splitQueries = preg_split('/(?<=;)(?!(?:(?!BEGIN).)*END)/s', $sqlString);
array_pop($splitQueries); // there is an extra value in the array, assuming
// your query ends in ;
首先,我使用了分号的正向lookbehind,这样你就可以使用一个简单的preg_split()
调用(因为它实际上不会匹配;
,而是它后面的空格)。
接下来,我通过否定前瞻跟踪:(?!.*END)
。这是s
修饰符所在的位置,因为它使.
与换行符匹配。
最后,我将否定前瞻中的.*
替换为另一个否定前瞻:(?:(?!BEGIN).)*
。
我们的最终结果是查找分号(技术上紧跟在后面的空格),然后查看每个后续字符(除非我们看到BEGIN
)以确保没有END
(信号)我们在BEGIN
/ END
声明中的事实。有趣!