我可以在oracle sql中的程序中实现多少个查询?

时间:2016-10-25 18:16:42

标签: sql oracle11g

create or replace PROCEDURE BUILDREPORT_sql_performance 
(
  userChoice IN INT
) AS 
BEGIN 
DELETE FROM TMP_sql_performance;

INSERT INTO TMP_sql_performance
(sql_text,
sql_fulltext,
cpu_time,
last_load_time)

   (SELECT sql_text, sql_fulltext, cpu_time,
last_load_time from v$sql 
WHERE (CASE 
        WHEN userChoice = 3 AND TO_DATE(substr(last_load_time, 1, 10),'YYYY-MM-DD') > ADD_MONTHS(TRUNC(SYSDATE), -12) THEN 1    --One Year
        WHEN userChoice = 2 AND TO_DATE(substr(last_load_time, 1, 10),'YYYY-MM-DD') > ADD_MONTHS(TRUNC(SYSDATE), -1)  THEN 1    --One Month
        WHEN userChoice = 1 AND TO_DATE(substr(last_load_time, 1, 10),'YYYY-MM-DD') > TRUNC(SYSDATE -7) THEN 1                  --One Week
        WHEN userChoice = 0 AND TO_DATE(substr(last_load_time, 1, 10),'YYYY-MM-DD') > TRUNC(SYSDATE -1) THEN 1                  --one Day
      ELSE 0
    END) = 1);

select * from tmp_sql_performance;

END BUILDREPORT_sql_performance;

它给了我:错误(24,3):PLS-00428:在这个SELECT语句中需要一个INTO子句。可能我只能在程序中查询一次或两次

1 个答案:

答案 0 :(得分:0)

你必须选择一些东西,它必须是一个变量,记录或集合(取决于你得到的数据 - 列数和行数)。或者你可以有一个迭代的游标并做一些事情(包括可能,仅用于调试目的,使用dbms_output进行记录)。

听起来您想要将查询结果返回给过程调用者,您可以使用ref cursor OUT parameter执行此操作:

create or replace PROCEDURE BUILDREPORT_sql_performance 
(
  userChoice IN INT,
  resultCursor OUT SYS_REFCURSOR
) AS 
BEGIN 
DELETE FROM TMP_sql_performance;

INSERT INTO TMP_sql_performance
(sql_text,
sql_fulltext,
cpu_time,
last_load_time)

   (SELECT sql_text, sql_fulltext, cpu_time,
last_load_time from v$sql 
WHERE (CASE 
        WHEN userChoice = 3 AND TO_DATE(substr(last_load_time, 1, 10),'YYYY-MM-DD') > ADD_MONTHS(TRUNC(SYSDATE), -12) THEN 1    --One Year
        WHEN userChoice = 2 AND TO_DATE(substr(last_load_time, 1, 10),'YYYY-MM-DD') > ADD_MONTHS(TRUNC(SYSDATE), -1)  THEN 1    --One Month
        WHEN userChoice = 1 AND TO_DATE(substr(last_load_time, 1, 10),'YYYY-MM-DD') > TRUNC(SYSDATE -7) THEN 1                  --One Week
        WHEN userChoice = 0 AND TO_DATE(substr(last_load_time, 1, 10),'YYYY-MM-DD') > TRUNC(SYSDATE -1) THEN 1                  --one Day
      ELSE 0
    END) = 1);

OPEN resultCursor FOR
  select * from tmp_sql_performance;

END BUILDREPORT_sql_performance;
/

然后对过程的调用需要传递sys_refcursor变量,并对生成的游标执行某些操作。

出于测试目的,您可以使用匿名块,以及 - 在SQL * Plus和SQL Developer中的leats - 客户端定义的绑定变量:

variable rc refcursor

exec buildreport_sql_performance(42, :rc);

print rc

exec是匿名阻止的简写,因此与执行操作相同:

begin
  buildreport_sql_performance(42, :rc);
end;
/

注意过程调用中:rc之前的冒号。这表示您正在传递一个在外部 PL / SQL块中定义的绑定变量。

variableprint命令是Oracle客户端命令,而不是SQL。其他客户端可能无法识别它们,尽管有些客户端模仿了Oracle的行为。

你说“每当我执行该程序时,它必须向我显示更新的表格”。这取决于执行它的任何人或任何人。您无法直接从PL / SQL显示任何内容 - 它实际上并不是设计为交互式语言。您可能最终通过JDBC从Java程序中调用它,然后将使用Java代码迭代结果集并对每行中的值执行某些操作。或者它可以从其他PL / SQL或预定作业调用,或者在其他地方没有逻辑位置来显示输出。在上面的示例中,客户端程序正在调用过程并显示OUT游标,但仅在明确告知时才会显示。

正如Justin Cave所指出的那样,你正在做的事情似乎是试图模仿另一个数据库系统中的行为。你真的需要一个(可能是全局临时的)表并不明显;您可以在打开光标时直接查询v$sql

create or replace procedure buildreport_sql_performance 
(
  userchoice in int,
  resultcursor out sys_refcursor
) as 
begin 
  open resultcursor for
   select sql_text, sql_fulltext, cpu_time, last_load_time from v$sql 
where (case 
        when userchoice = 3 and to_date(substr(last_load_time, 1, 10),'YYYY-MM-DD') > add_months(trunc(sysdate), -12) then 1    --One Year
        when userchoice = 2 and to_date(substr(last_load_time, 1, 10),'YYYY-MM-DD') > add_months(trunc(sysdate), -1)  then 1    --One Month
        when userchoice = 1 and to_date(substr(last_load_time, 1, 10),'YYYY-MM-DD') > trunc(sysdate -7) then 1                  --One Week
        when userchoice = 0 and to_date(substr(last_load_time, 1, 10),'YYYY-MM-DD') > trunc(sysdate -1) then 1                  --one Day
      else 0
    end) = 1;
end buildreport_sql_performance;
/

或者没有重复to_date()来电:

create or replace procedure buildreport_sql_performance 
(
  userchoice in int,
  resultcursor out sys_refcursor
) as 
begin 
  open resultcursor for
    select sql_text, sql_fulltext, cpu_time, last_load_time from v$sql 
    where to_date(substr(last_load_time, 1, 10),'YYYY-MM-DD') > case
        when userchoice = 3 then add_months(trunc(sysdate), -12)   --One Year
        when userchoice = 2 then add_months(trunc(sysdate), -1)    --One Month
        when userchoice = 1 then trunc(sysdate -7)                 --One Week
        when userchoice = 0 then trunc(sysdate -1)                 --one Day
        else null
    end;
end buildreport_sql_performance;
/