mysqli_stmt_prepare
Prepares a statement for execution. The query must consist of a single SQL statement.
The statement template can contain zero or more question mark ( ? ) parameter markers—also called placeholders. The parameter markers must be bound to application variables using mysqli_stmt_bind_param() before executing the statement.
- mysqlnd on Linux returns an error code of 1153. The error message means got a packet bigger than max_allowed_packet bytes .
- mysqlnd on Windows returns an error code 2006. This error message means server has gone away .
- libmysqlclient on all platforms returns an error code 2006. This error message means server has gone away .
Parameters
Procedural style only: A mysqli_stmt object returned by mysqli_stmt_init() .
The query, as a string. It must consist of a single SQL statement.
The SQL statement may contain zero or more parameter markers represented by question mark ( ? ) characters at the appropriate positions.
Note:
The markers are legal only in certain places in SQL statements. For example, they are permitted in the VALUES() list of an INSERT statement (to specify column values for a row), or in a comparison with a column in a WHERE clause to specify a comparison value. However, they are not permitted for identifiers (such as table or column names).
Return Values
Returns true on success or false on failure.
Errors/Exceptions
If mysqli error reporting is enabled ( MYSQLI_REPORT_ERROR ) and the requested operation fails, a warning is generated. If, in addition, the mode is set to MYSQLI_REPORT_STRICT , a mysqli_sql_exception is thrown instead.
Examples
Example #1 mysqli_stmt::prepare() example
mysqli_report ( MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT );
$mysqli = new mysqli ( «localhost» , «my_user» , «my_password» , «world» );
/* create a prepared statement */
$stmt = $mysqli -> stmt_init ();
$stmt -> prepare ( «SELECT District FROM City WHERE Name=?» );
/* bind parameters for markers */
$stmt -> bind_param ( «s» , $city );
/* execute query */
$stmt -> execute ();
/* bind result variables */
$stmt -> bind_result ( $district );
printf ( «%s is in district %s\n» , $city , $district );
mysqli_report ( MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT );
$link = mysqli_connect ( «localhost» , «my_user» , «my_password» , «world» );
/* create a prepared statement */
$stmt = mysqli_stmt_init ( $link );
mysqli_stmt_prepare ( $stmt , «SELECT District FROM City WHERE Name=?» );
/* bind parameters for markers */
mysqli_stmt_bind_param ( $stmt , «s» , $city );
/* execute query */
mysqli_stmt_execute ( $stmt );
/* bind result variables */
mysqli_stmt_bind_result ( $stmt , $district );
/* fetch value */
mysqli_stmt_fetch ( $stmt );
printf ( «%s is in district %s\n» , $city , $district );
The above examples will output:
Amersfoort is in district Utrecht
See Also
- mysqli_stmt_init() — Initializes a statement and returns an object for use with mysqli_stmt_prepare
- mysqli_stmt_execute() — Executes a prepared statement
- mysqli_stmt_fetch() — Fetch results from a prepared statement into the bound variables
- mysqli_stmt_bind_param() — Binds variables to a prepared statement as parameters
- mysqli_stmt_bind_result() — Binds variables to a prepared statement for result storage
- mysqli_stmt_get_result() — Gets a result set from a prepared statement as a mysqli_result object
- mysqli_stmt_close() — Closes a prepared statement
User Contributed Notes 9 notes
Note that if you’re using a question mark as a placeholder for a string value, you don’t surround it with quotation marks in the MySQL query.
mysqli_stmt_prepare($stmt, «SELECT * FROM foo WHERE foo.Date > ?»);
mysqli_stmt_prepare($stmt, «SELECT * FROM foo WHERE foo.Date > ‘?'»);
If you put quotation marks around a question mark in the query, then PHP doesn’t recognize the question mark as a placeholder, and then when you try to use mysqli_stmt_bind_param(), it gives an error to the effect that you have the wrong number of parameters.
The lack of quotation marks around a string placeholder is implicit in the official example on this page, but it’s not explicitly stated in the docs, and I had trouble figuring it out, so figured it was worth posting.
Turns out you can’t directly use a prepared statement for a query that has a placeholder in an IN() clause.
There are ways around that (such as constructing a string that consists of n question marks separated by commas, then using that set of placeholders in the IN() clause), but you can’t just say IN (?).
This is a MySQL restriction rather than a PHP restriction, but it’s not really documented in the MySQL docs either, so I figured it was worth mentioning here.
(Btw, turns out someone else had previously posted the info that I put in my previous comment, about not using quotation marks. Sorry for the repeat; not sure how I missed the earlier comment.)
If you select LOBs use the following order of execution or you risk mysqli allocating more memory that actually used
1)prepare()
2)execute()
3)store_result()
4)bind_result()
If you skip 3) or exchange 3) and 4) then mysqli will allocate memory for the maximal length of the column which is 255 for tinyblob, 64k for blob(still ok), 16MByte for MEDIUMBLOB — quite a lot and 4G for LONGBLOB (good if you have so much memory). Queries which use this order a bit slower when there is a LOB but this is the price of not having memory exhaustion in seconds.
If you wrap the placeholders with quotation marks you will experience warnings like «Number of variables doesn’t match number of parameters in prepared statement» (at least with INSERT Statements).
The `prepare` , `bind_param`, `bind_result`, `fetch` result, `close` stmt cycle can be tedious at times. Here is an object that does all the mysqli mumbo jumbo for you when all you want is a select leaving you to the bare essential `preparedSelect` on a prepared stmt. The method returns the result set as a 2D associative array with the `select`ed columns as keys. I havent done sufficient error-checking and it also may have some bugs. Help debug and improve on it.
class DB
public $connection ;
#establish db connection
public function __construct ( $host = «localhost» , $user = «user» , $pass = «» , $db = «bible» )
$this -> connection = new mysqli ( $host , $user , $pass , $db );
if( mysqli_connect_errno ())
echo( «Database connect Error : »
. mysqli_connect_error ( $mysqli ));
>
>
#store mysqli object
public function connect ()
return $this -> connection ;
>
#run a prepared query
public function runPreparedQuery ( $query , $params_r )
$stmt = $this -> connection -> prepare ( $query );
$this -> bindParameters ( $stmt , $params_r );
if ( $stmt -> execute ()) return $stmt ;
> else echo( «Error in $statement : »
. mysqli_error ( $this -> connection ));
return 0 ;
>
# To run a select statement with bound parameters and bound results.
# Returns an associative array two dimensional array which u can easily
# manipulate with array functions.
public function preparedSelect ( $query , $bind_params_r )
$select = $this -> runPreparedQuery ( $query , $bind_params_r );
$fields_r = $this -> fetchFields ( $select );
foreach ( $fields_r as $field ) $bind_result_r [] = &$< $field >;
>
$this -> bindResult ( $select , $bind_result_r );
$result_r = array();
$i = 0 ;
while ( $select -> fetch ()) foreach ( $fields_r as $field ) $result_r [ $i ][ $field ] = $ $field ;
>
$i ++;
>
$select -> close ();
return $result_r ;
>
#takes in array of bind parameters and binds them to result of
#executed prepared stmt
#returns a list of the selected field names
private function fetchFields ( $selectStmt )
$metadata = $selectStmt -> result_metadata ();
$fields_r = array();
while ( $field = $metadata -> fetch_field ()) $fields_r [] = $field -> name ;
>
return $fields_r ;
>
>
#end of class
#An example of the DB class in use
$DB = new DB ( «localhost» , «root» , «» , «bible» );
$var = 5 ;
$query = «SELECT abbr, name from books where id > ?» ;
$bound_params_r = array( «i» , $var );
$result_r = $DB -> preparedSelect ( $query , $bound_params_r );
#loop thru result array and display result
foreach ( $result_r as $result ) echo $result [ ‘abbr’ ] . » : » . $result [ ‘name’ ] . «
» ;
>
Prepared statements and stored procedures
Many of the more mature databases support the concept of prepared statements. What are they? They can be thought of as a kind of compiled template for the SQL that an application wants to run, that can be customized using variable parameters. Prepared statements offer two major benefits:
- The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query. For complex queries this process can take up enough time that it will noticeably slow down an application if there is a need to repeat the same query many times with different parameters. By using a prepared statement the application avoids repeating the analyze/compile/optimize cycle. This means that prepared statements use fewer resources and thus run faster.
- The parameters to prepared statements don’t need to be quoted; the driver automatically handles this. If an application exclusively uses prepared statements, the developer can be sure that no SQL injection will occur (however, if other portions of the query are being built up with unescaped input, SQL injection is still possible).
Prepared statements are so useful that they are the only feature that PDO will emulate for drivers that don’t support them. This ensures that an application will be able to use the same data access paradigm regardless of the capabilities of the database.
Example #1 Repeated inserts using prepared statements
This example performs an INSERT query by substituting a name and a value for the named placeholders.
$stmt = $dbh -> prepare ( «INSERT INTO REGISTRY (name, value) VALUES (:name, :value)» );
$stmt -> bindParam ( ‘:name’ , $name );
$stmt -> bindParam ( ‘:value’ , $value );
?php
// insert one row
$name = ‘one’ ;
$value = 1 ;
$stmt -> execute ();
// insert another row with different values
$name = ‘two’ ;
$value = 2 ;
$stmt -> execute ();
?>
Example #2 Repeated inserts using prepared statements
This example performs an INSERT query by substituting a name and a value for the positional ? placeholders.
$stmt = $dbh -> prepare ( «INSERT INTO REGISTRY (name, value) VALUES (?, ?)» );
$stmt -> bindParam ( 1 , $name );
$stmt -> bindParam ( 2 , $value );
?php
// insert one row
$name = ‘one’ ;
$value = 1 ;
$stmt -> execute ();
// insert another row with different values
$name = ‘two’ ;
$value = 2 ;
$stmt -> execute ();
?>
Example #3 Fetching data using prepared statements
This example fetches data based on a key value supplied by a form. The user input is automatically quoted, so there is no risk of a SQL injection attack.
$stmt = $dbh -> prepare ( «SELECT * FROM REGISTRY where name = ?» );
$stmt -> execute ([ $_GET [ ‘name’ ]]);
foreach ( $stmt as $row ) print_r ( $row );
>
?>?php
Example #4 Calling a stored procedure with an output parameter
If the database driver supports it, an application may also bind parameters for output as well as input. Output parameters are typically used to retrieve values from stored procedures. Output parameters are slightly more complex to use than input parameters, in that a developer must know how large a given parameter might be when they bind it. If the value turns out to be larger than the size they suggested, an error is raised.
$stmt = $dbh -> prepare ( «CALL sp_returns_string(?)» );
$stmt -> bindParam ( 1 , $return_value , PDO :: PARAM_STR , 4000 );
?php
// call the stored procedure
$stmt -> execute ();
print «procedure returned $return_value \n» ;
?>
Example #5 Calling a stored procedure with an input/output parameter
Developers may also specify parameters that hold values both input and output; the syntax is similar to output parameters. In this next example, the string ‘hello’ is passed into the stored procedure, and when it returns, hello is replaced with the return value of the procedure.
$stmt = $dbh -> prepare ( «CALL sp_takes_string_returns_string(?)» );
$value = ‘hello’ ;
$stmt -> bindParam ( 1 , $value , PDO :: PARAM_STR | PDO :: PARAM_INPUT_OUTPUT , 4000 );
?php
// call the stored procedure
$stmt -> execute ();
print «procedure returned $value \n» ;
?>
Example #6 Invalid use of placeholder
$stmt = $dbh -> prepare ( «SELECT * FROM REGISTRY where name LIKE ‘%?%'» );
$stmt -> execute ([ $_GET [ ‘name’ ]]);
?php
// placeholder must be used in the place of the whole value
$stmt = $dbh -> prepare ( «SELECT * FROM REGISTRY where name LIKE ?» );
$stmt -> execute ([ «% $_GET [ name ] %» ]);
?>