【问题标题】:How to Select a Variable As Query Result in Oracle PLSQL如何在 Oracle PLSQL 中选择变量作为查询结果
【发布时间】:2019-11-20 11:51:03
【问题描述】:

我看了又高又低,但没能弄明白。

我在 Oracle 中定义了这个函数:

FUNCTION MY_FUNCTION(
    INPUTVAR1 IN OUT NUMBER,
    INPUTVAR2 VARCHAR2
) RETURN NUMBER;

创建这个函数的人基本上是返回输入参数,如果它不为0。否则如果INPUTVAR1为0,它将返回一个新值。我想要那个新的价值。

在 T-SQL 中它是如此简单以至于愚蠢:

DECLARE @MyVar INT = 0;
SET @MyVar = MY_FUNCTION(@MyVar, NULL);
SELECT @MyVar as Result;

但在 Oracle 中,我无法弄清楚如何返回返回值作为结果。这是我目前所拥有的:

DECLARE MyVar NUMBER := 0;
BEGIN
MyVar := MY_FUNCTION(INPUTVAR1 => MyVar, INPUTVAR2 => NULL)
END;

但我不知道如何在结果中使用 MyVar。我绝对不能选择它。我试过DBMS_OUTPUT.PUT_LINE(MyVar);,但没有运气。

有人知道我如何返回MyVar 的值吗?

【问题讨论】:

  • 好像nullzero 混淆了......
  • 你是怎么运行这个的? SQL*Plus 或其他工具?另外,“返回值”是什么意思?你想在屏幕上看到它,将它返回给调用者,然后在另一个过程中使用它,...?
  • 我正在使用 Oracle SQL Developer IDE
  • 从您自己的回答来看,您似乎想要返回 result setcursor,而不是函数结果。这个问题在这里得到了回答:stackoverflow.com/a/40360471/230471(也许回答@Aleksej的问题会澄清一些事情。在另一条评论中你提到它是一个ETL工具,尽管上面你说你建议它用于SQL Developer,一个开发IDE。)
  • 你抓住了我。在将其移至我的 etl 工具之前,我在 sql developer 中进行了测试。

标签: oracle plsql


【解决方案1】:

带有 dbms_output 的原始 Oracle 代码是正确的。基本上,在调用一个函数之后,您使用分配的变量就像您为它分配了一个值(与 SQL Server 相同)。 因此,返回一个值(比如说 9)的函数调用
"x := some_function(y)" 在调用之后与编写
"x := 9" 完全相同。所以你的功能又是正确的。
但是,您表示您使用的是 SQL Developer。我的猜测是你没有打开 dbms_output 。为此,请在 SQL Developer 菜单栏上选择查看,然后单击 Dbms 输出。这将打开一个 dbms_output 窗口。但你还没有完成。在 Dbms 输出窗口中单击大的绿色 +,选择适当的模式(如果需要)并单击确定。 Dbms_output 现在将显示在该窗口中。

【讨论】:

    【解决方案2】:

    所以我找到了这个解决方案,它只有在你有 12c 或更高版本的 JDBC 驱动程序时才有效:

    DECLARE MyVar NUMBER := 0;
        rc sys_refcursor; 
    BEGIN
    MyVar := MY_FUNCTION(INPUTVAR1 => MyVar, INPUTVAR2 => NULL)
    
    open rc for SELECT MyVar FROM dual; 
    dbms_sql.return_result(rc); 
    
    END;
    

    我想认识一个人,他认为拥有一个具有 IN/OUT 参数和返回值的 FUNCTION 是个好主意。

    【讨论】:

    • 这里的12c新特性是隐式结果集。在 12c 之前,您可以显式返回 ref 游标。如何做到这一点取决于您的 ETL 框架。
    【解决方案3】:

    将函数重新定义为没有OUT 参数:

    CREATE FUNCTION MY_FUNCTION(
        INPUTVAR1 IN NUMBER,
        INPUTVAR2 IN VARCHAR2
    ) RETURN NUMBER
    IS
    BEGIN
      RETURN INPUTVAR1;
    END;
    /
    

    然后你可以在 SQL 查询中使用它:

    SELECT MY_FUNCTION( INPUTVAR1 => 0, INPUTVAR2 => NULL ) AS value
    FROM   DUAL
    

    输出:

    |价值 | | ----: | | 0 |

    db小提琴here


    更新

    如果您无法重新定义函数以删除 OUT 参数,则在其周围编写一个包装器:

    CREATE FUNCTION MY_FUNCTION_WRAPPER(
        INPUTVAR1 IN NUMBER,
        INPUTVAR2 IN VARCHAR2
    ) RETURN NUMBER
    IS
      var1 NUMBER := INPUTVAR1;
    BEGIN
      RETURN MY_FUNCTION( INPUTVAR1 => var1, INPUTVAR2 => INPUTVAR2 );
    END;
    /
    

    然后你可以从 SQL 语句中调用它:

    SELECT MY_FUNCTION_WRAPPER( INPUTVAR1 => 0, INPUTVAR2 => NULL ) AS value
    FROM   DUAL;
    

    输出:

    |价值 | | ----: | | 0 |

    db小提琴here

    【讨论】:

    • 我希望我可以删除 out 参数,但我不能,因为它会破坏任何现有的调用者。
    • @Sal 更新 - 为没有 OUT 参数的函数编写一个包装器。
    • 我希望避免创建 MY_FUNCTION2 函数,但我可能不得不这样做。我确实找到了我在这里发布的另一个解决方案,但是因为我无法更新 java 驱动程序(我正在使用第三方 ETL 工具),所以我无法使用该解决方案。
    【解决方案4】:

    dbms_output 对我来说很好用:

    create or replace FUNCTION MY_FUNCTION(
        INPUTVAR1 IN OUT NUMBER,
        INPUTVAR2 VARCHAR2
    ) RETURN NUMBER is
    begin
        if inputvar1 = 0 then
            return -1;
        else
            return inputvar1;
        end if;
    end;
    /
    
    declare
      my_var number := 0;
      my_var2 number := 0;
    begin
      my_var2 := my_function(my_var, 'A');
      dbms_output.put_line('my_var:' || my_var);
      dbms_output.put_line('my_var2:' || my_var2);
    end;
    /
    
    my_var:0
    my_var2:-1
    

    编辑:我有点担心函数中有一个 OUT 变量。这通常是编码不佳的标志,这就是我在上面使用 2 个变量的原因,因此您可以通过修改 INPUTVAR1 或使用返回值来查看该函数是“返回”新值。或两者兼而有之。

    【讨论】:

    • 这个功能是 12 年前由谁知道谁创建的。此外,dbms_output.put_line 对我不起作用,因为很遗憾我无法从我的 etl 工具访问输出缓冲区。
    【解决方案5】:

    试试这个

     DECLARE MyVar NUMBER := 0;
       varout VARCHAR2();
     BEGIN
     --MyVar := MY_FUNCTION(INPUTVAR1 => MyVar, INPUTVAR2 => NULL)
     select MY_FUNCTION(INPUTVAR1 => MyVar, INPUTVAR2 => NULL) INTO varout from dual;
      dbms_output.put_line(MyVar);
      END;
    

    【讨论】:

    • 如果函数具有OUT 参数,则不能在SQL 语句中使用该函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-14
    • 2013-04-07
    相关资源
    最近更新 更多