简体   繁体   English

如何在不运行实际查询的情况下检查JDBC语句的SQL语法?

[英]How can I check SQL syntax for a JDBC statement without running the actual query?

I have an SQL statement (for an Oracle database) that takes a long time to run if it is valid. 我有一个SQL语句(对于Oracle数据库)如果有效则需要很长时间才能运行。 If it's not valid, it returns immediately with an error. 如果它无效,则立即返回错误。

I'd like to check that the syntax is valid without running the statement (via JDBC), for example behind a 'check statement' button. 我想检查语法是否有效而不运行语句(通过JDBC),例如在'check statement'按钮后面。 Is there a vendor-independent way of doing that? 是否有独立于供应商的方式? My first thought of simply defining the query as a PreparedStatement does not seem to cause any kind of compilation or error checking. 我首先想到的只是将查询定义为PreparedStatement似乎不会导致任何类型的编译或错误检查。

possibly issuing an explain plan for the statement would give you useful results. 可能会为声明发布解释计划会给你有用的结果。

another thought - but maybe harder is to edit the query to add (and rownum < 1) or something to make it run fast 另一个想法 - 但可能更难的是编辑要添加的查询(和rownum <1)或其他东西以使其快速运行

This is more of a hack than a real answer but you could run a query that will always return one row and one column: 这更像是一个hack而不是一个真正的答案,但你可以运行一个总是返回一行和一列的查询:

SELECT ( EXISTS (SELECT 1 FROM dual)
         OR
         EXISTS (your Query here)
       ) AS result
FROM dual 

This should return TRUE if your query is valid and raise error if it is invalid. 如果您的查询有效,则应返回TRUE如果无效,则应引发错误。

如果您正在处理SELECT查询,那么JDBC PreparedStatement#getMetaData可能会起作用吗?

You could use DBMS_SQL.PARSE to check your statement. 您可以使用DBMS_SQL.PARSE来检查您的语句。 Warning : It will just parse DML statements, but it will execute and commit DDL statements such as create table etc. You could create a stored procedure to return a value or boolean and wrap a block like this: 警告 :它只会解析DML语句,但它会执行并提交DDL语句,例如create table等。您可以创建一个存储过程来返回一个值或布尔值,并像这样包装一个块:

set serveroutput on
-- Example of good SQL 
declare
  c integer;
  s varchar2(50) := 'select * from dual';
begin
  c := dbms_sql.open_cursor;
  dbms_sql.parse(c,s,1);
  dbms_sql.close_cursor(c);
  dbms_output.put_line('SQL Ok');
exception
  when others then
    dbms_sql.close_cursor(c);
    dbms_output.put_line('SQL Not Ok');
end;
/

-- Example of bad SQL
declare
  c integer;
  s varchar2(50) := 'select splat from dual';
begin
  c := dbms_sql.open_cursor;
  dbms_sql.parse(c,s,1);
  dbms_sql.close_cursor(c);
  dbms_output.put_line('SQL Ok');
exception
  when others then
    dbms_sql.close_cursor(c);
    dbms_output.put_line('SQL Not Ok');
end;
/

You can use Oracle's Pro*C precompiler to perform a syntax check ( download here ). 您可以使用Oracle的Pro * C预编译器执行语法检查( 此处下载 )。

This is a tool meant to precompile C code containing raw Oracle SQL statements, but you can "abuse" it to perform SQL syntax checks. 这是一个用于预编译包含原始Oracle SQL语句的C代码的工具,但您可以“滥用”它来执行SQL语法检查。

  1. Create a file test.pc with this code: 使用以下代码创建文件test.pc:

    EXEC SQL SELECT * FROM DUAL WERE 1=1; EXEC SQL SELECT * FROM DUAL WERE 1 = 1;

  2. Run this command after installing the precompiler tools: 安装预编译器工具后运行此命令:

    proc INAME=test SQLCHECK=SYNTAX proc INAME = test SQLCHECK = SYNTAX

  3. You will see this output: 你会看到这个输出:

    Syntax error at line 1, column 34, file test.pc: Error at line 1, column 34 in file test.pc 第1行第34列语法test.pc中的语法错误:文件test.pc中第1行第34行出错
    EXEC SQL SELECT * FROM DUAL WERE 1=1; EXEC SQL SELECT * FROM DUAL WERE 1 = 1;
    .................................1 ................................. 1
    PCC-S-02201, Encountered the symbol "1" when expecting one of the following: PCC-S-02201,当遇到以下情况之一时遇到符号“1”:
    ; ; , for, union, connect, group, having, intersect, minus, order, start, where, with, ,for,union,connect,group,having,intersect,minus,order,start,where,with,
    The symbol "having," was substituted for "1" to continue. 符号“有”代替“1”继续。

It should be straightforward to integrate that into your solution. 将其集成到您的解决方案中应该是直截了当的。

Note that it can also perform online semantics checks, verifying that all the used procedures and tables are valid in a specific schema. 请注意,它还可以执行在线语义检查,验证所有使用的过程和表在特定模式中是否有效。 For that you pass in SQLCHECK=SEMANTICS USERID=youruser 为此,您传入SQLCHECK = SEMANTICS USERID = youruser

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM