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

14

我有一个SQL语句(针对Oracle数据库),如果有效则执行需要很长时间,如果无效,则会立即返回一个错误。

我想通过JDBC,在“检查语句”按钮后面检查语法是否有效,而无需运行该语句。有没有厂商独立的方法可以做到这一点? 我最初的想法是将查询定义为PreparedStatement,但似乎没有任何编译或错误检查。


也许这个问题的答案可以帮助你:https://dev59.com/RnVC5IYBdhLWcg3w7V73 - Haroldo_OK
5个回答

12

可能为该语句发出一个解释计划会给你有用的结果。

另一个想法——但可能更难的是编辑查询,添加 (and rownum < 1) 或其他内容以使其运行更快。


3
解释计划是正确的选择。它将显示与“运行”查询相同的语法错误。 - user330315
2
如何处理绑定参数? - MRalwasser
如果您的查询中有任何一个参数,那么这个操作就不会起作用,返回值为True。 - Haroldo_OK
1
你可以考虑用一个假值替换绑定 - 它返回的行数并不重要,只要它能解析即可。 - Randy

6

5

这更像是一个技巧而不是一个真正的答案,但是您可以运行一个查询,该查询始终返回一行一列:

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

如果您的查询有效,则应返回TRUE,如果无效则应引发错误。


Gordy的评论得到了我的支持,因为它适用于除Oracle以外的其他数据库管理系统。 - AlainD
@user1938185 是的,在Oracle和MySQL(我认为还有SQLite)中,FROM dual 才有效。在其他数据库如SQL Server和Postgres中,你可以完全移除 FROM dual ,它仍然能正常工作。 - ypercubeᵀᴹ

2
您可以使用DBMS_SQL.PARSE来检查您的语句。警告:它只会解析DML语句,但会执行并提交DDL语句,如创建表等。您可以创建一个存储过程来返回值或布尔值,并包装一个类似于这样的块:
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;
/

0

你可以使用 Oracle 的 Pro*C 预编译器执行语法检查(在此下载)。

这是一个旨在预编译包含原始 Oracle SQL 语句的 C 代码的工具,但你可以"滥用"它来执行 SQL 语法检查。

  1. 创建一个名为test.pc的文件,并添加以下代码:

    EXEC SQL SELECT * FROM DUAL WERE 1=1;

  2. 安装预编译工具后,运行以下命令:

    proc INAME=test SQLCHECK=SYNTAX

  3. 您将看到以下输出:

    Syntax error at line 1, column 34, file test.pc: Error at line 1, column 34 in file test.pc
    EXEC SQL SELECT * FROM DUAL WERE 1=1;
    .................................1
    PCC-S-02201, Encountered the symbol "1" when expecting one of the following:
    ; , for, union, connect, group, having, intersect, minus, order, start, where, with,
    The symbol "having," was substituted for "1" to continue.

将其整合到您的解决方案中应该很简单。

请注意,它还可以执行在线语义检查,验证特定模式中使用的所有过程和表是否有效。为此,您需要传递SQLCHECK=SEMANTICS USERID=youruser参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接