【问题标题】:How do I extract selected columns given an Oracle SQL String?如何在给定 Oracle SQL 字符串的情况下提取选定的列?
【发布时间】:2013-01-15 04:37:39
【问题描述】:

好的,这似乎太难在这里发布,所以我请你原谅。已经为此工作了将近一周。

我需要提取给定 Oracle SQL 字符串中的所有选定列。它应该通过以下测试用例:

// single column test
select col1 from dual
    // ^ should match "col1"

// multiple column test
select col1,col2 from dual
    // ^ should match "col1", "col2"

// multiple space test
select   col1   ,  col2   from   dual
    // ^ should match "col1", "col2"

// "distinct" tests
select distinct col1 from dual
    // ^ should match "col1"
select distinct col1, col2 from dual
    // ^ should match "col1", "col2"

// "distinct" with whitespaces tests
select   distinct   col1   from   dual
    // ^ should match "col1"
select   distinct   col1  ,  col2  from   dual
    // ^ should match "col1", "col2"

// "as" tests
select col1 from dual
    // ^ should match "col1"
select colA as col1 from dual
    // ^ should match "col1"
select colA as col1, col2, col3 from dual
    // ^ should match "col1", "col2", "col3"
select col1, colB as col2, col3 from dual
    // ^ should match "col1", "col2", "col3"
select col1, col2, colC as col3 from dual
    // ^ should match "col1", "col2", "col3"

// "as" tests with whitespaces tests
select    colA    as    col1,    colB    as    col2,    colC    as    col3    from    dual
    // ^ should match "col1", "col2", "col3"


// "distinct" with "as" tests
select distinct colA as col1 from dual
    // ^ should match "col1"
select distinct colA as col1, colB as col2, col3 from dual
    // ^ should match "col1", "col2", "col3"
select distinct colA as col1, col2, colC as col3 from dual
    // ^ should match "col1", "col2", "col3"


// function test
select funct('1','2') as col1 from dual
    // ^ should match "col1"
select col1, funct('1','2') as col2 from dual
    // ^ should match "col1", "col2"
select col1, colB as col2, funct('1','2') as col3 from dual
    // ^ should match "col1", "col2", "col3"

我在 Java 中尝试了以下 RegEx

 ((?<=select\ )(?!distinct\ ).*?(?=,|from))
 ((?<=select\ distinct\ ).*?(?=,|from))
 ((?<=as\ ).*?(?=,|from))
 ((?<=,\ ).*?(?=,|from))(?!.*\ as\ ) // <- Right, I'm guessing here

将它们组合在一起,但我不能简单地通过上面的所有测试用例。 (我正在使用这个tool 来验证我的正则表达式)。

我尝试搜索 SQL 评估器,但找不到任何可以提取所有列而不针对真实数据库执行它并且假定所有引用的表和函数都存在的评估器。

一个 Java ReGex,一个可以通过测试的免费 SQL 评估器(不需要真正的数据库),或者任何更好的东西,这两个是可以接受的答案。假设 SQL 始终为 Oracle 11g 格式。

【问题讨论】:

  • Oracle llg 格式不也包括tablename.columnname 的结构并使用引号使列名带有空格,还是您知道您的select 语句具有更受约束的语法?
  • 是的,我知道它应该比给定的测试多。我只是把它放在那里,让我知道我打算做什么。我猜如果有人可以提供一个通过这些测试用例的正则表达式,我可能会从中得出解决方案,以通过这里未指定的所有剩余测试用例。

标签: java sql regex evaluation


【解决方案1】:

鉴于 Oracle SELECT 列表可能会变得非常复杂(必须考虑您提到的所有情况,加上子查询、tablename.columnname 结构、引用的别名等),您可能想要超越正则表达式并实际解析然后 SQL 查询将标记从解析的输出中提取出来。

为此,您有几个不同的选择,但都不是那么容易,但也许能够解决您的问题

  • 如果你愿意使用 Perl,你可以让SQL::Parser 做你想做的事。
  • 如果您想要一个基于 Java 的解决方案,您可以获得 90 次免费试用下载 gsqlparser,如果这是一个一次性项目,这将很有帮助。
  • 有这个 - SQL92 parser,它是免费下载的,但许可证未知,我不完全确定它是否可以处理任何特定于 Oracle 的怪事。
  • 您可以使用 Antlr 生成一个带有基于 this guy's work 的 java 接口的 SQL 解析器,该接口基于 CREATE TABLE 语法,但可以很容易地适应处理 SELECT 语法(或者您可以搜索 antlr sql grammar 并找到一个预制一个很容易)

【讨论】:

  • 我想这是我可能得到的最佳答案。我在想一个接受 Oracle SQL 的 JDBC 驱动程序,它可以在没有真正的数据库连接的情况下执行 SQL 并返回一个 ResutlSet。从那里我可能会得到所有的列名。我搜索了一下,发现 Hibernate 正在使用 ANTLR。也许我应该在那里碰碰运气。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-30
  • 1970-01-01
  • 2019-12-07
  • 1970-01-01
  • 2021-01-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多