【问题标题】:How can I declare and initialize a package variable by SELECT如何通过 SELECT 声明和初始化包变量
【发布时间】:2012-06-06 18:47:10
【问题描述】:

谁能帮我理解为什么我可以在包中声明一个硬编码的日期值,但不能从查询中分配值?我已经看到了许多显示硬编码值声明的示例(包括参考书),但我无法找到通过查询将值分配给变量的示例。

这是允许的:

create or replace package body PACKAGE_NAME AS
    tDate DATE := '2012-05-30';
    -- ...procedures follow

这是允许的:

create or replace package body PACKAGE_NAME AS
    tDate DATE := sysdate;

这是不允许的:

create or replace package body PACKAGE_NAME AS
    tDate DATE := select MAX(date_) from Table_Name;

我尝试了多种方法,但它不起作用 - 我可以在程序本身中根据需要使用它。但我想知道为什么我不能以这种方式为tDate 赋值?具体错误是:

在期待 .... 时遇到符号“SELECT”

补充说我可以通过存储过程中的查询获取分配的变量值,但相同的过程似乎不适用于包体。

PROCEDURE Proc_Name IS
tDate Date;
BEGIN
SELECT MAX(date_) into tDate from Table_Name;

【问题讨论】:

    标签: sql oracle variables plsql oracle11g


    【解决方案1】:

    直接选择变量时需要使用INTO

    select MAX(date_) 
    INTO tDate
    from Table_Name;
    

    【讨论】:

    • 感谢您的快速响应。我可以让它适用于存储过程,但不适用于包。 PROCEDURE Name_ 是 tDate DATE; BEGIN SELECT INTO tDate 等...但不适用于 PACKAGE BODY Package_Name tDate DATE; SELECT MAX(date_) INTO 等....
    • 一个包体应该包含过程和函数定义,它本身不是一个 PL/SQL 块。 tDate 声明作为包的全局变量是有效的,但 SELECT 应该出现在过程或函数中。
    【解决方案2】:

    你需要在你的包体中创建一个包初始化块。这是一个相对神秘的 PL/SQL 包知识,但它存在并且可以使用。这是一个例子:

    CREATE OR REPLACE PACKAGE TEST_PKG IS
      tDate  DATE;
    END TEST_PKG;
    

    在这里,我们创建了一个仅包含一个 DATE 变量的包规范。现在我们将创建一个简单的主体,使用 SELECT 语句初始化该变量:

    CREATE OR REPLACE PACKAGE BODY TEST_PKG IS
      -- package-private variables go first (if any)
    (...) 
      -- then the public functions/procedures
    (...)
      -- then a final BEGIN-END block which is the package initialization block
    BEGIN
      SELECT SYSDATE
        INTO tDATE
        FROM DUAL;
    EXCEPTION  -- you can have exception handlers in your initialization block
      WHEN OTHERS THEN
        NULL;  -- pointless here, but this is just an example
        RAISE;
    END TEST_PKG;
    

    现在如果你执行以下操作:

    begin
      -- Test statements here
      DBMS_OUTPUT.PUT_LINE('TEST_PKG.tDate = ' || TEST_PKG.tDate);
    end;
    

    它应该打印当前日期。

    分享和享受。

    【讨论】:

    • 感谢您回答我的问题。尽管我无法将其装入我的包裹中,但这绝对看起来应该可以工作。我收到“遇到符号'CREATE'”错误。当我尝试包含包体时。这可能只是我的环境的问题。我仍然不明白他们为什么这样做,以便我可以通过查询分配硬编码值但不是有效值。为什么我必须实现这个“神秘”方法来设置变量值?再次感谢。
    • 包规格和正文需要单独创建。所以你应该有CREATE OR REPLACE PACKAGE MY_PACKAGE...END MY_PACKAGE;,后跟CREATE OR REPLACE PACKAGE BODY MY_PACKAGE...END MY_PACKAGE;。至于“为什么我必须...” - 长答案是您不能在变量初始化中使用可执行语句,例如 SELECT,这正是包初始化程序块存在的原因 - 这样您就可以在会话访问为会话初始化包变量的包时执行代码。简短的回答是“因为你必须”。 :-) 分享和享受。
    • 感谢您解释原因,尽管长短答案似乎都是:“为什么?因为它是科学,这就是为什么!” F博士我仍然遇到问题,但我会四处询问并重新阅读有关 oracle 包构造的规范,我可能会在周末解决。
    • 我不明白您为什么将变量声明从包主体移到规范中。它可以是任何一个地方,具体取决于您是否希望它对外界可见。初始化。
    • @ShannonSeverance - 仅出于示例目的 - 我想展示一个创建规范和正文的示例,因此在规范中创建了变量。当然,您是正确的,初始化块可以处理在任一位置声明的变量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    相关资源
    最近更新 更多