9

我正在使用 python 将带有特殊字符的字符串插入 MySQL。

要插入的字符串如下所示:

macaddress_eth0;00:1E:68:C6:09:A0;macaddress_eth1;00:1E:68:C6:09:A1

这是SQL:

UPGRADE inventory_server 
set server_mac = macaddress\_eth0\;00\:1E\:68\:C6\:09\:A0\;macaddress\_eth1\;00\:1E\:68\:C6\:09\:A1' 
where server_name = 'myhost.fqdn.com

当我执行更新时,我收到此错误:

ERROR 1064 (42000): 
You have an error in your SQL syntax; check the manual that corresponds to your 
MySQL server version for the right syntax to use near 'UPGRADE inventory_server 
set server_mac = 'macaddress\_eth0\;00\:1E\:68\:C6\:09\' at line 1

蟒蛇代码:

sql = 'UPGRADE inventory_server set server_mac = \'%s\' where server_name = \'%s\'' % (str(mydb.escape_string(macs)),host)
print sql

try:
    con = mydb.connect(DBHOST,DBUSER,DBPASS,DB);
    with con:
       cur = con.cursor(mydb.cursors.DictCursor)
       cur.execute(sql)
   con.commit()
except:
return False

我怎样才能插入这个文本原始?

4

4 回答 4

15

这是您应该使用参数绑定而不是在 Python 中格式化参数的原因之一。

只需这样做:

sql = 'UPGRADE inventory_server set server_mac = %s where server_name = %s'

然后:

cur.execute(sql, macs, host)

这样,您可以将字符串作为字符串处理,并让 MySQL 库为您找出如何引用和转义它。

最重要的是,您通常可以获得更好的性能(因为 MySQL 可以编译和缓存一个查询并将其重用于不同的参数值)并避免SQL 注入攻击(让自己被黑客入侵的最常见方法之一)。

于 2013-04-03T22:03:08.713 回答
6

欢迎来到字符串编码格式的世界!

tl;dr - 在 MySQL 列中存储数据时处理引号和转义字符的首选方法是使用参数化查询并让 MySQLDatabase 驱动程序处理它。或者,您可以通过在插入之前将引号和斜杠加倍来转义它们。

链接底部的完整示例

标准 SQL 更新

# as_json must have escape slashes and quotes doubled
query = """\
        UPDATE json_sandbox
        SET data = '{}'
        WHERE id = 1;
    """.format(as_json)

with DBConn(*client.conn_args) as c:
    c.cursor.execute(query)
    c.connection.commit()

参数化 SQL 更新

# SQL Driver will do the escaping for you
query = """\
        UPDATE json_sandbox
        SET data = %s
        WHERE id = %s;
    """

with DBConn(*client.conn_args) as c:
    c.cursor.execute(query, (as_json, 1))
    c.connection.commit()

无效的 JSON SQL

{
  "abc": 123,
  "quotes": "ain't it great",
  "multiLine1": "hello\nworld",
  "multiLine3": "hello\r\nuniverse\r\n"
}

有效的 JSON SQL

{
  "abc": 123,
  "quotes": "ain''t it great",
  "multiLine1": "hello\\nworld",
  "multiLine3": "hello\\r\\nuniverse\\r\\n"
}

Python转换:

# must escape the escape characters, so each slash is doubled
# Some MySQL Python libraries also have an escape() or escape_string() method.
as_json = json.dumps(payload) \
    .replace("'", "''") \
    .replace('\\', '\\\\')

完整示例

import json
import yaml

from DataAccessLayer.mysql_va import get_sql_client, DBConn

client = get_sql_client()

def encode_and_store(payload):
    as_json = json.dumps(payload) \
        .replace("'", "''") \
        .replace('\\', '\\\\')

    query = """\
            UPDATE json_sandbox
            SET data = '{}'
            WHERE id = 1;
        """.format(as_json)

    with DBConn(*client.conn_args) as c:
        c.cursor.execute(query)
        c.connection.commit()

    return

def encode_and_store_2(payload):
    as_json = json.dumps(payload)

    query = """\
            UPDATE json_sandbox
            SET data = %s
            WHERE id = %s;
        """

    with DBConn(*client.conn_args) as c:
        c.cursor.execute(query, (as_json, 1))
        c.connection.commit()

    return


def retrieve_and_decode():
    query = """
        SELECT * FROM json_sandbox
        WHERE id = 1
    """

    with DBConn(*client.conn_args) as cnx:
        cursor = cnx.dict_cursor
        cursor.execute(query)

        rows = cursor.fetchall()


    as_json = rows[0].get('data')

    payload = yaml.safe_load(as_json)
    return payload



if __name__ == '__main__':

    payload = {
        "abc": 123,
        "quotes": "ain't it great",
        "multiLine1": "hello\nworld",
        "multiLine2": """
            hello
            world
        """,
        "multiLine3": "hello\r\nuniverse\r\n"
    }


    encode_and_store(payload)
    output_a = retrieve_and_decode()

    encode_and_store_2(payload)
    output_b = retrieve_and_decode()

    print("original: {}".format(payload))
    print("method_a: {}".format(output_a))
    print("method_b: {}".format(output_b))

    print('')
    print(output_a['multiLine1'])

    print('')
    print(output_b['multiLine2'])

    print('\nAll Equal?: {}'.format(payload == output_a == output_b))

于 2019-09-26T14:56:15.783 回答
2

Python 示例如何插入原始文本:

在 MySQL 中创建一个表:

create table penguins(id int primary key auto_increment, msg VARCHAR(4000))

Python代码:

#!/usr/bin/env python
import sqlalchemy
from sqlalchemy import text

engine = sqlalchemy.create_engine(
    "mysql+mysqlconnector://yourusername:yourpassword@yourhostname.com/your_database")
db = engine.connect()

weird_string = "~!@#$%^&*()_+`1234567890-={}|[]\;':\""

sql = text('INSERT INTO penguins (msg) VALUES (:msg)')
insert = db.execute(sql, msg=weird_string)

db.close()

运行它,检查输出:

select * from penguins

1      ~!@#$%^&*()_+`1234567890-={}|[]\;\':"

插入时没有解释这些字符。

于 2014-11-20T15:06:34.483 回答
2

虽然我也觉得应该使用参数绑定,但是还有这个:

>>> import MySQLdb
>>> example = r"""I don't like "special" chars ¯\_(ツ)_/¯"""
>>> example
'I don\'t like "special" chars \xc2\xaf\\_(\xe3\x83\x84)_/\xc2\xaf'
>>> MySQLdb.escape_string(example)
'I don\\\'t like \\"special\\" chars \xc2\xaf\\\\_(\xe3\x83\x84)_/\xc2\xaf'
于 2017-08-03T13:55:35.340 回答