适用于Oracle SQL的解析器

时间:2011-04-20 19:48:10

标签: sql oracle parsing

对于我当前的项目,我需要一个解析Oracle SQL语句的SQL解析器。 目前我一直在使用jsqlparser,它适用于简单查询。但是当特定函数发生时(例如cast()或(+)),解析器失败。

有人建议完全符合Oracle SQL的解析器吗?

最佳, 将

7 个答案:

答案 0 :(得分:10)

ANTLR(v3v4)解析器生成器已经为它编写了许多Oracle SQL和PL / SQL语法;有关详细信息,请参阅grammar list(v3)。其中:

  • 我使用了Andrey Kharitonkin的“用于ANTLR v3的Oracle PL / SQL语法”;从内存中它支持8i时代的大多数SQL和PL / SQL语法,在9i和10g中出现了一些零碎的部分
  • Patrick Higgins的“PL / SQL”语法更新,并声称支持大多数11g语法,但它似乎只是吞下大多数DML语句 - 如果你对SQL特别感兴趣,那么它就没有用了

答案 1 :(得分:7)

在处理同样的问题之后,我设法让SQL解析器正常工作:

我的代码如下所示:

import oracle.jdeveloper.db.DatabaseConnections;
import oracle.javatools.db.sql.SQLQueryBuilder;
import oracle.javatools.db.Database;
...
// load the database connections
// this is specific to Oracle SQL developer
DatabaseConnections connections = DatabaseConnections.getPrivateInstance(
    (new File("src/test/resources/connection.xml")).toURI().toURL(),
    "somePassword");
// get the one we are interested in
Database database = connections.getDatabase("the-name-of-a-sqldeveloper-connection");
SQLQueryBuilder queryBuilder = SQLQueryBuilderFactory.createBuilder(
      database, new Schema("OPTIONAL_SCHEMA"), "select * from some_table");

实现这一目标的挑战是:

  • 获取Oracle SQL Developer是一项挑战。为此,您需要破解Oracle SQL Developer创建的文件以保持这些连接;上例中的 connection.xml 看起来像这样:
<?xml version = '1.0' encoding = 'UTF-8'?>
<References xmlns="http://xmlns.oracle.com/adf/jndi">
   <Reference name="the-name-of-a-sqldeveloper-connection"     className="oracle.jdeveloper.db.adapter.DatabaseProvider" xmlns="">
      <Factory      className="oracle.jdevimpl.db.adapter.DatabaseProviderFactory1212"/>
  <RefAddresses>
     <StringRefAddr addrType="password">
        <Contents>HSx10FtlsPc=</Contents>
     </StringRefAddr>
     <StringRefAddr addrType="oraDriverType">
        <Contents>thin</Contents>
     </StringRefAddr>
...

要获得这样的文件,您需要深入了解存储Oracle SQL Developer设置的文件夹,然后将该内容复制粘贴到您自己的文件中。

现在,假设你设法在这里做到这一点是问题和我最终解决方案感到失望的要点:

  • 构建器中的API很不错,但解析将执行查询执行(这可能是一个大问题 - 在我的情况下,我需要解析速度很快)。
  • API 未正式公开。我没有能够在这里引用准确的措辞,我得到了一个Oracle答案,声称没有官方支持的Oracle解析器(其中提到的原因是这是一种非常有价值的技术,不会被出售或许可)。
  • 虽然这更像是一个黑客而不是解决方案,但我意识到它可能对某些情况有用(不是我的)。我认为,从技术和法律的角度来看,在现实生活中使用它可能存在很大的风险。

我发布这个答案的原因是为了让社区注意这样一个事实,即拥有 Oracle SQL解析器是完全可行的,也许有一天Oracle会考虑将解析器暴露为竞争优势(我是确定有用户可以高兴地支付一些费用来获得许可证。

答案 2 :(得分:4)

您考虑过General SQL Parser了吗?我自己没有任何经验,但浏览他们的网站有潜力。就个人而言,我已经在Eclipse Data Tools Platform中使用解析器构建了自己的内容(抱歉,我无法共享,它是专有的),但现在我将不得不评估我上面链接的那个,因为它声称对Oracle SQL的覆盖范围比我的解析器。

答案 3 :(得分:4)

鉴于当两者具有不同的SQL解析器时,Oracle公司无法保持SQL和PL / SQL VM的SQL解析器同步,因此第三方不太可能创建“完全兼容”的解析器。

您尝试从查询中提取哪些数据? Oracle数据库本身可能还有其他工具可以在不解析查询的情况下提取该信息。

答案 4 :(得分:4)

请问,为什么不使用Oracle解析器?

create global temporary table plans as select * from table(dbms_xplan.display_cursor());
--/
declare
c number;
i varchar2(30);
l number;
stmt varchar2(4000);
begin
delete from plans;
stmt:= 'select z.* from z,skew1 where z.z = skew1.fillblocks';
l:= length(stmt);
c:=dbms_sql.open_cursor();
dbms_sql.parse (c, stmt,dbms_sql.native);
select distinct sql_id into i from v$open_cursor where sid in (select sid from v$mystat) and substr(sql_text,1,l) = substr(stmt,1,l);
insert into plans select * from table(dbms_xplan.display_cursor(i));
dbms_output.put_Line ('sql_id:'||i);
end;
/
select * from plans;

PLAN_TABLE_OUTPUT                                                             
----------------------------------------------------------------------------  
SQL_ID  97qc3ynmw1pa4, child number 0                                         
-------------------------------------                                         
select z.* from z,skew1 where z.z = skew1.fillblocks                          

Plan hash value: 942457544                                                    

----------------------------------------------------------------------------  
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |  
----------------------------------------------------------------------------  
|   0 | SELECT STATEMENT   |       |       |       |    85 (100)|          |  
|*  1 |  HASH JOIN         |       |     1 |   410 |    85   (2)| 00:00:02 |  
|   2 |   TABLE ACCESS FULL| Z     |     1 |     9 |     2   (0)| 00:00:01 |  
|   3 |   TABLE ACCESS FULL| SKEW1 |  6000 |  2349K|    82   (0)| 00:00:01 |  
----------------------------------------------------------------------------  

Predicate Information (identified by operation id):                           
---------------------------------------------------                           

   1 - access("Z"."Z"=INTERNAL_FUNCTION("SKEW1"."FILLBLOCKS"))   

您确实需要oracle数据库连接。如果输出是您想要的,那么它是获得您想要的最简单的方法,而无需为车轮重新发明其他颜色。在这个例子中,我将sql限制为4000个字符,但你可以将一个pl / sql数组的varchar2输入到dbms_sql.parse函数中,这样做可以解析sql的难以想象的大小。

答案 5 :(得分:2)

我们的DMS Software Reengineering Toolkit可以通过Oracle PLSQL解析器或SQL 2011解析器获得。 DMS提供了一个解析器,构建了一个AST,让你可以任意调查/转换树,如果你想这样做,可以重新生成AST作为源代码。

您可以通过下载网站上提供的PLSQL格式化程序来测试解析器;使用相同的底层DMS机制;只是不分析/转换树。

您可能需要将SQL语句包装在一个简单的PLSQL过程中。

答案 6 :(得分:1)

试试这个http://www.ibrezina.net/OracleSQL.tgz。这是Oracle PL / SQL的ANTLR3.3语法。语法适用于C目标,但可以很容易地转换为Java或C#。您的任务,查询中包含的表列表已作为示例包含在内。