在执行之前如何验证Oracle动态SQL的语法?

问题陈述:
您想在执行之前验证SQL的语法。

解决方案: DBMS_SQL默认软件包允许动态执行SQL。它由SYS拥有,已使用AUTHID CURRENT_USER关键字定义,因此它以调用者的特权运行。我们可以利用DBMS_SQL.PARSE函数来验证语法。

我们将首先定义一个函数以接受SQL语句作为参数并解析SQL语句。

/*
 * ---------------------------------------------------------------------------
 *  Function : check_syntax
 *    Input  : sql statement
 *   Output  : Number
 * ---------------------------------------------------------------------------
 */
 
 FUNCTION check_syntax
    ( p_query IN CLOB )
  RETURN INTEGER
  IS
  l_cursor NUMBER := dbms_sql.open_cursor;
  BEGIN
     BEGIN
        DBMS_SQL.PARSE (l_cursor, p_query, DBMS_SQL.native);
     EXCEPTION
        WHEN OTHERS THEN
            DBMS_SQL.CLOSE_CURSOR (l_cursor);
            RETURN -1;
     END;
     DBMS_SQL.CLOSE_CURSOR (l_cursor);
     RETURN 0;
  END check_syntax;

在上面的函数l_cursor中,使用open_cursor函数打开。然后,使用DBMS_SQL.PARSE解析给定的SQL语句,如果SQL出现语法问题,它将重新调谐-1。现在,我们将通过传递示例SQL来运行该函数。

示例1:将有效SQL传递给函数

DECLARE
l_rc   VARCHAR2(100);
l_sql_stmnt CLOB;
BEGIN
l_sql_stmnt := 'SELECT 1 FROM DUAL' ;
l_rc   := my_package.check_syntax(l_sql_stmnt);
IF l_rc = 0 THEN
  dbms_output.put_line(' ** SQL Validation Pass - ' || l_sql_stmnt);
ELSE
  dbms_output.put_line(' ** SQL Validation Fail - ' || l_sql_stmnt);
END IF;
END;

输出结果

 ** SQL Validation Pass - SELECT 1 FROM DUAL

示例2:将有效SQL传递给函数

DECLARE
l_rc   VARCHAR2(100);
l_sql_stmnt CLOB;
BEGIN
l_sql_stmnt := 'SELECT 1 FROM DUALED' ;
l_rc   := my_package.check_syntax(l_sql_stmnt);
IF l_rc = 0 THEN
  dbms_output.put_line(' ** SQL Validation Pass - ' || l_sql_stmnt);
ELSE
  dbms_output.put_line(' ** SQL Validation Fail - ' || l_sql_stmnt);
END IF;
END;

输出结果

 ** SQL Validation Fail - SELECT 1,2,4 FROM DUALED