我想开发一个简单的函数来替换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(*)"
但它不起作用......
答案 0 :(得分:1)
您正在替换
select(\b(.*))\bfrom
如果您只想替换select
和from
之间的部分,则不应在要替换的字符串中包含这些部分。尝试
(?<=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