plsql - 获取第一行 - 哪一个更好?

时间:2012-03-11 10:30:10

标签: sql oracle plsql

LV_id number;
Cursor CR_test Is
  select t.id
  from table1 t
  where t.foo = p_foo
  order by t.creation_date; 

Open CR_test;
Fetch CR_test
 Into LV_id;
Close CR_test;

或者这个:

select x.id
from(select t.id
     from table1 t
     where t.foo=p_foo
     order by t.creation_date) x
where rownum = 1

以上两者都有类似的结果,但我需要知道哪一个更有效!

2 个答案:

答案 0 :(得分:7)

这是Tom Kyte的口头禅:

  

如果可能,您应该在单个SQL语句中执行此操作   如果您无法在单个SQL语句中执行此操作,请在PL / SQL中执行此操作   如果您无法在PL / SQL中执行此操作,请尝试Java存储过程   如果您不能在Java中执行此操作,请在C外部过程中执行此操作   如果你不能在C外部程序中做到这一点,你可能想认真考虑为什么你需要这样做...

http://tkyte.blogspot.com/2006/10/slow-by-slow.html

答案 1 :(得分:3)

在这种情况下,最简单的方法是测试您的查询。

请务必自行测试,表格中的索引和数据可能会对您的表格产生不同的结果。

没有任何索引,看起来使用分析函数DENSE_RANK有更好的方法:

SELECT MIN(id) KEEP (DENSE_RANK FIRST ORDER BY creation_date)
INTO lv_id
FROM table1
WHERE foo = p_foo;

我使用以下代码来测试查询所消耗的时间(多次执行此块,结果可能会有所不同):

DECLARE
  p_foo  table1.foo%TYPE := 'A';
  lv_id  table1.id%TYPE;
  t      TIMESTAMP := SYSTIMESTAMP;
BEGIN
  FOR i IN 1 .. 100 LOOP
    -- Query here
  END LOOP;
  dbms_output.put_line(SYSTIMESTAMP - t);
END;

结果:

  1. 使用光标,取第一行:
    2.241 s

  2. 将查询与ROWNUM一起使用:
    1.483 s

  3. 使用DENSE_RANK
    1.168 s