上次介绍了动态SQL(字符串的SQL)的基本语法:

<动态SQL的执行基本语法>
EXECUTE IMMEDIATE 动态SQL;

但是有个问题,如果动态SQL是查询的时候,无论结果是一行还是多行,查询的结果怎么放到变量里边呢。

之前介绍的时候后,查询结果只有一行的时候,可以使用使用SELECT INTO语句,如果结果是多行的时候,则需要使用光标。

这一章,针对动态SQL只返回一行的结果进行说明。

首先,复习一下不要动态SQL的例子和语法:也就是SELECT INTO文。

以下的例子是在SQL*Plus等画面上显示指定员工的名字的处理。

SQL>SET SERVEROUT ON --SQLPLUS、SQLDeveloper的画面输出有效
 SQL> DECLARE
 2 V_ENAME EMP.ENAME%TYPE;–用于存储查询结果的变量
 3 BEGIN
 4 SELECT ENAME INTO V_ENAME FROM EMP WHERE EMPNO = 7934;
 5 DBMS_OUTPUT.PUT_LINE(‘取得的员工名称=’|V_ENAME);
 6 END;
 7 /

取得的员工名称=MILLER

PL/SQL过程成功完成。

简单地解释如下:
●第2行……预先声明保存查询结果的变量
●第4行……用SELECT INTO语句将结果赋给该变量
●第5行……画面上显示变量的值

让我们猜想一下,如果动态查询SQL的结果和上边第4行一样,SELECT INTO文单引号引起来,做成字符串作为动态SQL,用EXECUTE IMMEDIATE来实行的话会怎么样呢?

SQL> DECLARE
 2 V_ENAME EMP.ENAME%TYPE;
 3 BEGIN
 4 EXECUTE IMMEDIATE
 5 ‘SELECT ENAME INTO V_ENAME FROM EMP WHERE EMPNO = 7934’;
 6 DBMS_OUTPUT.PUT_LINE(‘取得的员工名称=’|V ENAME);
 7 END;
 8 /

DECLARE
*
行1发生错误。:
ORA-00905:没有关键词。
ORA-06612:行4

发生语法错误。

所以,把SELECT INTO文直接变成动态SQL的文字串是不行的。

出问题出在INTO语句,INTO句必须在动态SQL(字符串SQL)之后。
如下所示的话,就OK了:

SQL> DECLARE
 2 V_ENAME EMP.ENAME%TYPE;
 3 BEGIN
 4 EXECUTE IMMEDIATE
 5 ‘SELECT ENAME FROM EMP WHERE EMPNO = 7934’ INTO V_ENAME;
 6 DBMS_OUTPUT.PUT_LINE(‘取得的员工名称=’|V_ENAME);
 7 END;
 8 /

取得的员工名称=MILLER

PL/SQL过程成功完成。

结果正常。

如上所述,查询用的动态SQL返回1行结果时的语法如下所示:

<查询用的动态SQL返回1行的基本语法>
EXECUTE IMMEDIATE 'SELECT 列1,列2,… ’ II INTO 变量1,变量2;

要点是INTO语句不包括在动态SQL(字符串SQL)的记述中,要和变量一起写在动态SQL字符串之外。

同理,要返回一行的多列时,可以使用变量也可以使用记录变量。
INTO 变量1,变量2

INTO 记录变量

和嵌入的SELECT INTO文一样呢。只是INTO句的地方不同。

假如检索结果是0行,或者多行的时候,会发生错误(分别为NO DATA FOUND例外、TOO MANY ROWS例外),发生错误时需要进行例外处理。

本次到此为止。