Php 将多个SQL语句拆分为单个SQL语句
介绍说明:我希望有一个库或例程可以做到这一点,但我还没有找到类似的东西。我真的在寻找方向和建议,从哪里开始 情况如下: 我有一个以纯文本形式出现的SQL命令块。它可能是一个SQL命令或多个SQL命令。我需要一种方法来拆分多个SQL命令,以便一次运行一个。Microsoft SQL Management Studio确实具有这种开箱即用的行为 我试图将此功能添加到在Apache(Debian)上运行的PHP5/MySQL5应用程序中 一些要点:Php 将多个SQL语句拆分为单个SQL语句,php,sql,mysql,Php,Sql,Mysql,介绍说明:我希望有一个库或例程可以做到这一点,但我还没有找到类似的东西。我真的在寻找方向和建议,从哪里开始 情况如下: 我有一个以纯文本形式出现的SQL命令块。它可能是一个SQL命令或多个SQL命令。我需要一种方法来拆分多个SQL命令,以便一次运行一个。Microsoft SQL Management Studio确实具有这种开箱即用的行为 我试图将此功能添加到在Apache(Debian)上运行的PHP5/MySQL5应用程序中 一些要点: 我真的需要一次运行一个。真的 我不想要求用户在每条S
select sMessage,
(
SELECT COUNT(sTag) FROM Tags WHERE ixTicket = note.ixTicket
) FROM note
select * from ticket
WHERE (SELECT MAX(nCount) FROM Counter WHERE ixTicket = ticket.ixTicket) > 5
我尝试了一些正则表达式的尝试,但似乎还不够强大
关于解决这个问题的方法有什么建议吗?你最好的办法是要求用户在语句之间放置某种类型的除虫剂。例如:要求每个语句都用一行只包含GO或“\”一词的行来表示,或者在每个语句的末尾加一个“;”
通过这种方式,您可以轻松地将单个字符串拆分为单独的SQL语句。也许可以尝试使用此库。我过去曾成功地将其用于解析sql 如果不希望用户输入分隔符,如“;”或者其他任何事情,您将需要自己解析输入,并有逻辑来确定语句的开始位置
您的逻辑将需要处理明显的查询起始关键字“选择”、“更新”、“插入”、“删除”并前进到下一个关键字(或输入结束)。您是否尝试过使用关键字“选择”、“更新”、“插入”和“删除”并计算开始括号(“和结束括号”)的数量
这将允许您确定避免嵌套的SELECT语句,并找到语句的正确结尾。您需要分号分隔符。从技术上讲,没有它,SQL语句是完全无效的;任何忽略它的人都在编写格式错误的SQL。要求使用分号可以以标准化的方式解决所有问题,并使软件易于编写 可能需要执行以下操作:如果用户输入的查询不包含一个或多个分号(当然,在引号之外),请在末尾添加一个分号,并将其作为单个查询运行。否则,以分号分隔输入的查询,并单独运行每个查询,如果省略,可能会在最终查询的末尾加上分号
此解决方案易于编写,符合SQL标准,而且简单易行。不需要分隔符肯定会导致疯狂。我想你可以自己解析它。查找关键字SELECT、DELETE、UPDATE、INSERT、EXEC等 在解析过程中,如果遇到一个“(”增量a计数器:nest_level++ 如果遇到“)”减量嵌套单元级别-- 然后,当您遇到一个关键字,并且nest_level==0时,就进入下一个语句 你还必须处理像这样的案件
INSERT ...
SELECT ....
因此,对于插入,您必须查找SELECT或VALUES
毫无疑问,还有其他情况
同意奎因的说法,你只需要分号。我不认为这有什么“不酷”的地方。我不确定这是否可能。您当然需要深入了解目标DBMS的SQL语法。例如,在我脑海中,这是一条MySQL语句:
INSERT INTO things
SELECT * FROM otherthings ON DUPLICATE KEY
UPDATE thingness=thingness+1
在某些DBMS中,如果没有分隔符,很可能存在不明确的结构
我不想要求用户在每条SQL语句后输入分号
我想你可能是被迫的。这完全是划分SQL语句的标准方法。即使您可以找到一种启发式方法来检测SQL语句点的起始点,您也可能会遇到灾难,比如意外的“从事物中删除”——而不带WHERE子句
SQL语句可以在一行或多行上,所以我不能在LBs/CRs上换行
可以接受新语句的双换行符吗
我尝试了一些正则表达式的尝试,但似乎还不够强大
不,即使使用分号分隔符,正则表达式也远远不够强大,无法解析SQL。问题点包括:
';'
";"
`;`
'\';'
''';'
-- ;
#;
/*;*/
以及这些结构的任何插入。哎呀 要在定期引发问题的讨论中添加一个怪癖:
DECLARE c CURSOR FOR
SELECT * FROM SomeWhere ...
FOR UPDATE
后续的更新往往会使特别的解析器无所适从。很可能您不必担心这一点,因为首先不允许使用DECLARE符号(实际上是嵌入式SQL,而不是普通SQL)。但是FOR UPDATE子句可能会出现在SQL的某些方言中,即使它不在DECLARE语句中,所以要小心。可能与以下Java Regexp一起出现?检查测试
@Test
public void testRegexp() {
String s = //
"SELECT 'hello;world' \n" + //
"FROM DUAL; \n" + //
"\n" + //
"SELECT 'hello;world' \n" + //
"FROM DUAL; \n" + //
"\n";
String regexp = "([^;]*?('.*?')?)*?;\\s*";
assertEquals("<statement><statement>", s.replaceAll(regexp, "<statement>"));
}
@测试
公共void testRegexp(){
字符串s=//
“选择‘hello;world’\n”+//
“来自双路;\n”+//
“\n”+//
“选择‘hello;world’\n”+//
“来自双路;\n”+//
“\n”;
字符串regexp=“([^;]*?('.*?)?)*?;\\s*”;
assertEquals(“,s.replaceAll(regexp)”);
}
$sMultiQuery='显示表格;从“测试”中选择*;
$aQueries=array();
如果(preg_match_all('/([^;]*?(\'.*?'))(“*?”)*?(;\s*.\s*$)/',$sMultiQuery,$aMatches))
{
$aQueries=$aMatches[0];
}
其他的
{
$aQueries=array($sMultiQuery);
}
foreach($aQue)
$sMultiQuery = 'SHOW TABLES; SELECT * FROM `test`';
$aQueries = array();
if ( preg_match_all('/([^;]*?((\'.*?\')|(".*?"))?)*?(;\s*|\s*$)/', $sMultiQuery, $aMatches) )
{
$aQueries = $aMatches[0];
}
else
{
$aQueries = array($sMultiQuery);
}
foreach ( $aQueries as $sQuery )
{
# Do your thing
}