I am using the MySQLdb in Python. I was told that to properly create SQL statements and to avoid SQL injection attacks I should code something like:
sql = "insert into table VALUES ( %s, %s, %s )"
args = var1, var2, var3
cursor.execute( sql, args )
Or:
cursor.execute( "insert into table VALUES ( %s, %s, %s )", var1, var2, var3 )
Or even this (this might be wrong):
header = ( 'id', 'first_name', 'last_name' )
values = ( '12', 'bob' , 'smith' )
cursor.execute( "insert into table ( %s ) values ( %s )", ( header + values ) )
When I programmed in PHP, I would normally store my entire SQL statement as a long string then execute the string. Something like (with PostgreSQL):
$id = db_prep_string( pg_escape_string( $id ) );
$first_name = db_prep_string( pg_escape_string( $first_name ) );
$last_name = db_prep_string( pg_escape_string( $last_name ) );
$query = "insert into table ( id, first_name, last_name ) values ( $id, $first_name, $last_name )"
$result = pg_query( $con, $query );
$retval = pg_fetch_array( $result );
where db_prep_string is
function db_prep_string( $value ) {
if(
!isset( $value ) ||
(is_null($value)) ||
preg_match( '/^\s+$/', $value ) ||
( $value == '' )
) {
$value = 'null';
}
else {
$value = "'$value'";
}
return $value;
}
Then to debug, I could simply echo out $query to view the entire SQL statement. Is there something similar I can do with Python? In other words, can I store the safe SQL statement as a string, print it to debug, then execute it?
I would like to do something like:
id = prevent_sql_injection_string( id )
first_name = prevent_sql_injection_string( first_name )
last_name = prevent_sql_injection_string( last_name )
sql = "insert into table ( id, first_name, last_name ) values "
sql += id + ", "
sql += first_name + ", "
sql += last_name
print sql #for debugging
cursor.execute( sql )
If not, then how do I view the SQL statement in its entirety in Python?
Bonus question: how do I enter null values in a SQL statement using Python?
Have a look at the Python Database API specification as it answers some of your questions. For example, on NULL values the API specification says this:
and on parameter styles the specification offers multiple options to the implementer, including the
'format'option that MySQLdb uses.If you want to see what query MySQLdb will execute against your database you can cheat a little and use the connections
literal(...)method. For example:However the
db.literal(...)method isn’t really meant to be used by clients of the MySQLdb module, so don’t put it in production code.Also, note that the MySQLdb documentation has this to say about parameters:
So beware of using the parameter placeholders for the column names of a table in an insert statement.