在Oracle中,open-for和打开带参数的游标有什么区别?

dtc*_*dtc 7 oracle plsql

这两段代码有什么区别?

TYPE t_my_cursor IS REF CURSOR; 
v_my_cursor t_my_cursor;
OPEN v_my_cursor FOR SELECT  SomeTableID 
        FROM MYSCHEMA.SOMETABLE
        WHERE SomeTableField = p_parameter;
Run Code Online (Sandbox Code Playgroud)

和...

CURSOR v_my_cur(p_parameter VARCHAR2) IS
SELECT SomeTableID
FROM MYSCHEMA.SOMETABLE
WHERE SomeTableField = p_parameter;

OPEN presf_cur(p_subscriber_id);
Run Code Online (Sandbox Code Playgroud)

他们似乎都工作.它们是相同的还是我应该注意到的一些差异?

APC*_*APC 6

第二个示例是显式游标,它是静态的.也就是说,它是一个与一个SQL语句关联的变量.有一个隐含的等价物......

FOR lrec in ( SELECT  SomeTableID 
              FROM MYSCHEMA.SOMETABLE
              WHERE SomeTableField = p_parameter )
LOOP
    do_something_with (lrec.sometableid);
END LOOP;
Run Code Online (Sandbox Code Playgroud)

第一个例子是一个引用游标,它是一个指向SQL语句的指针,因此可以是动态的.例如,我们可以像这样扩展这个例子:

TYPE t_my_cursor IS REF CURSOR; 
v_my_cursor t_my_cursor;

...

if flag = 1 then
    OPEN v_my_cursor FOR SELECT  SomeTableID 
        FROM MYSCHEMA.SOMETABLE
        WHERE SomeTableField = p_parameter;
else
    OPEN v_my_cursor FOR SELECT  SomeTableID 
        FROM MYSCHEMA.ANOTHERTABLE
        WHERE AnotherTableField = p_parameter;
end if;
Run Code Online (Sandbox Code Playgroud)

甚至:

    l_stmt := 'SELECT * FROM your_table WHERE ';
    if p_parameter is not null then
        l_stmt := l_stmt ||'id = :1'; 
        open v_my_cursor for l_stmt using p_parameter;
    else
        l_stmt := l_stmt ||'created_date > trunc(sysdate)'; 
        open v_my_cursor for l_stmt;
    end if;
Run Code Online (Sandbox Code Playgroud)

因此,使用引用游标可以让我们更好地控制执行的最终SQL语句.另一个区别是,因为引用游标是一个指针,它可以在程序之间传递.这对于将数据从PL/SQL传递到其他语言(例如JDBC结果集)非常有用.


Bri*_*ian 5

  1. 可以"描述"强类型游标.
  2. 如果您构建API(包),您可以将光标定义放在规范级别,并让客户端程序员更好地了解您的API所做的事情并返回,而无需了解源代码.
  3. 布局/ IDE/GUI工具可能会更好地使用命名游标.
  4. 具有已知的类型光标可能具有可忽略的性能益处; 但我不指望它有什么重要意义.