Как проверить и выполнить операторы SQL в Python - PullRequest
1 голос
/ 16 января 2012

Я использую MySQLdb в Python. Мне сказали, что для правильного создания операторов 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-оператор safe в виде строки, распечатать его для отладки, а затем выполнить?

Я хотел бы сделать что-то вроде:

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 )        

Если нет, то как мне просмотреть оператор SQL полностью в Python?

Дополнительный вопрос: как ввести нулевые значения в оператор SQL с использованием Python?

Ответы [ 2 ]

3 голосов
/ 16 января 2012

Ознакомьтесь со спецификацией Python Database API , так как она отвечает на некоторые ваши вопросы.Например, для значений NULL в спецификации API указано следующее:

Значения SQL NULL представлены синглтоном Python None при вводе и выводе.

и при стилях параметровСпецификация предлагает множеству опций для реализатора, включая опцию 'format', которую использует MySQLdb.

Если вы хотите увидеть, какой запрос 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 имеет следующее, что можно сказать о параметрах:

Заполнители параметров могут использоваться только для вставки значений столбцов.Их нельзя использовать для других частей SQL, таких как имена таблиц, операторы и т. Д.

Поэтому остерегайтесь использования заполнителей параметров для имен столбцов таблицы в операторе вставки.

0 голосов
/ 16 января 2012

Код, который вы хотели бы сделать, действителен. Вы можете сделать что-то вроде:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...