Php 将多个SQL语句拆分为单个SQL语句

Php 将多个SQL语句拆分为单个SQL语句,php,sql,mysql,Php,Sql,Mysql,介绍说明:我希望有一个库或例程可以做到这一点,但我还没有找到类似的东西。我真的在寻找方向和建议,从哪里开始 情况如下: 我有一个以纯文本形式出现的SQL命令块。它可能是一个SQL命令或多个SQL命令。我需要一种方法来拆分多个SQL命令,以便一次运行一个。Microsoft SQL Management Studio确实具有这种开箱即用的行为 我试图将此功能添加到在Apache(Debian)上运行的PHP5/MySQL5应用程序中 一些要点: 我真的需要一次运行一个。真的 我不想要求用户在每条S

介绍说明:我希望有一个库或例程可以做到这一点,但我还没有找到类似的东西。我真的在寻找方向和建议,从哪里开始

情况如下: 我有一个以纯文本形式出现的SQL命令块。它可能是一个SQL命令或多个SQL命令。我需要一种方法来拆分多个SQL命令,以便一次运行一个。Microsoft SQL Management Studio确实具有这种开箱即用的行为

我试图将此功能添加到在Apache(Debian)上运行的PHP5/MySQL5应用程序中

一些要点:

  • 我真的需要一次运行一个。真的
  • 我不想要求用户在每条SQL语句后输入分号
  • SQL语句可以在一行或多行上,所以我不能在LBs/CRs上换行
  • 它至少需要支持选择、更新、插入、删除
  • 它需要支持子选择的查询
  • 整洁的选项卡式SQL需要工作
  • (为了便于使用软件)我不想强制用户输入任何类型的分隔符
  • 下面是一个SQL示例块,我需要将其拆分为两条语句:

    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 }