通过直接 sql 的 plsql 光标

Posted

技术标签:

【中文标题】通过直接 sql 的 plsql 光标【英文标题】:plsql cursor via straight sql 【发布时间】:2010-11-17 17:00:25 【问题描述】:

我正在研究以下两种检索值并稍后通过插入语句存储它的方法。即通过 Pl/SQL 游标或通过直接 SQL。 这两种方法有什么优势吗?还是有更有效的方法?

方法 1

Cursor system_date
Is 
 select sysdate from dual;
system_date_rec system_date%type;

Open system_Date;
Fetch system_date into system_date_rec;

Insert into table(dateValue)
values(system_date_rec.date);

方法二

dateString  varchar(20);
Select sysdate into dateString from dual;
Insert into table(dateValue)
values(dateString);

【问题讨论】:

【参考方案1】:

方法3怎么样:

Insert into table(dateValue)
values(sysdate);

或者假设您确实需要进行选择来获取数据:

Insert into table(dateValue)
select dateValue from other_table where ...;

关于当需要一个或另一个时显式游标或 SELECT INTO 是否更可取,我会选择 SELECT INTO,因为如果您希望查询只返回一行,它会更简洁、更安全:

select some_value
into l_var
from other_table
where ...;

if l_var = 'A' then
  do_something;
end if;

现在,如果返回的行数与预期不符,您将收到异常(NO_DATA_FOUND 或 TOO_MANY_ROWS)。使用游标,你最终会得到 l_var 不变,或者设置为第一个匹配行的值 - 这可能意味着你有一个错误但不知道。

【讨论】:

“sysdate”只是演示这些方法的一个例子,但它并不是我真正想做的。我只是想知道这两种方法中哪一种在性能方面更有效。我有时必须编写几个大查询并通过访问游标或局部变量来处理结果。您知道这两种方法之间是否会有任何性能差异?谢谢:) 我相信 SELECT INTO 会稍微快一点。 每次回看这个答案都比上次长! 我知道,在思考蹄子!【参考方案2】:

每种方法都有其优点,但如果它是您获得的唯一一个值,那么我会选择select ... into ...,因为这更简单,并且会检查您是否只有一个值。

尽管在适当的情况下,Tony 的方法可能比两者都更可取。

如果您还想取回该值,则插入语句的 RETURNING 子句始终存在。

my_date_value date;
...
INSERT into table(datevalue)
values (sysdate)
returning sysdate into my_date_value;

【讨论】:

有趣,我不知道 insert 有一个返回子句。【参考方案3】:

我同意@Tony 和@MikeyByCrikey 的观点,即select ... into 通常更可取,尤其是-在我个人的主观意见中-因为它使选择和进入保持在一起,而不是让选择在声明部分。如果它很简单,这并不是一个真正的问题,但您建议您正在执行几个大型查询和操作,这意味着一个冗长的过程。

有点题外话,但如果所有操作都是在最后为单个插入收集数据,那么我会考虑将单个变量声明为行类型并将列更新为适当的:

declare
    l_row my_table%ROWTYPE;
begin
    select ... into l_row.column1;
    select ... into l_row.column2;
    if l_row.column2 = 'A' then
        /* do something */
    end if;
    l_row.column3 := 'somevalue';
    fetch ... into l_row.column4;
    /* etc */
    insert into my_table values l_row;
end;

【讨论】:

以上是关于通过直接 sql 的 plsql 光标的主要内容,如果未能解决你的问题,请参考以下文章

使用 PL SQL 删除

关于plsql!!!

C# 和 PlSql 光标

plsql导入dmp文件时:IMP-00041:警告:创建的对象有编译警告

如何修改plsql数据库列的属性值?

如何在plsql 执行导入导入语句: 在dos下能直接执行exp 和imp语句,但plsql下执行报错?