programing

Oracle SQL용 파서

javajsp 2023. 6. 23. 21:45

Oracle SQL용 파서

현재 프로젝트의 경우 Oracle SQL 문을 구문 분석하는 SQL 파서가 필요합니다.현재 저는 간단한 쿼리에 잘 맞는 jsqlparser를 사용하고 있습니다.그러나 특정 기능(예: 캐스트() 또는 (+))이 발생하면 파서가 실패합니다.

오라클 SQL을 완벽하게 준수하는 파서를 제안할 수 있는 사람이 있습니까?

최고야, 윌

ANTLR(v3, v4) 파서 생성기에는 수많은 Oracle SQL 및 PL/SQL 문법이 작성되어 있습니다. 자세한 내용은 문법 목록(v3)을 참조하십시오.다음 중:

  • 저는 Andrey Karitonkin의 "ANTLR v3용 Oracle PL/SQL Grammar"를 사용했습니다. 메모리에서 9i와 10g에 나타나는 몇 가지 비트와 조각으로 8i 시대의 대부분의 SQL 및 PL/SQL 구문을 지원했습니다.
  • 패트릭 히긴스의 "PL/SQL" 문법은 더 새롭고 대부분의 11g 구문을 지원한다고 주장하지만, 그것은 대부분의 DML 문을 그냥 삼키는 것처럼 보입니다. 특히 SQL에 관심이 있다면 그다지 유용하지 않습니다.

윌, 오라클 파서를 사용하는 게 어때요?

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자로 제한했지만 varchar2의 pl/sql 배열을 dbms_sql.parse 함수에 입력할 수 있으므로 상상할 수 없는 크기의 sql을 구문 분석할 수 있습니다.

동일한 문제를 해결한 후 SQL 파서를 사용할 수 있었습니다.

  • http://www.oracle.com/technetwork/developer-tools/sql-developer/overview/index.html 에서 Oracle SQL Developer를 다운로드합니다.
  • Oracle SQL developer에는 세트된 jar가 포함되어 있으며 일부 API는 Oracle Fusion Middleware Java API Reference for Oracle Extension SDK(javadoc: http://docs.oracle.com/middleware/1212/jdev/ESDKJ/index.html?oracle/javatools/db/sql/class-use/SQLQueryBuilder.SQLQueryObjectSet.html) 링크)의 일부로 문서화되어 있습니다.
  • 사용 가능한 클래스 중 하나는 oracle.javatools.db.sql입니다.SQLQueryBuilder입니다.

내 코드는 다음과 같습니다.

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 설정이 저장된 폴더를 파고 해당 내용을 자신의 파일에 복사 붙여넣기만 하면 됩니다.

  • 다음 과제는 데이터베이스 암호를 정의하는 것입니다.그것은 암호화되어 있지만 이 게시물(https://community.oracle.com/message/12359081) 은 매우 도움이 될 것입니다 - 게시물 끝에 있는 답을 확인하십시오.

여기까지 성공했다고 가정하면 문제와 최종 솔루션에 실망한 점이 있습니다.

  • 빌더의 API는 괜찮은 편이지만 구문 분석은 쿼리 실행을 수행합니다(그리고 이것은 큰 문제가 될 수 있습니다). 저의 경우에는 구문 분석이 빨라야 했습니다.
  • API는 공식적으로 공개되지 않습니다.여기서 정확한 문구를 인용할 수는 없었지만 공식적으로 지원되는 Oracle 파서가 없다는 Oracle 답변을 받았습니다(단, 언급된 이유는 이 기술이 판매되거나 라이센스가 부여되지 않는 매우 가치 있는 기술이기 때문입니다).
  • 이것은 해결책이라기보다는 해킹에 가깝지만, 저는 (제가 아닌) 경우에 유용할 수도 있다는 것을 깨달았습니다.저는 그것을 실제 시나리오에서 사용하는 것은 기술적인 측면과 법적인 측면 모두에서 매우 위험할 수 있다고 생각합니다.

제가 이 답변을 올린 이유는 Oracle SQL 파서를 보유하는 것이 완벽하게 실현 가능하며 언젠가는 Oracle이 파서를 경쟁 우위로 노출하는 것을 고려할 것이라는 사실에 대한 커뮤니티의 관심을 유도하기 위한 것입니다(라이센스를 얻기 위해 기꺼이 비용을 지불하는 사용자도 있을 것입니다).

일반 SQL 파서를 고려해 보셨습니까?저는 그것에 대한 경험이 없지만 그들의 웹사이트를 검색하는 것은 잠재력이 있습니다.개인적으로 Eclipse Data Tools Platform의 파서에 구축된 자체 빌드를 롤업했지만(공유할 수 없습니다. 독점적입니다.) 이제 위에서 링크한 것을 평가해야 합니다. 왜냐하면 파서보다 Oracle SQL의 적용 범위가 더 많다고 주장하기 때문입니다.

Oracle Corporation은 SQL 파서와 PL/SQL VM의 SQL 파서가 서로 다를 때 SQL 파서와 PL/SQL VM의 동기화 상태를 유지할 수 없었기 때문에 타사에서 "완전하게 호환되는" 파서를 만들 수 있을 가능성은 거의 없습니다.

쿼리에서 추출하려는 데이터가 무엇입니까?Oracle 데이터베이스 자체에는 먼저 쿼리를 구문 분석하지 않고 해당 정보를 추출할 수 있는 다른 기능이 있을 수 있습니다.

NAT의 DMS Software Reengineering Toolkit은 Oracle PLSQL 파서 또는 SQL 2011 파서를 사용하여 얻을 수 있습니다. DMS는 파서를 제공하고 AST를 빌드하며 트리를 임의로 조사/변환할 수 있도록 하며, 원하는 경우 AST를 소스 코드로 재생성합니다.

웹 사이트에서 사용할 수 있는 PLSQL 포맷터를 다운로드하여 파서를 테스트할 수 있습니다. 동일한 기본 DMS 시스템을 사용합니다. 트리를 분석/변환하지 않습니다.

SQL 문을 간단한 PLSQL 절차로 묶어야 할 수도 있습니다.

http://www.ibrezina.net/OracleSQL.tgz 을 사용해 보십시오.오라클의 PL/SQL에 대한 ANTLR3.3 문법입니다.문법은 C 대상을 대상으로 하지만 Java 또는 C#으로 쉽게 변환할 수 있습니다.작업, 쿼리에 포함된 테이블 목록이 이미 예제로 포함되어 있습니다.

jOOQ에는 Oracle SQL을 포함하여 지원되는 모든 데이터베이스 제품에서 많은 SQL을 구문 분석할 수 있는 내장 파서가 있습니다.모든 것을 구문 분석할 수는 없지만 대부분의 사용 사례에 충분할 수 있습니다.예를 들어 Oracle 외부 조인 연산자를 구문 분석할 수 있습니다.(+)ANSI SQL로 변환할 수도 있습니다.파서번역기 데모는 여기에서 볼 수 있습니다.

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

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

사이트, CLI 또는 Java, Kotlin, Scala 등을 사용하여 프로그래밍 방식으로 파서를 사용할 수 있습니다.

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

구문 분석 출력은 일반적인 jOOQ API이며, jOOQ의 모델 API를 사용하여 다른 SQL로 변환할 수 있습니다.

언급URL : https://stackoverflow.com/questions/5735791/parser-for-oracle-sql