【问题标题】:Can I return values to PHP from an anonymous PL/SQL block?我可以从匿名 PL/SQL 块返回值给 PHP 吗?
【发布时间】:2011-02-26 13:39:54
【问题描述】:

我正在使用 PHP 和 OCI8 来执行匿名 Oracle PL/SQL 代码块。有什么方法可以绑定变量并在块完成后获取其输出,就像我以类似方式调用存储过程一样?

$SQL = "declare
something varchar2 := 'I want this returned';
begin
  --How can I return the value of 'something' into a bound PHP variable?
end;";

【问题讨论】:

    标签: php oracle plsql oci8


    【解决方案1】:

    您可以通过在名称和数据类型声明之间使用关键字OUT 来定义输出参数。即:

    CREATE OR REPLACE PROCEDURE blah (OUT_PARAM_EXAMPLE OUT VARCHAR2) IS ...
    

    如果未指定,IN 是默认值。如果您想同时使用参数作为输入和输出,请使用:

    CREATE OR REPLACE PROCEDURE blah (INOUT_PARAM_EXAMPLE IN OUT VARCHAR2) IS ...
    

    以下示例创建一个带有 IN 和 OUT 参数的过程。然后执行该过程并打印出结果。

    <?php
       // Connect to database...
       $c = oci_connect("hr", "hr_password", "localhost/XE");
       if (!$c) {
          echo "Unable to connect: " . var_dump( oci_error() );
          die();
       }
    
       // Create database procedure...
       $s = oci_parse($c, "create procedure proc1(p1 IN number, p2 OUT number) as " .
                         "begin" .
                         "  p2 := p1 + 10;" .
                         "end;");
       oci_execute($s, OCI_DEFAULT);
    
       // Call database procedure...
       $in_var = 10;
       $s = oci_parse($c, "begin proc1(:bind1, :bind2); end;");
       oci_bind_by_name($s, ":bind1", $in_var);
       oci_bind_by_name($s, ":bind2", $out_var, 32); // 32 is the return length
       oci_execute($s, OCI_DEFAULT);
       echo "Procedure returned value: " . $out_var;
    
       // Logoff from Oracle...
       oci_free_statement($s);
       oci_close($c);
     ?>
    

    参考:

    【讨论】:

    • 存储过程是永久创建的,还是只为这个会话创建的?我已经使用这种方法从我在数据库中编译的过程中接收 OUT 参数(看起来这是在做同样的事情,除了首先创建过程)。执行此代码时,我想避免在数据库中创建任何永久对象。
    • @Renderlin:是的,来自 orafaq.com 的示例将创建存储过程。您需要将存储过程放在匿名 PLSQL 块的 DECLARE 块中,并在 BEGIN/END 部分中设置proc1(...,以免创建过程。
    • @OMGPonies 10g 不支持参数,我在读他们拿出支持!
    【解决方案2】:

    这是我的决定:

    function execute_procedure($procedure_name, array $params = array(), &$return_value = ''){
        $sql = "
        DECLARE
            ERROR_CODE      VARCHAR2(2000);
            ERROR_MSG       VARCHAR2(2000);
            RETURN_VALUE    VARCHAR2(2000);
        BEGIN ";
    
        $c = $this->get_connection();
    
        $prms = array();
        foreach($params AS $key => $value) $prms[] = ":$key";
        $prms = implode(", ", $prms);
    
        $sql .= ":RETURN_VALUE := ".$procedure_name."($prms);";
        $sql .= " END;";
    
    
        $s = oci_parse($c, $sql);
    
        foreach($params AS $key => $value)
        {
            $type = SQLT_CHR;
            if(is_array($value))
            {
                if(!isset($value['value'])) continue;
                if(!empty($value['type'])) $type = $value['type'];
                $value = $value['value'];
            }
            oci_bind_by_name($s, ":$key", $value, -1, $type);
        }
    
        oci_bind_by_name($s, ":RETURN_VALUE", $return_value, 2000);
    
        try{
            oci_execute($s);
            if(!empty($ERROR_MSG))
            {
                $data['success'] = FALSE;
                $this->errors = "Ошибка: $ERROR_CODE $ERROR_MSG";
            }
            return TRUE;
        }
        catch(ErrorException $e)
        {
            $this->errors = $e->getMessage();
            return FALSE;
        }
    }
    

    示例:

        execute_procedure('My_procedure', array('code' => 5454215), $return_value);
        echo $return_value;
    

    【讨论】:

    • 转储代码块我几乎不认为这是一个有价值的答案。请解释为什么您的代码解决了 OP 的问题。
    猜你喜欢
    • 2017-11-04
    • 2014-09-30
    • 2014-05-14
    • 2015-02-21
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 2013-05-04
    • 1970-01-01
    相关资源
    最近更新 更多