在sqlplus或其他工具中,开发和执行SQL语句时,经常会遇到以下三种变量:

  • 脚本替换变量:& / && / define / undefine
  • SQL语句绑定变量:: / var(iable) / exec
  • PL/SQL存储过程变量:declare

本文将对Oracle SQL中的变量进行分析探讨。

1. 脚本替换变量

替换变量可以放在SQL或PL/SQL语句中的任意位置,包含select值或字段,from表名,where字段或条件,order by、group by、having等任意位置,以及PL/SQL语句的deaclre、begin中的任意位置。

替换变量在使用时,进行的是字符串替换,没有数据类型之分,全部为字符串,在SQL语句执行之前已由sqlplus等工具完成了SQL语句的字符串替换。需要注意的是,如果SQL语句中,替换变量所在的位置应为字符或日期类型的值,则最好用单引号扩起来。

1.1 使用规则

替换变量的使用,可以分别以下几个基本动作:

  • 交互输入:当&或&&引用的变量没有定义时,会提示用户输入替换值
  • 变量引用:当&或&&引用的变量已经定义时,会引用变量的值
  • 字符替换:通过字符串替换的方式,将该位置出现的替换变量替换为对应变量值或输入值
  • 变量定义:通过define命令定义或修改,或变量未定义时&&第一次交互输入的值

替换变量使用过程中,所设计的操作符或命令如下:

  • &:变量引用、交互输入和字符替换
  • &&:变量引用、交互输入、字符替换和变量定义
  • define/undefine:定义与清除变量

1.2 命令帮助

SQL> help define
 DEFINE
 ------
 Specifies a substitution variable and assigns a CHAR value to it, or
 lists the value and variable type of a single variable or all variables.
 DEF[INE] [variable] | [variable = text]

SQL> help undefine
 UNDEFINE
 --------
 Deletes one or more substitution variables that you defined either
 explicitly (with the DEFINE command), or implicitly (with a START
 command argument).
 UNDEF[INE] variable ...

1.3 应用详解

  • &:如果变量已定义时,则引用变量并替换;如果变量无定义,交互输入替换值,替换,但不定义变量,即如果后面又出现该替换变量,则仍需要交互输入替换值,当然也可以使用define提前定义替换变量值,规避交互输入。

postgresql 替换全部替换字符串 plsql中替换函数_绑定变量

SQL> select '&name','&name' from dual;
Enter value for name: Li
Enter value for name: Qiang
old   1: select '&name','&name' from dual
new   1: select 'Li','Qiang' from dual

'L 'QIAN
-- -----
Li Qiang

SQL> select &col,&col from v$database;
Enter value for col: name
Enter value for col: open_mode
old   1: select &col,&col from v$database
new   1: select name,open_mode from v$database

NAME	  OPEN_MODE
--------- --------------------
ORCL	  READ WRITE

SQL> /
Enter value for col: open_mode
Enter value for col: name
old   1: select &col,&col from v$database
new   1: select open_mode,name from v$database

OPEN_MODE	     NAME
-------------------- ---------
READ WRITE	     ORCL

SQL> define col
SP2-0135: symbol col is UNDEFINED
  • &&:如果变量已定义时,则引用变量并替换;如果变量无定义,交互输入替换值,替换并定义变量。也可以使用define提前定义替换变量值,规避交互输入。

postgresql 替换全部替换字符串 plsql中替换函数_绑定变量_02

SQL> select '&&name','&&name' from dual;
Enter value for name: Li
old   1: select '&&name','&&name' from dual
new   1: select 'Li','Li' from dual

'L 'L
-- --
Li Li

SQL> select &&col,&&col from v$database;
Enter value for col: name
old   1: select &&col,&&col from v$database
new   1: select name,name from v$database

NAME	  NAME
--------- ---------
ORCL	  ORCL

SQL> /
old   1: select &&col,&&col from v$database
new   1: select name,name from v$database

NAME	  NAME
--------- ---------
ORCL	  ORCL

SQL> define col
DEFINE COL	       = "name" (CHAR)
  • define:用于查看、定义或修改替换变量值。define定义的变量,可以使用&或&&直接引用和替换,无需再交互输入变量值。
  • unfine:用于清除变量。
SQL> define col
DEFINE COL	       = "name" (CHAR)
SQL> undefine col
SQL> define col
SP2-0135: symbol col is UNDEFINED

SQL> define col=name
SQL> select &&col from v$database;
old   1: select &&col from v$database
new   1: select name from v$database

NAME
---------
ORCL

SQL> select &col from v$database;
old   1: select &col from v$database
new   1: select name from v$database

NAME
---------
ORCL
  • PL/SQL中的使用示例
SQL> declare
  2  n number;
  3  begin
  4  select count(*) into n from &t;
  5  dbms_output.put_line(n);
  6  end;
  7  /
Enter value for t: v$database
old   4: select count(*) into n from &t;
new   4: select count(*) into n from v$database;
1

PL/SQL procedure successfully completed.

SQL> /
Enter value for t: v$datafile
old   4: select count(*) into n from &t;
new   4: select count(*) into n from v$datafile;
4

PL/SQL procedure successfully completed.

2. SQL语句绑定变量

绑定变量用于,将一组只有检索值或插入值不同,而其他部分相似的SQL语句,统一为绑定变量替换后的SQL语句形式,从而实现软解析。

绑定变量只能用于SQL语句的where或values部分,形式上会在变量名前面加冒号。在PL/SQL语句中,SQL语句外的变量均为PL/SQL存储过程变量,可以使用using命令,将带绑定变量的SQL语句和存储过程变量的值,一起发送给SQL引擎。

2.1 使用规则

绑定变量在赋值或引用时,需要在变量名前加冒号“:”。这样做对PL/SQL语句块来说,是为了与存储过程变量区分,对SQL语句来说,是为了表示这是个绑定变量,SQL执行前不做变量引用,从而实现SQL软解析,最后SQL执行时,再做变量引用。

与绑定变量有关的命令如下,前3个为sqlplus工具命令,最后1个为PL/SQL语句命令。

  • variable:绑定变量定义与赋值
  • execute:绑定变量赋值,
  • print:打印绑定变量的值
  • execute immediate(PL/SQL):执行动态SQL,并使用using附加绑定变量

绑定变量有数据类型之分,在sqlplus中使用variable命令定义绑定变量时,需要声明数据类型,在PL/SQL中包含绑定变量的SQL中,可以不指定数据类型,PL/SQL会根据using后跟的值类型,来确定绑定变量数据类型。

  • NUMBER
  • CHAR CHAR (n [CHAR|BYTE])
  • NCHAR NCHAR (n)
  • VARCHAR2 (n [CHAR|BYTE])
  • NVARCHAR2 (n)
  • CLOB NCLOB
  • REFCURSOR
  • BINARY_FLOAT BINARY_DOUBLE

2.2 命令帮助

SQL> help variable

 VARIABLE
 --------

 Declares a bind variable that can be referenced in PL/SQL, or
 lists the current display characteristics for a single variable
 or all variables.

 VAR[IABLE] [<variable> [type][=value]]

 where type represents one of the following:

     NUMBER         CHAR          CHAR (n [CHAR|BYTE])
     NCHAR          NCHAR (n)     VARCHAR2 (n [CHAR|BYTE])
     NVARCHAR2 (n)  CLOB          NCLOB
     REFCURSOR      BINARY_FLOAT  BINARY_DOUBLE

 One can assign value to a variable for input with the new syntax
 Example:
   VARIABLE tmp_var VAHRCHAR2(10)=Smith
   or
   VARIABLE tmp_var VAHRCHAR2(10)
   VARIABLE tmp_var=Smith
   EXECUTE DBMS_OUTPUT.PUT_LINE(:tmp_var)
   
SQL> help print

 PRINT
 -----

 Displays the current values of bind variables, or lists all bind
 variables.

 PRINT [variable ...]
 
 SQL> help exec

 EXECUTE
 -------

 Executes a single PL/SQL statement or runs a stored procedure.

 EXEC[UTE] statement

2.3 应用详解

  • sqlplus中使用绑定变量

sqlplus工具中,通过variable命令创建绑定变量并赋值,再执行包含绑定变量的SQL语句,sqlplus会将SQL语句和绑定变量值,一起发送给SQL引擎。

SQL> variable fileno number = 1
--或
SQL> variable fileno number
SQL> exec :fileno := 1;
PL/SQL procedure successfully completed.

SQL> print fileno
    FILENO
----------
	 1

SQL> select file#,name from v$datafile where file# = :fileno;

     FILE#        NAME
---------------  ----------------------
	 1           /data/ORCL/system01.dbf
  • PL/SQL语句中使用

PL/SQL语句中使用绑定变量时,需要使用execute immediate执行带有绑定变量的SQL语句,使用into接收select语句的输出,使用using附加绑定变量的值。using中的值,可以是实际值,也可以是存储过程变量。

--using实际值
SQL> declare
  2  oid varchar2(200);
  3  begin 
  4  execute immediate 'select object_id from dba_objects where owner = :1 and object_name = :2' into oid using 'MDSYS','R_TABLE';
  5  dbms_output.put_line(oid);
  6  end;
  7  /
70560
PL/SQL procedure successfully completed.

--using存储过程变量
SQL> declare
  2  oid varchar2(200);
  3  own varchar2(10) := 'MDSYS';
  4  obn varchar2(10) := 'R_TABLE';
  5  begin
  6  execute immediate 'select object_id from dba_objects where owner = :1 and object_name = :2' into oid using own,obn;
  7  dbms_output.put_line(oid);
  8  end;
  9  /
70560
PL/SQL procedure successfully completed.

3. PL/SQL存储过程变量

PL/SQL存储过程变量,需要在declare字句中进行声明,赋值时使用“:=”冒号等号赋值符。在赋值或引用存储过程变量时,直接写变量名即可,不需要加&或:号。

3.1 使用规则

与PL/SQL存储过程相关的操作如下:

  • declare:变量声明,生命变量名、数据类型,并可以赋值
  • %TYPE:引用某个表的某一列的数据类型
  • %ROWTYPE:引用某个表的表结构
  • var := value:变量赋值
  • select col into var:将select结果赋值给变量
  • execute immeidate 'select ...' into var:将SQL结果赋值给变量

3.2 应用详解

变量使用前必须声明,变量声明必须在declare字句中。

可以在变量声明时,同时赋值,也可以在begin字句使用变量前进行赋值。

直接键入变量名,即可引用变量,无需加任何修饰符。

--声明时直接赋值
SQL> declare
  2  out varchar2(20) := 'My Output';
  3  begin
  4  dbms_output.put_line(out);
  5  end;
  6  /
My Output

--在begin中赋值
SQL> declare  
  2  out varchar2(20);
  3  begin
  4  out := 'My Output';
  5  dbms_output.put_line(out);
  6  end;
  7  /
My Output

--使用select into语句赋值,into在select和from之间
SQL> declare
  2  name v$database.name%TYPE;
  3  begin
  4  select name into name from v$database;
  5  dbms_output.put_line(name);
  6  end;
  7  /
ORCL

--使用execute immediate执行SQL语句后,将结果赋值给变量,into语句后面
SQL> declare
  2  name v$database.name%TYPE;
  3  begin
  4  execute immediate 'select name from v$database' into name;
  5  dbms_output.put_line(name);
  6  end;
  7  /
ORCL

--将表结构作为变量的数据类型,可以通过点号,引号某列的值
SQL> declare
  2  out v$database%ROWTYPE;
  3  begin
  4  select * into out from v$database;
  5  dbms_output.put_line(out.name);
  6  end;
  7  /
ORCL