Oracle中“&”和“&&”的区别

2hh7jdfx  于 2023-10-16  发布在  Oracle
关注(0)|答案(3)|浏览(156)

我正在研究绑定变量(:)和与号运算符(& /替换变量)之间的区别。我意识到,“双&号是存储变量值和重用这些值的地方,它是相同的会话。
根据这一事实,如果我使用双&,那么我可以避免硬解析或没有?

ifmq2ha2

ifmq2ha21#

绑定变量的前缀是:,由数据库中的SQL引擎计算。
替换变量以&(或&&)为前缀,并由用于连接到数据库的客户端应用程序进行计算(即,SQL*Plus、SQL Developer或其他支持相同语法的客户端,但并非所有客户端都支持替换变量语法),并且数据库中的SQL引擎无法理解(如果客户端将其发送到数据库而不进行预处理,则会导致语法错误)。
如果我使用双与号,那么我是否可以避免硬解析?
替换变量将被视为您对正在使用的脚本的源代码执行了查找-替换,并且在任何代码发送到数据库之前由客户端应用程序完成。
然后数据库必须解析您发送给它的语句,并且需要对它以前没有见过的任何语句(包括空白中的更改)进行硬解析。如果你总是使用不同的语句,那么数据库每次都必须对语句进行硬解析;它可以对它已经高速缓存的语句进行软解析。
绑定变量可能会阻止这种重新解析;替换变量不会阻止它(因为它们在客户端处理)。

hm2xizp9

hm2xizp92#

标题要求区分&&&
这两种方法都使用替换变量(正如你已经知道的)。这里有一个简单而又虚拟的例子,但将说明差异。

第一项:只有一个&使用相同的替换变量名;您需要输入相同的值两次(或根据需要多次):

SQL> set ver off
SQL>
SQL> select e.ename, e.job, e.sal
  2  from emp e join dept d on e.deptno = d.deptno
  3  where e.deptno = &par_deptno
  4    and d.deptno = &par_deptno;
Enter value for par_deptno: 10   --> this is from line #3
Enter value for par_deptno: 10   --> this is from line #4

ENAME      JOB              SAL
---------- --------- ----------
CLARK      MANAGER         2450
KING       PRESIDENT       5000
MILLER     CLERK           1300

重新运行相同的查询-您将再次得到提示:

SQL> /
Enter value for par_deptno: 30
Enter value for par_deptno: 30

ENAME      JOB              SAL
---------- --------- ----------
ALLEN      SALESMAN        1600
WARD       SALESMAN        1250
MARTIN     SALESMAN        1250
BLAKE      MANAGER         2850
TURNER     SALESMAN        1500
JAMES      CLERK            950

6 rows selected.

SQL>

第二种选择&&,这只会导致一个输入值的提示:

SQL> select e.ename, e.job, e.sal
  2  from emp e join dept d on e.deptno = d.deptno
  3  where e.deptno = &&par_deptno
  4    and d.deptno = &&par_deptno;
Enter value for par_deptno: 10

ENAME      JOB              SAL
---------- --------- ----------
CLARK      MANAGER         2450
KING       PRESIDENT       5000
MILLER     CLERK           1300

如果我重新运行它会发生什么?老(Old!)值,没有任何提示:

SQL> /

ENAME      JOB              SAL
---------- --------- ----------
CLARK      MANAGER         2450
KING       PRESIDENT       5000
MILLER     CLERK           1300

SQL>

如果要使用另一个替换变量值,请取消定义它,然后运行查询:

SQL> undefine par_deptno
SQL> /
Enter value for par_deptno: 30

ENAME      JOB              SAL
---------- --------- ----------
ALLEN      SALESMAN        1600
WARD       SALESMAN        1250
MARTIN     SALESMAN        1250
BLAKE      MANAGER         2850
TURNER     SALESMAN        1500
JAMES      CLERK            950

6 rows selected.

SQL>

至于你在 body 中发布的问题(关于硬解析):据我所知,替换变量在这方面没有帮助。Bind变量。
看看BluShadow在OTN Forums(PL/SQL 101 : Substitution vs. Bind Variables)上写了什么:
因此,总而言之,Substitution变量是用户界面在将其提交给数据库之前检测并提示文本替换到代码中的变量,Bind变量是查询中的占位符,允许SQL查询被软解析而不是硬解析当查询被重用时,有助于防止SQL注入,并且允许在发出它的代码内容易且无缝地提供值。
另外,请注意,替代变量不能在任何地方使用;这取决于你使用的工具。例如,SQL*Plus可以处理它们,TOAD不能识别它们,等等。

ulmd4ohb

ulmd4ohb3#

其他人已经充分回答了使用替换变量(&&&)对解析问题没有帮助。但是绑定变量(:)也有一个问题。
如果你使用的是SQLPlus,你应该知道如果你的变量是一个新的值,就没有办法避免硬解析。SQLPlus不是一个编程环境。它更像一个瘦客户机,只是一个数据库的输入/输出屏幕。这对绑定变量(:)的使用产生了重大影响。要在SQLPlus中使用绑定变量,必须声明它,然后 * 赋值 * 它的值:

SQL> var junk number
SQL> exec :junk := 5;

PL/SQL procedure successfully completed.

在幕后,它使用PL/SQL来完成分配。这行exec :junk := 5;被发送到数据库:

BEGIN :junk := 5; END;

这是一个匿名的PL/SQL块需要共享池中的游标,就像普通的SQL一样,因为5将是一个文字,随着值的变化,这个赋值块将创建新的游标,* 每次都很难解析 *。
因此,提供输入(而不是接收输出)的SQLPlus绑定变量不能帮助您避免硬解析。也就是说,如果使用bind变量的SQL很复杂,有很多连接等等。那么你就可以通过使用binds来避免对SQL进行硬解析,而且可能会比赋值块更昂贵,需要更多的解析时间和共享池中的内存。因此,即使是输入,使用绑定变量也是有好处的。但是你无法避免赋值本身的硬解析。
因此,如果目的是将数据插入到Oracle中,并且您希望对插入列使用绑定变量,那么它将对共享池造成严重破坏。这使得SQLPlus不适合将数据加载到数据库中,因为数据库通常需要大量的连续输入。然而,如果你只是想做一个查询,你需要提供一些将在查询 predicate 中使用的输入,那么大概你不会太频繁地运行这个,因为硬解析成为一个问题。几十次迭代是一回事,几千次完全是另一回事。
SQLPlus是一个方便的工具,可以用来进行特别的工作或偶尔编写脚本,它可以很好地提取适量的数据。我们都欣赏它的普遍性。但它不是一个很好的工具,在任何可观的执行量(数据处理)的编程使用。为此,您需要一个真实的、完全成熟的编程环境,其中包含使用OCI的数据连接器。这样的环境将是功能齐全的,并且可以做很多SQLPlus无法做的事情,包括在不使用PL/SQL的情况下分配客户端绑定变量。然后,您可以使用批量赋值,而无需任何严格的解析。
如果您按照预期的方式使用SQLPlus,用于临时或偶尔计划的脚本使用,那么容量非常小,没有人会关心解析问题。使用它并享受它。

相关问题