【问题标题】:How to return a table from a Stored Procedure to PHP如何将表从存储过程返回到 PHP
【发布时间】:2016-04-26 18:53:14
【问题描述】:

对于一个数据库项目,我需要实现一个存储过程。就我而言,我尝试获取指定订单的内容。我的存储过程如下所示:

create or replace PROCEDURE bestellinhalt (sbestellnr IN integer, rtable OUT sys_refcursor) IS
BEGIN
  OPEN rtable for SELECT beinhaltet.bestellnr,artikel.artikelname, artikel.artikelnr, beinhaltet.anzahl, artikel.preis FROM ARTIKEL, BEINHALTET WHERE ARTIKEL.ARTIKELNR = BEINHALTET.ARTIKELNR AND BEINHALTET.BESTELLNR = sbestellnr;
END;

在 SQL Developer 中,它还以表格形式返回所需的值:

但现在我不知道如何将这个表放入我的 PHP 页面。我就是这样尝试的:

    <?php
     //Handle Stored Procedure
     if (isset($_GET['bestellnr']))
     {
        //Call Stored Procedure  
        $bestellnr = intval($_GET['bestellnr']);
        $sproc = oci_parse($conn, 'begin bestellinhalt(:in, :rtable); end;');
        $returntable = oci_new_collection($conn, 'RTABLE');
        //Bind variables, p1=input (nachname), p2=output (abtnr)
        oci_bind_by_name($sproc, ':in', $bestellnr);
        oci_bind_by_name($sproc, ':rtable', $returntable);
        oci_execute($sproc);
        $conn_err=oci_error($conn);
        $proc_err=oci_error($sproc);
        //If there have been no Connection or Database errors, print department
        if(!$conn_err && !$proc_err){
           echo("Erfolg" );  // prints OUT parameter of stored procedure
        }
        else{
          //Print potential errors and warning
          echo("Fehler!");
          print($conn_err);
          print_r($proc_err);
        }  
     }
     // clean up connections
     oci_free_statement($sproc);
     oci_close($conn);
    ?>

我总是以以下错误结束:

PLS-00306:调用“BESTELLINHALT”ORA-06550 时参数的数量或类型错误

但是这个过程只需要一个输入,所以我现在有点困惑。另一个错误是"RTABLE" not found in index.php"。我以前从未使用过php。我的方法是基于这个论坛条目@oracle:

https://community.oracle.com/thread/617612?tstart=0

【问题讨论】:

    标签: php sql-server oracle stored-procedures


    【解决方案1】:

    请仔细阅读本页。我有你需要的所有答案。

    http://www.oracle.com/technetwork/articles/fuecks-sps-095636.html

    并从同一页面引用您的答案。

    CREATE OR REPLACE PACKAGE BODY blog AS
    
        /*------------------------------------------------*/
        PROCEDURE latest(
            num_entries_in IN NUMBER,
            entries_cursor_out OUT cursorType
        ) AS
    
            BEGIN
    
                OPEN entries_cursor_out FOR
                    SELECT * FROM blogs WHERE rownum < num_entries_in
                    ORDER BY date_published DESC;
    
            END latest;
    
        /*------------------------------------------------*/
        PROCEDURE edit_entry(
            status_out OUT NUMBER,
            status_msg_out OUT VARCHAR2,
            id_inout IN OUT INTEGER,
            title_in IN VARCHAR2,
            text_out OUT CLOB,
            categories_in IN list_of_numbers
        ) AS
    
            ENTRY_NOT_FOUND EXCEPTION;
            entry_found INTEGER := 0;
    
            BEGIN
    
                /* Default status to success */
                status_out := 1;
    
                /* If id_inout has a value then attempt to UPDATE */
                IF id_inout IS NOT NULL THEN
    
                    /* Check the id exists - raise ENTRY_NOT_FOUND if not */
                    SELECT COUNT(*) INTO entry_found
                    FROM blogs b WHERE b.id = id_inout;
                    IF entry_found != 1 THEN RAISE ENTRY_NOT_FOUND; END IF;
    
                    /* Update the blogs table returning the CLOB field */
                    UPDATE blogs b SET b.title = title_in, b.text = EMPTY_CLOB()
                    WHERE b.id = id_inout RETURNING b.text INTO text_out;
    
                    /* Remove any existing relationships to categories
                       - new categories inserted below */
                    DELETE FROM blogs_to_categories WHERE blog_id = id_inout;
    
                    status_msg_out := 'Blog entry ' || id_inout || ' updated';
    
                /* id_inout was null so INSERT new record */
                ELSE
    
                    INSERT INTO blogs b ( b.id, b.title, b.date_published, b.text )
                    VALUES ( blog_id_seq.nextval, title_in, SYSDATE, EMPTY_CLOB() )
                    RETURNING b.id, b.text INTO id_inout, text_out;
    
                    status_msg_out := 'Blog entry ' || id_inout || ' inserted';
    
                END IF;
    
                /* Now handle assignment to categories.
                   Loop over the categories_in collection,
                   inserting the new category assignments */
                FOR i IN 1 .. categories_in.count
                    LOOP
                        INSERT INTO blogs_to_categories (blog_id,category_id)
                        VALUES (id_inout,categories_in(i));
                    END LOOP;
    
                status_msg_out := status_msg_out || ' - added to '
                                  || categories_in.count || ' categories';
    
                EXCEPTION
                    /* Catch the exception when id_inout not found */
                    WHEN ENTRY_NOT_FOUND THEN
                        status_out := -1001;
                        status_msg_out := 'No entry found in table blogs with id = '
                                          || id_inout;
                    /* Catch any other exceptions raised by Oracle */
                    WHEN OTHERS THEN
                        status_out := -1;
                        status_msg_out := 'Error: ' || TO_CHAR (SQLCODE) || SQLERRM;
    
            END edit_entry;
    
    END blog;
    /
    
    The underlying table structure the procedures are using is:
    
    CREATE SEQUENCE blog_id_seq
        INCREMENT BY 1;
    /
    CREATE TABLE blogs (
        id NUMBER PRIMARY KEY,
        title VARCHAR2(200),
        date_published DATE,
        text CLOB
    );
    /
    CREATE SEQUENCE category_id_seq
        INCREMENT BY 1;
    
    CREATE TABLE categories (
        id NUMBER PRIMARY KEY,
        name VARCHAR2(30) UNIQUE
    );
    /
    CREATE TABLE blogs_to_categories (
        blog_id INTEGER NOT NULL
        REFERENCES blogs(id),
        category_id INTEGER NOT NULL
        REFERENCES categories(id),
        PRIMARY KEY (blog_id, category_id)
    );
    /
    
    Stored Procedures and Reference Cursors
    
    Looking at the blog.latest procedure, you'll see it returns a reference cursor for iterating over the row in my blogs table.
    
    To work with a cursor in PHP two additional steps are required, as compared to accessing rows directly from a SELECT statement. The first step is preparing a cursor resource in PHP, using the oci_new_cursor() function, which you then use to bind to the appropriate parameter. The second step, after you have executed the SQL statement, is calling oci_execute() on the cursor resource.
    
    The following PHP script illustrates this procedure:
    
    <?php
    $conn = oci_connect('SCOTT','TIGER') or die;
    
    
    $sql = 'BEGIN blog.latest(:num_entries, :blog_entries); END;';
    
    $stmt = oci_parse($conn, $sql);
    
    // Bind the input num_entries argument to the $max_entries PHP variable
    $max_entries = 5;
    oci_bind_by_name($stmt,":num_entries",$max_entries,32);
    
    // Create a new cursor resource
    $blog_entries = oci_new_cursor($conn);
    
    // Bind the cursor resource to the Oracle argument
    oci_bind_by_name($stmt,":blog_entries",$blog_entries,-1,OCI_B_CURSOR);
    
    // Execute the statement
    oci_execute($stmt);
    
    // Execute the cursor
    oci_execute($blog_entries);
    
    print "The $max_entries most recent blog entries\n";
    
    // Use OCIFetchinto in the same way as you would with SELECT
    while ($entry = oci_fetch_assoc($blog_entries, OCI_RETURN_LOBS )) {
        print_r($entry);
    }
    ?>
    

    【讨论】:

    • 感谢您的回答,我会按照页面上的描述尝试实现它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多