2

我想开发一个简单的函数来替换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(*)"

但它没有用......

4

2 回答 2

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
于 2012-10-04T04:08:54.000 回答
1

您正确替换

select(\b(.*))\bfrom

如果您只想替换两者之间的部分,select并且from您不应该在要替换的字符串中包含这些部分。尝试

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

并将其替换为

count(*) from 

编辑:

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

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

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

它基于这样的原则,即列名(您要替换的)是前面的标记(允许我使用这个词),from或者它与其他标记用逗号分隔。

然后以这种方式管理案件

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

token FROM
^this is the starting point

用你想要的替换第一组,你就可以了。在这里测试

于 2012-10-03T13:19:15.937 回答