虽然我同意 Tony 的观点,即使用动态 SQL 的性能更好,但上下文变量是比使用绑定变量更好的方法。
使用IN_VARIABLE IS NULL OR table.fieldx = IN_VARIABLE
不适合处理可选值。每次提交查询时,Oracle 首先在其共享池中检查该语句之前是否已提交过。如果有,则检索查询的执行计划并执行 SQL。如果在共享池中找不到该语句,Oracle 必须经过解析语句、计算出各种执行路径并提出最佳访问计划(也称为“最佳路径”)的过程才能执行。这个过程被称为“硬解析”,它可能比查询本身花费更长的时间。在此处阅读有关Oracle 中的硬/软解析的更多信息,并在此处阅读 AskTom。
简而言之 - 这个:
and (:bcode is null or q.bcode = :bcode)
...将执行相同的,动态的或其他的。在动态 SQL 中为可选参数使用绑定变量没有任何好处。该设置仍然会破坏 SARGability ......
上下文参数是Oracle 9i中引入的一个特性。它们与包绑定,可用于设置属性值(仅适用于对包具有 EXECUTE 权限的用户,您必须将 CREATE CONTEXT 授予模式)。上下文变量可用于定制动态 SQL,因此它仅包含基于过滤器/搜索条件的查询所需的内容。相比之下,绑定变量(在动态 SQL 中也支持)要求指定一个值,这可能会导致IN_VARIABLE IS NULL OR table.fieldx = IN_VARIABLE
搜索查询中的测试。在实践中,应为每个程序或功能使用单独的上下文变量,以消除价值污染的风险。
这是您使用上下文变量的查询:
L_CURSOR SYS_REFCURSOR;
L_QUERY VARCHAR2(5000) DEFAULT 'SELECT num
FROM (SELECT DISTINCT q.num
FROM CQQV q
WHERE 1 = 1 ';
BEGIN
IF IN_BCODE IS NOT NULL THEN
DBMS_SESSION.SET_CONTEXT('THE_CTX',
'BCODE',
IN_BCODE);
L_QUERY := L_QUERY || ' AND q.bcode = SYS_CONTEXT(''THE_CTX'', ''BCODE'') ';
END IF;
IF IN_LB IS NOT NULL THEN
DBMS_SESSION.SET_CONTEXT('THE_CTX',
'LB',
IN_LB);
L_QUERY := L_QUERY || ' AND q.lb = SYS_CONTEXT(''THE_CTX'', ''LB'') ';
END IF;
IF IN_TYPE IS NOT NULL THEN
DBMS_SESSION.SET_CONTEXT('THE_CTX',
'TYPE',
IN_TYPE);
L_QUERY := L_QUERY || ' AND q.type = SYS_CONTEXT(''THE_CTX'', ''TYPE'') ';
END IF;
IF IN_EDATE IS NOT NULL THEN
DBMS_SESSION.SET_CONTEXT('THE_CTX',
'EDATE',
IN_EDATE);
L_QUERY := L_QUERY || ' AND q.edate = SYS_CONTEXT(''THE_CTX'', ''EDATE'') - 30 ';
END IF;
L_QUERY := L_QUERY || ' ORDER BY dbms_random.value()) subq
WHERE rownum <= :numrows ';
FOR I IN 0 .. (TRUNC(LENGTH(L_QUERY) / 255)) LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(L_QUERY, I * 255 + 1, 255));
END LOOP;
OPEN L_CURSOR FOR L_QUERY USING IN_ROWNUM;
RETURN L_CURSOR;
END;
该示例仍然为 rownum 使用绑定变量,因为该值不是可选的。
DBMS_SESSION.SET_CONTEXT('THE_CTX', 'LB', IN_LB);
SET_CONTEXT 参数如下:
- 上下文变量名称。不涉及实例创建
- 上下文变量中的变量。假设熟悉 Web 应用程序和会话对象,上下文变量就像会话变量。
- 参数 #2 中定义的变量的值。
绑定与上下文
绑定变量意味着 Oracle 期望填充变量引用 - 否则会出现 ORA 错误。例如:
... L_QUERY USING IN_EXAMPLE_VALUE
...期望有一个要填充的绑定变量引用。如果IN_EXAMPLE_VALUE
为空,则必须在:variable
查询中。IE:AND :variable IS NULL
使用上下文变量意味着不必包含无关/冗余逻辑,检查值是否为空。
重要提示:绑定变量按出现顺序(称为序数)处理,而不是按名称处理。USING
您会注意到子句中没有数据类型声明。序数并不理想 - 如果您在查询中更改它们而不更新USING
子句,它将破坏查询,直到它被修复。