我正在处理一个包含多个 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);
但是我无法让负面的前瞻/后顾工作发挥作用。请帮助我找出正确的正则表达式模式或正确的方向!
最佳答案
免责声明:这只是按照您的要求进行操作,并在 ;
之后分割输入,除非在 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 ;
首先,我对分号使用了正向后查找,这样您就可以只使用一个简单的 preg_split()
调用(因为它实际上不会匹配 ;
,而是匹配它后面的空格)。
接下来,我接着进行否定前瞻:(?!.*END)
。这是需要 s
修饰符的地方,因为它使 .
匹配换行符。
最后,我将否定前瞻中的 .*
替换为另一个否定前瞻:(?:(?!BEGIN).)*
.
我们的最终结果会查找分号(从技术上讲,是分号后面的空格),然后查看后面的每个字符(除非我们看到 BEGIN
),以确保没有 END
(表明我们处于 BEGIN
/END
语句内)。有趣!
关于php - 用于正确分割嵌套 SQL 分隔符的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32149059/