DECLARE
var_customer_id number;
rec_customer customer%ROWTYPE;
BEGIN
var_customer_id := 1234567;
SELECT *
INTO rec_customer
FROM customer
WHERE customer_id = var_customer_id; -- this cursor can be reused by different customer ID values
END;
在SQL Plus中使用var声明:
var customer_id number
exec :customer_id := 1234567;
SELECT *
FROM customer
WHERE customer_id = :customer_id; -- this cursor can be reused by different customer ids
1条答案
按热度按时间w1e3prcc1#
当您向Oracle提交SQL时,数据库必须留出共享内存来描述SQL,并通过一些复杂的优化器排列生成执行计划,然后存储其计划(它为满足您的请求而生成的内部程序)。这就是我们所说的“光标”。它会消耗内存并需要时间来生成。这发生在解析步骤,如果不显式执行,则在客户端执行SQL时隐式发生。如果你要在一个循环中进行一百万次迭代,使用相同的SQL,但每次都改变一些文字标识符,那么你会在这个解析活动上花费大量的时间,并且消耗大量的共享内存,因为每个SQL都与它之前的SQL不同,并且需要自己的游标。在高容量下,使用每次执行都会更改的文字的SQL可能会使数据库处于不健康的状态(它最终可能会在管理其共享池时遇到问题,这可能会导致其他用户的分配错误,甚至在严重时使数据库崩溃)。它还为用户增加了不必要的运行时间。如果程序必须对循环的每次迭代进行硬解析,那么它的运行速度比应有的要慢。所以你的DBA是正确的,这是我们总是引导开发人员远离的东西。
绑定变量允许重复使用相同的SQL语句(游标),即使引用的特定 predicate 值从一次执行到下一次执行会发生变化,也可以通过屏蔽每次变化的文字值来实现。然后SQL文本每次都是相同的,并且只需要一次(硬)解析。解析一次,执行多次。这消除了重复硬解析的昂贵开销以及在共享池中分配内存的压力,以及所需的所有引脚和锁存器,从而减少了争用和CPU开销。
如果您发现不可能实现绑定(不太可能),那么DBA可以选择创建一个登录触发器,该触发器拦截您的登录并发出
alter session
以设置“cursor_sharing=force
“,这是解决此问题的一个老方法,尽管它可能会导致某些客户端接口出现问题,并且是最后的解决方案。这个设置会强制重写SQL,将每个文本替换为绑定,不管这样做是否有意义。这并不理想,但当代码无法更改时,这是一个有用的创可贴。最好的办法是更改代码,并在频繁更改的 predicate 值上使用客户端的适当绑定变量。如何实现绑定取决于您的编程环境。在PL/SQL中,它可以通过使用PL/SQL变量来完成:
在SQL Plus中使用
var
声明:在使用OCI 8 instantclient的PHP中,它可能看起来像这样:
每个客户机编程环境和Oracle接口API都是唯一的,但几乎所有的都应该有绑定的概念。在所有情况下,SQL文本都包含一个占位符(通常使用
:
,但不总是)和一种将客户端变量绑定到该占位符的方法。如何实现取决于你的编程环境。