oracle 如何在PL/SQL中使用声明变量创建存储过程

rm5edbpk  于 2023-11-17  发布在  Oracle
关注(0)|答案(2)|浏览(119)

我想在PL/SQL中使用声明变量创建一个存储过程。但它不起作用。我如何创建这个?
我的代码看起来像:

create or replace procedure only_for_test as
begin
declare
maxdate date;
BEGIN
SELECT to_date(max(create_date)) 
INTO maxdate
FROM table_a where product = 'A' and create_date >= date'2023-09-01';
END;
if
maxdate = to_date(sysdate)
then
begin
proc_test;
end;
end if;
commit;
end only_for_test;

字符串
上面的代码显示错误:
PLS-00201:必须声明标识符“MAXDATE”
PL/SQL:忽略语句
请帮帮我。非常感谢。

8fq7wneg

8fq7wneg1#

你的问题是你有嵌套的PL/SQL块,你试图在外部块中使用MAXDATE,而在内部块中只有DECLARE d。

CREATE OR REPLACE PROCEDURE only_for_test
AS                  -- Variable definitions for outer block
BEGIN               -- Begin outer block
  DECLARE           -- Variable definitions for inner block
    maxdate DATE;
  BEGIN             -- Begin inner block
    -- ...          -- Do stuff in the inner block
  END;              -- End the inner block
                    -- maxdate was declared in the inner block and stops being
                    -- usable when you end the block
  -- ...            -- Do stuff in the outer block
END only_for_test;  -- End the outer block
/

字符串
首先创建一个匿名PL/SQL块(而不是一个过程),并测试你想要做的事情是否有效:

DECLARE
  maxdate DATE;
BEGIN
  SELECT TRUNC(MAX(create_date))
  INTO   maxdate
  FROM   table_a
  WHERE  product = 'A'
  AND    create_date >= DATE '2023-09-01';

  IF maxdate = TRUNC(sysdate) THEN
    proc_test;
  END IF;
END;
/


注意事项:

  • 除非你正在捕获异常,否则你(几乎总是)需要一个DECLARE,在这里声明变量,然后在最后声明一个BEGIN和一个END
    *Never在已经是DATE的值上使用TO_DATE。如果你想比较忽略DATE的时间分量的值,那么使用TRUNC将日期截断到午夜。
  • 不应该在过程中使用COMMIT,因为这会阻止您运行多个过程,然后在后面的过程失败时使用ROLLBACK回滚第一个过程中的更改。相反,从调用过程的代码中使用COMMIT

一旦一个简单的PL/SQL块开始工作,然后将块开始处的DECLARE语句交换为过程签名:

CREATE OR REPLACE PROCEDURE only_for_test
AS
  maxdate DATE;
BEGIN
  SELECT TRUNC(MAX(create_date))
  INTO   maxdate
  FROM   table_a
  WHERE  product = 'A'
  AND    create_date >= DATE '2023-09-01';

  IF maxdate = TRUNC(sysdate) THEN
    proc_test;
  END IF;
END;
/

vmdwslir

vmdwslir2#

它是关于作用域的。阅读下面代码中的注解。
首先,测试程序(以避免错误,它不存在):

SQL> CREATE PROCEDURE proc_test
  2  IS
  3  BEGIN
  4     NULL;
  5  END;
  6  /
CREATE PROCEDURE proc_test
                 *
ERROR at line 1:
ORA-00955: name is already used by an existing object

字符串
这是你的过程(修改了一点,以便它在我的模式中运行):

SQL> CREATE OR REPLACE PROCEDURE only_for_test
  2  AS
  3  BEGIN
  4     DECLARE
  5        maxdate  DATE;          --> this MAXDATE is local to its own DECLARE-BEGIN-END block
  6     BEGIN                      --> and you can use it whererver you want, but only within its block
  7        SELECT TO_DATE (MAX (hiredate))
  8          INTO maxdate
  9          FROM emp
 10         WHERE     job = 'CLERK'
 11               AND hiredate >= DATE '1980-09-01';
 12     END;
 13
 14     IF maxdate = TO_DATE (SYSDATE) --> referencing it here is out-of-scope, it doesn't exist
 15     THEN                           --> in this context
 16        BEGIN
 17           proc_test;
 18        END;
 19     END IF;
 20
 21     COMMIT;
 22  END only_for_test;
 23  /

Warning: Procedure created with compilation errors.

SQL> show err
Errors for PROCEDURE ONLY_FOR_TEST:

LINE/COL ERROR
-------- -----------------------------------------------------------------
14/4     PL/SQL: Statement ignored
14/7     PLS-00201: identifier 'MAXDATE' must be declared
SQL>


这就是工作原理-变量在过程级别声明:

SQL> CREATE OR REPLACE PROCEDURE only_for_test
  2  AS
  3     maxdate  DATE; --> if you declare it here, on procedure level, then ...
  4  BEGIN
  5     BEGIN
  6        SELECT TO_DATE (MAX (hiredate))
  7          INTO maxdate
  8          FROM emp
  9         WHERE     job = 'CLERK'
 10               AND hiredate >= DATE '1980-09-01';
 11     END;
 12
 13     IF maxdate = TO_DATE (SYSDATE) --> ... you CAN reference it through the whole procedure
 14     THEN
 15        BEGIN
 16           proc_test;
 17        END;
 18     END IF;
 19
 20     COMMIT;
 21  END only_for_test;
 22  /

Procedure created.

SQL>

相关问题