代码之家  ›  专栏  ›  技术社区  ›  Dustin

使用REGEX在查询中获取别名列

  •  2
  • Dustin  · 技术社区  · 6 年前

    我已经到处搜索,真的很难找到合适的正则表达式来帮助我找回我想要的东西。假设我有以下查询字符串:

    SELECT col, col2 AS c2, col3, col * col2 calc FROM...
    

    我想要一个正则表达式,它可以在逗号之间提取所有内容,其中有空格或“AS”表示列别名。它还应排除SELECT和FROM。对于上面的示例,我需要以下匹配:

    col2 AS c2
    col * col2 calc
    

    本质上,这应该删除col和col3,因为它们没有别名。我尝试了以下变体,但没有成功(注意:$colname包含别名):

    /(SELECT|,)([^,]*{$colname}[^,]*)(FROM|,)/
    

    目前仅返回:

    , col2 AS c2,
    col2 AS c2
    , col2 AS c2,
    col2 AS c2
    

    我觉得我很接近,但我需要一些指导。欢迎提出任何建议。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Wiktor Stribiżew    6 年前

    几乎不可能用一个正则表达式来处理SQL字符串解析,您应该寻找一种更通用的解决方案,如 PHP-SQL-Parser .

    我提出的正则表达式是一种特殊的解决方法,可以进一步细化、调整等,以满足特定项目的需要:

    (?:\G(?!\A),|SELECT)(?:\s+[^\s,]+(?:\([^()]*\))?,)*\s*\K[^\s,]+\s*(?:(?![()',])[[:punct:]]|AS)\s*(?:(?!FROM)[^,])*(?!\w)
    

    请参见 regex demo .

    它的作用如下:

    • (?:\G(?!\A),|SELECT) -上一次成功匹配的结尾和后面的逗号( \G(?!\A), )或( | )文字 SELECT 子字符串
    • (?:\s+[^\s,]+(?:\([^()]*\))?,)* -零个或多个序列( (?:...)* )其中:
      • \s+ -1+空格
      • [^\s,]+ -除空格和逗号以外的1+个字符
      • (?:\([^()]*\))? -可选的子字符串,如 (...) (a) ( ,则0个以上字符 ( ) ,然后是 ) )
      • , -逗号
    • \s* -0+空格字符
    • \K -匹配重置操作符丢弃迄今为止匹配的文本(到目前为止, SELECT abc, Contains(...), 将从比赛中删除,但比赛将需要)
    • [^\s,]+ -除空格和 ,
    • \s* -0+空格字符
    • (?:(?![()',])[[:punct:]]|AS) -要么
      • (?![()',])[[:punct:]] -任何标点或符号char,但a ( , ) , ' ,
      • | -或
      • AS -文字 作为 子字符串
    • \s* -0多个空格
    • (?:(?!FROM)[^,])* -除逗号以外的零个或多个字符不以 FROM 字符序列(它是 tempered greedy token )
    • (?!\w) -未后跟单词char。