14

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

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

4

5 回答 5

12

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

另一个想法 - 但也许更难的是编辑查询以添加(并且 rownum < 1)或使其运行快速的东西

于 2012-04-20T13:25:47.813 回答
6

如果您正在处理 SELECT 查询,也许 JDBC PreparedStatement#getMetaData会起作用?

于 2012-04-20T15:36:13.903 回答
5

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

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

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

于 2012-04-20T14:17:27.840 回答
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;
/
于 2012-04-20T15:21:02.500 回答
0

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

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

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

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

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

    proc INAME=test SQLCHECK=SYNTAX

  3. 您将看到以下输出:

    文件 test.pc 第 1 行第 34 列的语法错误:文件 test.pc 中第 1 行第 34 列的错误
    EXEC SQL SELECT * FROM DUAL WERE 1=1;
    .................................1
    PCC-S-02201,在期待其中之一时遇到符号“1”以下:
    ; , for, union, connect, group, having, intersect, minus, order, start, where, with,
    符号“有”被替换为“1”继续。

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

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

于 2013-08-21T12:04:51.163 回答