2015-08-21 77 views
2

我處理一個包含多個SQL查詢字符串:正則表達式正確裂開嵌套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查詢中使用SQL命令DELIMITER $$

但是,請注意BEGINEND之間的;分隔符。這會導致問題!如果我只是使用;定界符來爆炸字符串,它將不會正確分離程序。

我一直在使用正則表達式瞎搞找到不是一個BEGINEND之間的一切,然後用別的東西(如$$分隔符)取代那些分隔符 - 然後執行爆炸關閉$$分隔符 - - 但似乎沒有任何工作。

這裏是什麼我在PHP和正則表達式,其中$sqlString是字符串與多個查詢到目前爲止已經試過一(壞)刺:

$sqlString = preg_replace("#(?<!BEGIN.+);(?!.+END)#",'$$',$sqlString); 
$splitQueries = explode("$$",$sqlString); 

但我不能讓消極look-前方/後方工作。請幫助我找出正確的正則表達式模式或正確的方向!

回答

2

免責聲明:這只是做了你問什麼和;後會把輸入的,除非陳述BEGINEND之間/(它將無法在像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聲明)。有趣!

+0

哇,這正是我需要的!我只是測試它,它的工作原理。謝謝! –

+0

沒問題!希望這個解釋已經足夠清楚了 - 通過使用lookaround你已經走上了正確的軌道,這只是一個複雜的過程;) – Sam