首页 > Linux操作系统 > Linux操作系统 > 谈谈“&”替换标志的一些特性
在Oracle客户端,我们可以使用“&”来进行SQL语句指定内容的替换。当我们使用Sqlplus等基于Oracle客户端的工具时,“&”标号可以帮助我们实现一些功能。在本篇中,笔者准备探讨一下标号的基本特性和深层特点。
1、&标号基本使用
应该说,&标号的作用是在SQL语句执行过程中,如果Oracle发现中间使用了&标记,就终止执行,转而要求用户前段确认标记的变量取值,之后用输入的值进行数据替换。下面是在Sqlplus上的一个基本应用,我们在Oracle 10g下进行试验。
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 – Production
SQL> select empno, ename from emp where empno=&no;
输入 no 的值: 7902
原值 1: select empno, ename from emp where empno=&no
新值 1: select empno, ename from emp where empno=7902
EMPNO ENAME
---------- ----------
7902 FORD
当使用了&标号后,Oracle会提示用户输入这个取值,之后进行内容“全文替换”。注意,如果输入变量是一个字符串类型,要注意单引号’的使用特性如下:
SQL> select empno, ename from emp where job=&job;
输入 job 的值: CLERK
原值 1: select empno, ename from emp where job=&job
新值 1: select empno, ename from emp where job=CLERK
select empno, ename from emp where job=CLERK
*
第 1 行出现错误:
ORA-00904: "CLERK": 标识符无效
SQL> select empno, ename from emp where job='&job';
输入 job 的值: CLERK
原值 1: select empno, ename from emp where job='&job'
新值 1: select empno, ename from emp where job='CLERK'
EMPNO ENAME
---------- ----------
7369 SMITH
7876 ADAMS
SQL> select empno, ename from emp where job=&job;
输入 job 的值: 'CLERK'
原值 1: select empno, ename from emp where job=&job
新值 1: select empno, ename from emp where job='CLERK'
EMPNO ENAME
---------- ----------
7369 SMITH
7876 ADAMS
在&与字符串的结合应用中,我们从上面的例子就可以看出端倪要点,如果SQL语句中的字符串列条件值没有使用单引号进行包括,那么输入的变量就一定要求带上’。如果字符串列条件值已经包括了单引号,就不需要输入了。
进一步想,我们可以认为,在&标号的情况下,就是一个简单的“内容替换”。
2、&标号的更进一步特性
其实,&标号绝不仅仅可以替换where后面的条件句。从语法本质看,这个标记可以替换SQL语句中更多的内容。
--1、替换where字句
SQL> select empno, ename from emp &state job='CLERK';
输入 state 的值: where
原值 1: select empno, ename from emp &state job='CLERK'
新值 1: select empno, ename from emp where job='CLERK'
EMPNO ENAME
---------- ----------
7369 SMITH
7876 ADAMS
--2、替换select字句
SQL> &state empno, ename from emp where job='CLERK';
SP2-0734: 未知的命令开头 "&state emp..." - 忽略了剩余的行。
SQL> select empno, ename &state emp where job='CLERK';
输入 state 的值: from
原值 1: select empno, ename &state emp where job='CLERK'
新值 1: select empno, ename from emp where job='CLERK'
EMPNO ENAME
---------- ----------
7369 SMITH
7876 ADAMS
--3、替换列名
SQL> select empno, &colum from emp where job='CLERK';
输入 colum 的值: ename
原值 1: select empno, &colum from emp where job='CLERK'
新值 1: select empno, ename from emp where job='CLERK'
EMPNO ENAME
---------- ----------
7369 SMITH
7876 ADAMS
--4、替换排序列
SQL> select empno from emp where job='CLERK' order by &m;
输入 m 的值: empno
原值 1: select empno from emp where job='CLERK' order by &m
新值 1: select empno from emp where job='CLERK' order by empno
EMPNO
----------
7369
7876
上面的四个语句试验,告诉我们&替代符可以做更多的事情,包括替代SQL语句中的关键字和列名。注意,这里除了SQL的第一个关键字不能做之外。
说到这里,顺便提一下“&&”标记。&&标记的作用就是记住变量的取值,在下一次使用的时候,就不需要强制进行替换了。
SQL> select empno, ename from emp where job='&&job';
输入 job 的值: CLERK
原值 1: select empno, ename from emp where job='&&job'
新值 1: select empno, ename from emp where job='CLERK'
EMPNO ENAME
---------- ----------
7369 SMITH
7876 ADAMS
7900 JAMES
7934 MILLER
SQL> select empno, ename from emp where job='&&job';
原值 1: select empno, ename from emp where job='&&job'
新值 1: select empno, ename from emp where job='CLERK'
EMPNO ENAME
---------- ----------
7369 SMITH
7876 ADAMS
3、关于&标号和绑定变量
&标号和我们在实际开发中使用的绑定变量有一些相似之处,但是具有更大的灵活性。绑定变量(bind variable)只能进行where条件单值的替换,而且不能进行SQL关键字的替换。那么,我们怎么看待这两个特性呢?
笔者认为,&标号的特性具有更加强的灵活性,多种的替换功能是建立在Oracle客户端功能的基础之上。也就是说,我们替换的全文内容,是Oracle客户端给我们进行替换的。Oracle客户端进行替换之后,将替换完的SQL语句发送给Oracle服务端,Oracle优化器optimizer接受和处理解析的语句,都是替换完成的SQL语句。下面我们通过实验去证明:
SQL> alter system flush shared_pool;
System altered
SQL> select /*+ demo */count(*) from emp where deptno=&no;
输入 no 的值: 10
原值 1: select /*+ demo */count(*) from emp where deptno=&no
新值 1: select /*+ demo */count(*) from emp where deptno=10
COUNT(*)
----------
3
SQL> select /*+ demo */count(*) from emp where deptno=&no;
输入 no 的值: 40
原值 1: select /*+ demo */count(*) from emp where deptno=&no
新值 1: select /*+ demo */count(*) from emp where deptno=40
COUNT(*)
----------
0
此时,我们检查Shared Pool中的游标,如下:
SQL> col sql_text for a52;
SQL> select sql_text, sql_id from v$sqlarea where sql_text like 'select /*+ demo */count(*)%';
SQL_TEXT SQL_ID
---------------------------------------------------- -------------
select /*+ demo */count(*) from emp where deptno=40 0rtgwj49d4yu2
select /*+ demo */count(*) from emp where deptno=10 19a1vdf75kucg
可见,我们在shared pool中找到两条的父游标记录,说明在服务端接受的时候,就是已经替换完的取值。进一步说,&号在服务端是不能够起到bind variable的共享父子游标的作用。
而bind variable是可以起到这个作用的。
SQL> var x number;
SQL> exec :x := 10;
PL/SQL 过程已成功完成。
SQL> select /*+ demo */count(*) from emp where deptno=:x;
COUNT(*)
----------
3
SQL> exec :x := 20;
PL/SQL 过程已成功完成。
SQL> select /*+ demo */count(*) from emp where deptno=:x;
COUNT(*)
----------
5
SQL> select sql_text, sql_id from v$sqlarea where sql_text like 'select /*+ demo */count(*)%';
SQL_TEXT SQL_ID
---------------------------------------------------- -------------
select /*+ demo */count(*) from emp where deptno=:x 888j35kfajnuj
4、结论
&是我们在Oracle客户端可以支持的一种工具类型。在我们进行调试程序的时候,可以提供一定程度的帮助。但是笔者认为,在实际开发工作中,意义不是很大。&标记符的出现,可能是作为某种历史时期的产品方向。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/17203031/viewspace-742014/ ,如需转载,请注明出处,否则将追究法律责任。