Prepared statement
In database management systems, a prepared statement or parameterized statement is a feature used to execute the same or similar database statements repeatedly with high efficiency. Typically used with SQL statements such as queries or updates, the prepared statement takes the form of a template into which certain constant values are substituted during each execution.
The typical workflow of using a prepared statement is as follows:
- Prepare: At first, the application creates the statement template and sends it to the DBMS. Certain values are left unspecified, called parameters, placeholders or bind variables :
- :
- Then, the DBMS compiles the statement template, and stores the result without executing it.
- Execute: At a later time, the application supplies values for the parameters of the statement template, and the DBMS executes the statement. The application may execute the statement as many times as it wants with different values. In the above example, it might initially supply "bike" for the first parameter and "10900" for the second parameter, and then later supply "shoes" for the first parameter and "7400" for the second parameter.
- The overhead of compiling the statement is incurred only once, although the statement is executed multiple times. However not all optimization can be performed at the time the statement template is compiled, for two reasons: the best plan may depend on the specific values of the parameters, and the best plan may change as tables and indexes change over time.
- Prepared statements are resilient against SQL injection because values which are transmitted later using a different protocol are not compiled like the statement template. If the statement template is not derived from external input, SQL injection cannot occur.
A stored procedure, which is also precompiled and stored on the server for later execution, has similar advantages. Unlike a stored procedure, a prepared statement is not normally written in a procedural language and cannot use or modify variables or use control flow structures, relying instead on the declarative database query language. Due to their simplicity and client-side emulation, prepared statements are more portable across vendors.
Software support
Major DBMSs, including MySQL, Oracle, DB2, Microsoft SQL Server and PostgreSQL widely support prepared statements. Prepared statements are normally executed through a non-SQL binary protocol for efficiency and protection from SQL injection, but with some DBMSs such as MySQL prepared statements are also available using a SQL syntax for debugging purposes.A number of programming languages support prepared statements in their standard libraries and will emulate them on the client side even if the underlying DBMS does not support them, including Java's JDBC, Perl's DBI, PHP's PDO and Python's DB-API. Client-side emulation can be faster for queries which are executed only once, by reducing the number of round trips to the server, but is usually slower for queries executed many times. It resists SQL injection attacks equally effectively.
Many types of SQL injection attacks can be eliminated by disabling literals, effectively requiring the use of prepared statements; only H2 supports this feature.
Examples
Java JDBC
This example uses Java and JDBC:import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Main
Java
PreparedStatement
provides "setters", setString, setDouble for all major built-in data types.PHP PDO
This example uses PHP and PDO:try catch
Perl DBI
This example uses Perl and DBI:- !/usr/bin/perl -w
use DBI;
my = ;
my $dbh = DBI->connect
or die "ERROR while connecting to database $db_name: ".
$DBI::errstr. "\n";
$dbh->do;
my $sth = $dbh->prepare;
$sth->execute foreach , , ;
$sth = $dbh->prepare;
$sth->execute;
print "$$_\n" foreach $sth->fetchrow_arrayref;
$sth->finish;
$dbh->disconnect;
C# ADO.NET
This example uses C# and ADO.NET:using )
ADO.NET
SqlCommand
will accept any type for the value
parameter of AddWithValue
, and type conversion occurs automatically. Note the use of "named parameters" rather than "?"
—this allows you to use a parameter multiple times and in any arbitrary order within the query command text.However, the AddWithValue method should not be used with variable length data types, like varchar and nvarchar. This is because.NET assumes the length of the parameter to be the length of the given value, rather than getting the actual length from the database via reflection. The consequence of this is that a different query plan is compiled and stored for each different length. In general, the maximum number of "duplicate" plans is the product of the lengths of the variable length columns as specified in the database. For this reason, it is important to use the standard Add method for variable length columns:
, where ParamLength is the length as specified in the database.
Since the standard Add method needs to be used for variable length data types, it is a good habit to use it for all parameter types.
Python DB-API
This example uses Python and DB-API:import mysql.connector
conn = None
cursor = None
try:
conn = mysql.connector.connect
cursor = conn.cursor
cursor.execute
params =
cursor.executemany
params =
cursor.execute
finally:
if cursor is not None:
cursor.close
if conn is not None:
conn.close
Magic Direct SQL
This example uses Direct SQL from Fourth generation language like eDeveloper, uniPaaS and magic XPA from Magic Software EnterprisesVirtual username Alpha 20 init: 'sister'
Virtual password Alpha 20 init: 'yellow'
SQL Command:
Input Arguments:
1: username
2: password
PureBasic
can manage 7 types of link with the following commandsSetDatabaseBlob, SetDatabaseDouble, SetDatabaseFloat, SetDatabaseLong, SetDatabaseNull, SetDatabaseQuad, SetDatabaseString
There are 2 different methods depending on the type of database
For SQLite, ODBC, MariaDB/Mysql use: ?
SetDatabaseString
If DatabaseQuery
;...
EndIf
For PostgreSQL use: $1, $2, $3,...
SetDatabaseString ; -> $1
SetDatabaseString ; -> $2
SetDatabaseLong ; -> $3
If DatabaseQuery
;...
EndIf