Oracle SQL分析器

gpnt7bae  于 2023-10-16  发布在  Oracle
关注(0)|答案(9)|浏览(142)

对于我目前的项目,我需要一个SQL解析器,解析Oracle SQL语句。目前我一直在使用jsqlparser,它对于简单的查询很好用。但是,当特定功能发生时(例如,cast()或(+))解析器失败。
有人能建议一个完全符合Oracle SQL的解析器吗?
最好的,威尔

35g0bw71

35g0bw711#

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

  • 我使用了Andrey Kharitonkin的 “Oracle PL/SQL Grammar for ANTLR v3”;从内存上看,它支持8i时代的大多数SQL和PL/SQL语法,只有一些出现在9 i和10 g中的片段
  • 帕特里克Higgins的 “PL/SQL” 语法较新,并声称支持大多数11 g语法,但它似乎只包含大多数DML语句-如果您对SQL特别感兴趣,则不太有用
hl0ma9xz

hl0ma9xz2#

在解决了同样的问题后,我设法让一个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解析器(暗示的原因是这是一项非常有价值的技术,不会出售或许可)。
  • 虽然这更像是一个黑客而不是一个解决方案,但我意识到它可能对某些情况有用(不是我的)。我认为在真实的生活场景中使用它可能从技术和法律的Angular 都有很高的风险。

我发布这个答案的原因是为了引起社区的注意,让他们知道拥有一个Oracle SQL解析器是完全可行的,也许有一天Oracle会考虑将解析器作为一个竞争优势(我相信有用户会很乐意支付一些费用来获得许可证)。

k5hmc34c

k5hmc34c3#

为什么不使用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个字符,但是你可以将varchar 2的pl/sql数组输入到dbms_sql.parse函数中,这样做可以让你解析难以想象大小的sql。

ve7v8dk2

ve7v8dk24#

你有没有考虑过General SQL Parser?我自己没有任何经验,但浏览他们的网站,它有潜力。就我个人而言,我已经在Eclipse Data Tools Platform中的解析器上推出了自己的构建(对不起,我不能分享,它是专有的),但现在我将不得不评估我上面链接的那个,因为它声称比我的解析器覆盖了更多的Oracle SQL。

ryhaxcpt

ryhaxcpt5#

鉴于Oracle公司无法保持SQL和PL/SQL VM的SQL解析器同步,当两者具有不同的SQL解析器时,第三方不太可能能够创建“完全兼容”的解析器。
您试图从查询中提取哪些数据?Oracle数据库本身可能具有其他功能,允许您在不首先解析查询的情况下提取该信息。

ee7vknir

ee7vknir6#

我们的DMS Software Reengineering Toolkit可以通过Oracle PLSQL解析器或SQL 2011解析器获得。DMS提供了一个解析器,构建了一个AST,允许您任意地调查/转换树,如果您想这样做,还可以将AST重新生成为源代码。
您可以通过从网站下载PLSQL格式化程序来测试解析器;使用相同的基础DMS机制;只是不分析/转换树。
您可能需要将SQL语句 Package 在一个简单的PLSQL过程中。

qhhrdooz

qhhrdooz7#

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

vh0rcniy

vh0rcniy8#

jOOQ有一个内置的parser,可以通过任何支持的数据库产品(包括Oracle SQL)解析大量SQL。它不能解析 * 所有 *,但它可能足以满足大多数用例。例如,它可以解析Oracle外部连接运算符(+)甚至transform that to ANSI SQLA parser and translator demo can be seen here,例如:

-- Input
SELECT *
FROM t, u
WHERE t.id = u.id(+)

-- Output
SELECT *
FROM t
  LEFT OUTER JOIN u
    ON t.id = u.id

您可以使用websiteas a CLI中的解析器,或者使用Java、Kotlin、Scala等编程:

Select<?> select = ctx.parser().parseSelect(
    """
    SELECT *
    FROM t, u
    WHERE t.id = u.id(+)
    """
);

解析输出是普通的jOOQ API,您可以使用jOOQ的model API将其转换为其他SQL

3z6pesqy

3z6pesqy9#

FlowHigh附带了一个SQL解析器,它支持Oracle SQL方言,包括非ANSI连接。您可以使用UI或使用Python SDK以编程方式访问它以实现自动化。
作为输入,您给它给予一个SQL语句,作为输出,它生成一个JSON或XML消息。
SDK还附带了一系列抽象,以满足常见用例,例如。给予我所有的表,连接,列,过滤器等。在查询中
它可以用于静态代码分析,以检测错误的SQL和SQL反模式,如自连接,SELECT * 等。
下面是一篇Medium博客文章,详细描述了https://medium.com/@sonradata/parsing-oracle-sql-with-flowhigh-e366dae23920
免责声明:我为Sonra工作

相关问题