此文档介绍两个事情,一个是替代变量,另一个就是了解一下硬解析和软解析对于变量来说declare定义的好还是variable定义的好 在oracle 中,对于一个提交的sql语句,存在两种可选的解析过程, 一种叫做硬解析,一种叫做软解析.一个硬解析需要经解析,制定执行路径,优化访问计划等许多的步骤.硬解释不仅仅耗费大量的cpu,更重要的是会占据重要的们闩(latch)资源,严重的影响系统的规模的扩大(即限制了系统的并发行),而且引起的问题不能通过增加内存条和cpu的数量来解决。之所以这样是因为门闩是为了顺序访问以及修改一些内存区域而设置的,这些内存区域是不能被同时修改。当一个sql语句提交后,oracle会首先检查一下共享缓冲池(shared pool)里有没有与之完全相同的语句,如果有的话只须执行软分析即可,否则就得进行硬分析。 而唯一使得oracle 能够重复利用执行计划的方法就是采用绑定变量。绑定变量的实质就是用于替代sql语句中的常量的替代变量。绑定变量能够使得每次提交的sql语句都完全一样。 连接 前两天看到有人在pub上问在sqlplus中通过define和variable定义的变量的区别。其实define定义的我 理解不是变量而是字符常量,通过define定义之后,在通过&或者&&引用的时候不需要输入了,仅此而已。 oracle在执行的时候自动用值进行了替换;而variable定义的是绑定变量,上面已经提到。 绑定变量引用的时候用":" ,替代变量引用的时候用"&"; 绑定变量初始化 exec :num1:=2,替代变量默认类型为char 替换变量(仅用于SQL *Plus或者用于原理和SQL *Plus相同的开发工具): 临时存储值 利用它可以达到创建通用脚本的目的 利用它可以达到和用户交互,故在SQL *Plus中又称交互式命令 替换变量的格式式在变量名称前加一个&,以便在运行SQL命令时提示用户输入替换数据,然后按输入数据运行SQL命令 语法: (1)& :“&变量名”eg:&name; 生命周期:单次引用中,不需要声明,如果替换字符或日期类型,最好用单引号扩起 使用范围:where、order by、列表达式、表名、整个SELECT 语句中 www.2cto.com (2)&& :“&&变量名”eg:&&name; 生命周期:整个会话(session连接),不需要声明 (3)define :“define 变量名=变量值”eg:DEFINE a = clark; 生命周期:整个会话,预先声明,使用时用&引用声明的变量 define variable=用户创建的CHAR类型的值:define 变量名=值; define 变量名:查看变量命令。 undefine 变量名:清除变量 define:查看在当前会话中所有的替换变量和它们的值 (4)accept 生命周期:整个会话 预先声明,可以客户化提示信息,使用时用&引用声明的变量。 定义: accept 变量名name number/char/date prompt '提示信息内容'即:ACC[EPT] variable [NUM[BER] | CHAR | DATE] [FOR[MAT] format] [DEF[AULT] default] [PROMPT text | NOPR[OMPT]] [HIDE] 解释: PROMPT命令:用于输出提示用户的信息,以便使用户了解脚本文件的功能和运行情况 PAUSE命令:用于暂停脚本文件的运行 HIDE选项:用于隐藏用户的输入,使别人不可见,安全 这条命令的意思是:当plsql程序段执行到变量name的时候,此时需要用户的交互才能继续执行下去,plsql程序段会显示“提示信息内容”让用户输入相关信息(如果指定hide选项,那么在接下去用户输入的东西将被用星号显示出来增加安全,有点像输入密码),用户输入的内容被接收到并且把它付给name,关于在“提示信息内容”下用户输入的内容的类型,plsql程序段开发人员来通过number/char/date指定,变量name得到正确的值以后,继续执行相关下面的程序! 例:accept a char prompt '请输入员工的雇佣时间(yyyy-mm-dd):' hide 例:accept a char prompt 'input a:' hide www.2cto.com set verify on/off; #verify:是否给出原值及新值提示。 具体请参看下面的例子: plsql程序1: [sql] declare v_sal number(6,2); v_ename emp.ename%type:='&ename'; begin select sal into v_sal from emp where lower(ename)=lower(v_ename); if v_sal<2000 then update emp set sal=v_sal + 200 where lower(ename)=lower(v_ename); end if; end; / plsql程序2: [sql] declare v_sal number(6,2); v_ename emp.ename%type:='&&ename'; begin select sal into v_sal from emp where lower(ename)=lower(v_ename); if v_sal<2000 then update emp set sal=v_sal + 200 where lower(ename)=lower(v_ename); end if; www.2cto.com end; / secureCRT的一个会话中先执行程序2,再次执行程序1,会发现直接PL/SQL procedure successfully completed. 而不让我输入ename,将set verify off也不行 另一个打开会话 将set verify off后,每次执行程序1都会让你输入ename。 这就是在前面一个会话执行程序2的时候已经将ename,保存为了会话的变量,而不是plsql程序的变量。 另外一个案例完整的accept例子 CREATE TABLE EMP (EMPNO NUMBER(4) NOT NULL, ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4), HIREDATE DATE, SAL NUMBER(7, 2), COMM NUMBER(7, 2), DEPTNO NUMBER(2)); INSERT INTO EMP VALUES (7369, 'SMITH', 'CLERK', 7902, TO_DATE('23-12-2013', 'DD-MM-YYYY'), 800, NULL, 20); INSERT INTO EMP VALUES (7499, 'ALLEN', 'SALESMAN', 7698, TO_DATE('20-02-1981', 'DD-MM-YYYY'), 1600, 300, 30); INSERT INTO EMP VALUES (7521, 'WARD', 'SALESMAN', 7698, TO_DATE('22-02-1981', 'DD-MM-YYYY'), 1250, 500, 30); INSERT INTO EMP VALUES (7566, 'JONES', 'MANAGER', 7839, TO_DATE('22-04-1981', 'DD-MM-YYYY'), 2975, NULL, 20); INSERT INTO EMP VALUES (7654, 'MARTIN', 'SALESMAN', 7698,TO_DATE('28-09-1981', 'DD-MM-YYYY'), 1250, 1400, 30); INSERT INTO EMP VALUES (7698, 'BLAKE', 'MANAGER', 7839,TO_DATE('01-03-1981', 'DD-MM-YYYY'), 2850, NULL, 30); INSERT INTO EMP VALUES (7782, 'CLARK', 'MANAGER', 7839,TO_DATE('09-05-1981', 'DD-MM-YYYY'), 2450, NULL, 10); INSERT INTO EMP VALUES (7788, 'SCOTT', 'ANALYST', 7566,TO_DATE('09-12-1982', 'DD-MM-YYYY'), 3000, NULL, 20); INSERT INTO EMP VALUES (7839, 'KING', 'PRESIDENT', NULL,TO_DATE('17-11-1981', 'DD-MM-YYYY'), 5000, NULL, 10); INSERT INTO EMP VALUES (7844, 'TURNER', 'SALESMAN', 7698,TO_DATE('08-09-1981', 'DD-MM-YYYY'), 1500, 0, 30); INSERT INTO EMP VALUES (7876, 'ADAMS', 'CLERK', 7788,TO_DATE('12-06-1983', 'DD-MM-YYYY'), 1100, NULL, 20); INSERT INTO EMP VALUES (7900, 'JAMES', 'CLERK', 7698,TO_DATE('13-12-1981', 'DD-MM-YYYY'), 950, NULL, 30); INSERT INTO EMP VALUES (7902, 'FORD', 'ANALYST', 7566,TO_DATE('13-12-1981', 'DD-MM-YYYY'), 3000, NULL, 20); INSERT INTO EMP VALUES (7934, 'MILLER', 'CLERK', 7782,TO_DATE('23-03-1982', 'DD-MM-YYYY'), 1300, NULL, 10); prompt C R E A T E N E W E M P L O Y E E R E C O R D prompt prompt Enter the employee's information: prompt accept l_ename char format a10 prompt '名字: ' accept l_empno number format '9999' prompt '编号 #: ' accept l_sal number format '99999.99' prompt 'Salary [1000]: ' default '1000.00' accept l_comm number format '99999.99' prompt 'Commission % [0]: ' default '0' accept l_hired date format 'mm/dd/yyyy' prompt 'Hire date (mm/dd/yyyy): ' prompt List of available jobs: select distinct job from emp order by job / accept l_job char format a9 prompt 'Job: ' prompt List of managers and employee numbers: select empno, ename from emp order by ename / accept l_mgr number format '9999' prompt 'Manager''s Employee #: ' prompt List of department numbers and names: select deptno, dname from dept order by deptno / accept l_dept number format '99' prompt 'Department #: ' insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (&l_empno, '&l_ename', '&l_job', &l_mgr, to_date('&l_hired','mm/dd/yyyy'), &l_sal, &l_comm, &l_dept) / select * from emp where empno=&l_empno / drop table emp;