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

Posted

技术标签:

【中文标题】如何在不运行实际查询的情况下检查 JDBC 语句的 SQL 语法?【英文标题】:How can I check SQL syntax for a JDBC statement without running the actual query? 【发布时间】:2012-05-02 02:10:48 【问题描述】:

我有一条 SQL 语句(用于 Oracle 数据库),如果它有效,则需要很长时间才能运行。如果无效,则立即返回错误。

我想在不运行语句(通过 JDBC)的情况下检查语法是否有效,例如在“检查语句”按钮后面。是否有独立于供应商的方式来做到这一点?我的第一个想法是将查询简单地定义为 PreparedStatement 似乎不会导致任何类型的编译或错误检查。

【问题讨论】:

也许其他问题的答案可以帮助你:***.com/questions/141499/… 【参考方案1】:

可能为该语句发布解释计划会给您带来有用的结果。

另一个想法 - 但可能更难的是编辑要添加的查询(和 rownum

【讨论】:

解释计划是要走的路。它将给出与“运行”查询相同的语法错误 绑定参数如何处理? 没错,如果您的查询中只有一个参数,这根本行不通。 您可能会考虑用假值替换绑定 - 它是否会返回行无关紧要,只要它会解析即可。【参考方案2】:

如果您正在处理 SELECT 查询,也许 JDBC PreparedStatement#getMetaData 可以工作?

【讨论】:

【参考方案3】:

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

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

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

【讨论】:

gordy 的评论得到了我的投票,因为它适用于 Oracle 以外的其他 dbms。 @user1938185 是的,FROM dual 仅适用于 Oracle 和 mysql(我认为是 SQLite)。在其他方面,例如 SQL Server 和 Postgres,您可以完全删除 FROM dual,它也可以正常工作。【参考方案4】:

您可以使用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;
/

【讨论】:

【参考方案5】:

您可以使用Oracle's Pro*C precompiler 执行语法检查 (download here)。

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

    使用以下代码创建文件 test.pc:

    执行 SQL SELECT * FROM DUAL WERE 1=1;

    安装预编译工具后运行此命令:

    proc INAME=test SQLCHECK=SYNTAX

    你会看到这个输出:

    文件 test.pc 第 1 行第 34 列的语法错误: 文件 test.pc 中第 1 行第 34 列出错 执行 SQL SELECT * FROM DUAL WERE 1=1; ..................................1 PCC-S-02201,在预期以下情况之一时遇到符号“1”: ; , 为, 联合, 连接, 分组, 有, 相交, 减号, 顺序,开始,在哪里,与, 符号“有”被替换为“1”以继续。

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

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

【讨论】:

以上是关于如何在不运行实际查询的情况下检查 JDBC 语句的 SQL 语法?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不实际启动活动的情况下检查外部应用程序的活动“exported=false”

如何在不使用 CURL 的情况下运行 HTTP 请求

如何在不影响实际文档的情况下修改 Mongoose 中的结果查询?

如何在不运行Bash脚本的情况下语法检查?

如何在不实际运行“vagrant ssh”的情况下 ssh 到 vagrant?

在 C++ 中,如何在不使用 if 语句的情况下选择运行特定的成员函数?