scala正则表达式在sql语句中提取fields子句

时间:2012-10-03 13:08:05

标签: sql regex

我想开发一个简单的函数来替换sql语句中的fields子句

类似这样的事情

replaceFields("select  * from x", "f1")
// should return "select f1 from x"

replaceFields("select top 10 *   FROM x", "f1")
// should return "select top 10 f1   FROM x"

replaceFields("select top 10 f3, f4    FROM x", "f1, f2")
// should return "select top 10 f1, f2    FROM x"

我知道这应该很简单,但我尝试了几个正则表达式,但我似乎无法找到它

"select * from".replaceFirst("""select (\w+) from""", "count(*)")
// returns "select * from"

"select * from".replaceFirst("""select(\b(.*))\bfrom""", "count(*)")
// returns "count(*)"

但它不起作用......

2 个答案:

答案 0 :(得分:1)

您正在替换

select(\b(.*))\bfrom

如果您只想替换selectfrom之间的部分,则不应在要替换的字符串中包含这些部分。尝试

(?<=select\b)(.*?) from

并将其替换为

count(*) from 

编辑:

您似乎想要替换表中的列列表。

假设每个列名都在select语句之后可以找到的TOP之类的关键字列表之后,使用相关参数我创建了这个正则表达式

(([^\s]+,\s+)*([^\s]+)\s+)from

这是基于以下原则:列名(您要替换它)是{em>令牌(允许我这个词)在from之前或者用逗号分隔来自其他代币。

然后以这种方式管理案件

token token, token FROM
      ^this is the starting point of substitution

token FROM
^this is the starting point

用你想要的东西替换第一组,你没事。测试here

答案 1 :(得分:1)

感谢gabber的帮助,以及(不是那么)对正则表达式的挣扎,我找到了这个解决方案:

def replaceFields(sql: String, fields: String): String = {
  val parseSql = """(?imx)                #insensitive case, multiline, whitespaces and comments
    (^ select \s+ #(?:top \s+ \d+ \s+)?)  #m1: select clause and optional clauses
      (?:top \s+ \d+ \s+)?                #  top x clause (ignored match)
      (?:(?:distinct|all) \s+)?           #  distinct | all clause (ignored match)
    )
    (.+?)                                 #m2: the field clause I'm looking for, non greedy to leave spaces to match3
    (\s+ from \s+ .* $)                   #m3: the rest of the sql sentence, greedy spaces
  """.r
  val replace = "$1%s$3".format(fields)   // replace match2 with new fields
  parseSql.replaceFirstIn(sql, replace)
}

给出:

scala> replaceFields("select * from x", "count(*)")
res1: String = select count(*) from x

scala> replaceFields("select top 24 f1, f2 from x", "f3, f4, f5")
res2: String = select top 24 f3, f4, f5 from x

scala> replaceFields("select  f1  from x", " f2,  f3 ")
res3: String = select   f2,  f3   from x

scala> replaceFields("select top 23 distinct f1, f2 from x", "f3, f4, f5")
res0: String = select top 23 distinct f3, f4, f5 from x