如何在Python中检查和执行SQL语句

时间:2012-01-15 23:12:29

标签: python mysql sql

我在Python中使用MySQLdb。我被告知要正确创建SQL语句并避免SQL注入攻击,我应该编写类似的代码:

sql = "insert into table VALUES ( %s, %s, %s )"
args = var1, var2, var3
cursor.execute( sql, args )

或者:

cursor.execute( "insert into table VALUES ( %s, %s, %s )", var1, var2, var3 )

甚至这个(这可能是错的):

header = ( 'id', 'first_name', 'last_name' )
values = ( '12', 'bob'       , 'smith'     )
cursor.execute( "insert into table ( %s ) values ( %s )", ( header + values ) )

当我在PHP中编程时,我通常将整个SQL语句存储为长字符串然后执行字符串。像(使用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 );

其中db_prep_string

function db_prep_string( $value ) {
    if( 
        !isset( $value ) ||
        (is_null($value)) ||
        preg_match( '/^\s+$/', $value ) ||
        ( $value == '' )
     ) {
    $value = 'null';
}
else {
    $value = "'$value'";
}
    return $value;
}

然后调试,我可以简单地回显$query来查看整个SQL语句。我可以用Python做类似的事吗?换句话说,我可以将安全 SQL语句存储为字符串,将其打印到调试,然后执行吗?

我想做点什么:

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 )        

如果没有,那么我如何在Python中查看整个SQL语句?

奖金问题:如何使用Python在SQL语句中输入空值?

2 个答案:

答案 0 :(得分:3)

在回答您的一些问题时,请查看Python Database API specification。例如,在NULL值上,API规范说明了这一点:

  

SQL NULL值由Python None单例表示       输入和输出。

并且在参数样式上,规范为实现者提供了多个选项,包括MySQLdb使用的'format'选项。

如果你想看看MySQLdb将对你的数据库执行什么查询,你可以作弊并使用连接literal(...)方法。例如:

>>> import MySQLdb
>>> db = MySQLdb.connect(...)
>>> print "insert into table VALUES ( %s, %s, %s )" % db.literal((5, "ab'c", None))
insert into table VALUES ( 5, 'ab\\'c', NULL )

但是db.literal(...)方法实际上并不是由MySQLdb模块的客户端使用,所以不要将它放在生产代码中。

另请注意,MySQLdb documentation可以说明参数:

  

参数占位符只能用于插入列值。它们不能用于SQL的其他部分,例如表名,语句等。

请注意在insert语句中使用参数占位符作为表的列名。

答案 1 :(得分:-2)

您想要执行的代码是有效的。你可以这样做:

def prevent_sql_injection_string( value ):
    if (value is None or str(value).strip()=''):
        value = 'null'
    else:
        value = "'%s'" % str(value)
    return value    

# convert inputs
id         = prevent_sql_injection_string( id         )
first_name = prevent_sql_injection_string( first_name )
last_name  = prevent_sql_injection_string( last_name  )

# construct query
# Note: "some formatted string" % (value,value,value) syntax is like doing
# printf("some formatted string",value,value,value)
sql = "insert into table (id, first_name, last_name ) values (%s, %s, %s)" 
         % (id,first_name,last_name)

# print
print sql

# execute
cursor.execute(sql)