Good Readings

Search Posts

mysqli-php-quickstart-php-stored-procedures-1

  • Quick start guide
  • Stored Procedures

  • Stored Procedures
  • Stored Procedures

    Stored Procedures

    The MySQL database supports stored procedures. A
    stored procedure is a subroutine stored in the database catalog.
    Applications can call and execute the stored procedure. The
    CALL SQL statement is used to execute a stored
    procedure.

    Parameter

    Stored procedures can have IN,
    INOUT and OUT parameters, depending on the MySQL
    version. The mysqli interface has no special notion for the
    different kinds of parameters.

    IN parameter

    Input parameters are provided with the
    CALL statement. Please, make sure values are escaped
    correctly.

    Example #1 Calling a stored procedure

    <?php
    $mysqli 
    = new mysqli("example.com""user""password""database");
    if (
    $mysqli->connect_errno) {
        echo 
    "Failed to connect to MySQL: (" $mysqli->connect_errno ") " $mysqli->connect_error;
    }

    if (!$mysqli->query("DROP TABLE IF EXISTS test") || !$mysqli->query("CREATE TABLE test(id INT)")) {
        echo 
    "Table creation failed: (" $mysqli->errno ") " $mysqli->error;
    }

    if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||
        !
    $mysqli->query("CREATE PROCEDURE p(IN id_val INT) BEGIN INSERT INTO test(id) VALUES(id_val); END;")) {
        echo 
    "Stored procedure creation failed: (" $mysqli->errno ") " $mysqli->error;
    }

    if (!$mysqli->query("CALL p(1)")) {
        echo 
    "CALL failed: (" $mysqli->errno ") " $mysqli->error;
    }

    if (!($res $mysqli->query("SELECT id FROM test"))) {
        echo 
    "SELECT failed: (" $mysqli->errno ") " $mysqli->error;
    }

    var_dump($res->fetch_assoc());
    ?>

    The above example will output:

    array(1) {
      ["id"]=>
      string(1) "1"
    }
    

    INOUT/OUT parameter

    The values of INOUT/OUT
    parameters are accessed using session variables.

    Example #2 Using session variables

    <?php
    $mysqli 
    = new mysqli("example.com""user""password""database");
    if (
    $mysqli->connect_errno) {
        echo 
    "Failed to connect to MySQL: (" $mysqli->connect_errno ") " $mysqli->connect_error;
    }

    if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||
        !
    $mysqli->query('CREATE PROCEDURE p(OUT msg VARCHAR(50)) BEGIN SELECT "Hi!" INTO msg; END;')) {
        echo 
    "Stored procedure creation failed: (" $mysqli->errno ") " $mysqli->error;
    }

    if (!$mysqli->query("SET @msg = ''") || !$mysqli->query("CALL p(@msg)")) {
        echo 
    "CALL failed: (" $mysqli->errno ") " $mysqli->error;
    }

    if (!($res $mysqli->query("SELECT @msg as _p_out"))) {
        echo 
    "Fetch failed: (" $mysqli->errno ") " $mysqli->error;
    }

    $row $res->fetch_assoc();
    echo 
    $row['_p_out'];
    ?>

    The above example will output:

    Hi!
    

    Application and framework developers may be able to
    provide a more convenient API using a mix of session variables and
    databased catalog inspection. However, please note the possible
    performance impact of a custom solution based on catalog
    inspection.

    Handling result sets

    Stored procedures can return result sets. Result
    sets returned from a stored procedure cannot be fetched correctly
    using mysqli_query(). The mysqli_query() function combines statement
    execution and fetching the first result set into a buffered result
    set, if any. However, there are additional stored procedure result
    sets hidden from the user which cause mysqli_query() to fail returning the user
    expected result sets.

    Result sets returned from a stored procedure are
    fetched using mysqli_real_query() or mysqli_multi_query(). Both functions allow
    fetching any number of result sets returned by a statement, such as
    CALL. Failing to fetch all result sets returned by a
    stored procedure causes an error.

    Example #3 Fetching results from stored
    procedures

    <?php
    $mysqli 
    = new mysqli("example.com""user""password""database");
    if (
    $mysqli->connect_errno) {
        echo 
    "Failed to connect to MySQL: (" $mysqli->connect_errno ") " $mysqli->connect_error;
    }

    if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
        !
    $mysqli->query("CREATE TABLE test(id INT)") ||
        !
    $mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)")) {
        echo 
    "Table creation failed: (" $mysqli->errno ") " $mysqli->error;
    }

    if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||
        !
    $mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;')) {
        echo 
    "Stored procedure creation failed: (" $mysqli->errno ") " $mysqli->error;
    }

    if (!$mysqli->multi_query("CALL p()")) {
        echo 
    "CALL failed: (" $mysqli->errno ") " $mysqli->error;
    }

    do {
        if ($res $mysqli->store_result()) {
            
    printf("---\n");
            
    var_dump($res->fetch_all());
            
    $res->free();
        } else {
            if (
    $mysqli->errno) {
                echo 
    "Store failed: (" $mysqli->errno ") " $mysqli->error;
            }
        }
    } while (
    $mysqli->more_results() && $mysqli->next_result());
    ?>

    The above example will output:

    ---
    array(3) {
      [0]=>
      array(1) {
        [0]=>
        string(1) "1"
      }
      [1]=>
      array(1) {
        [0]=>
        string(1) "2"
      }
      [2]=>
      array(1) {
        [0]=>
        string(1) "3"
      }
    }
    ---
    array(3) {
      [0]=>
      array(1) {
        [0]=>
        string(1) "2"
      }
      [1]=>
      array(1) {
        [0]=>
        string(1) "3"
      }
      [2]=>
      array(1) {
        [0]=>
        string(1) "4"
      }
    }
    

    Use of prepared
    statements

    No special handling is required when using the
    prepared statement interface for fetching results from the same
    stored procedure as above. The prepared statement and non-prepared
    statement interfaces are similar. Please note, that not every MYSQL
    server version may support preparing the CALL SQL
    statement.

    Example #4 Stored Procedures and Prepared
    Statements

    <?php
    $mysqli 
    = new mysqli("example.com""user""password""database");
    if (
    $mysqli->connect_errno) {
        echo 
    "Failed to connect to MySQL: (" $mysqli->connect_errno ") " $mysqli->connect_error;
    }

    if (!$mysqli->query("DROP TABLE IF EXISTS test") ||
        !
    $mysqli->query("CREATE TABLE test(id INT)") ||
        !
    $mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)")) {
        echo 
    "Table creation failed: (" $mysqli->errno ") " $mysqli->error;
    }

    if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||
        !
    $mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;')) {
        echo 
    "Stored procedure creation failed: (" $mysqli->errno ") " $mysqli->error;
    }

    if (!($stmt $mysqli->prepare("CALL p()"))) {
        echo 
    "Prepare failed: (" $mysqli->errno ") " $mysqli->error;
    }

    if (!$stmt->execute()) {
        echo 
    "Execute failed: (" $stmt->errno ") " $stmt->error;
    }

    do {
        if ($res $stmt->get_result()) {
            
    printf("---\n");
            
    var_dump(mysqli_fetch_all($res));
            
    mysqli_free_result($res);
        } else {
            if (
    $stmt->errno) {
                echo 
    "Store failed: (" $stmt->errno ") " $stmt->error;
            }
        }
    } while (
    $stmt->more_results() && $stmt->next_result());
    ?>

    Of course, use of the bind API for fetching is
    supported as well.

    Example #5 Stored Procedures and Prepared Statements
    using bind API

    <?php
    if (!($stmt $mysqli->prepare("CALL p()"))) {
        echo 
    "Prepare failed: (" $mysqli->errno ") " $mysqli->error;
    }

    if (!$stmt->execute()) {
        echo 
    "Execute failed: (" $stmt->errno ") " $stmt->error;
    }

    do {

        $id_out NULL;
        if (!
    $stmt->bind_result($id_out)) {
            echo 
    "Bind failed: (" $stmt->errno ") " $stmt->error;
        }
     
        while (
    $stmt->fetch()) {
            echo 
    "id = $id_out\n";
        }
    } while (
    $stmt->more_results() && $stmt->next_result());
    ?>

    See also