簡體   English   中英

pymysql中的Unicode值插入查詢

[英]Unicode values in pymysql insert query

我正在嘗試使用pymysql插入Unicode值,並在INSERT查詢中出現語法錯誤。 但是,當我用utf8編碼值時,它可以正常工作,而我不希望這樣做。

這是我的代碼:

from pymysql.cursors import *
import pymysql
from collections import OrderedDict
import datetime

class OrderedDictCursor(DictCursorMixin, Cursor):
    dict_type = OrderedDict

conn1 = pymysql.connect(host='127.0.0.1',
                       port=3306,
                       user='root',
                       passwd='pwd',
                       db='test',
                       charset='utf8',
                       use_unicode=True,
                       autocommit=True)

cursor1 = conn1.cursor(OrderedDictCursor)
odict = OrderedDict([(u'id', 374), (u'title', u'Chapter 4'), (u'intro_list', u'Objective:\r\n\r\n* Exit any mininet launch done earlier using \u201cmn \u2013c\u201d\r\n'), (u'solution', u'%%beginpanel%%\r\n\r\n## 1. net\r\n\r\n```\r\nmn -c\r\n```\r\n\r\n \u201cCTRL+C\u201d \r\n\r\n%%endpanel%%\r\n'), (u'created', datetime.datetime(2017, 3, 9, 7, 58, 7)), (u'modified', datetime.datetime(2017, 8, 28, 4, 58, 15))])
cols = odict.keys()
vals = odict.values()
cursor1.execute("INSERT INTO %s (%s) VALUES (%s)" % ("test1", ",".join(cols), (str(vals)[1:-1])))

這會引發語法錯誤,因為

pymysql.err.ProgrammingError:(1064,u“您的SQL語法有誤;請查看與您的MySQL服務器版本相對應的手冊,以獲取在'第4章',u'Objective:\\ r \\附近使用的正確語法。 n \\ r \\ n *在第1行使用\\ u'退出先前完成的任何mininet啟動)

當我使用utf8對值進行編碼時,插入操作成功完成,但也會對\\ u201cmn \\ u2013c \\ u201d之類的值進行編碼,而我的應用無法對其進行解碼。

我需要一種解決方案,將unicode值直接插入MySQL數據庫。

任何人,請幫助。

"INSERT INTO %s (%s) VALUES (%s)" % ("test1", ",".join(cols), (str(vals)[1:-1]))

這是從上面的數據得出的查詢字符串:

INSERT INTO test1 (id,title,intro_list,solution,created,modified)
VALUES (
    374,
    u'Chapter 4',
    u'Objective:\\r\\n\\r\\n* Exit any mininet launch done earlier using \\u201cmn \\u2013c\\u201d\\r\\n',
    u'%%beginpanel%%\\r\\n\\r\\n## 1. net\\r\\n\\r\\n```\\r\\nmn -c\\r\\n```\\r\\n\\r\\n \\u201cCTRL+C\\u201d \\r\\n\\r\\n%%endpanel%%\\r\\n',
    datetime.datetime(2017, 3, 9, 7, 58, 7),
    datetime.datetime(2017, 8, 28, 4, 58, 15)
)

在值列表上調用str()將創建值列表的Python表示形式。 值文字的Python語法與SQL語法有很大不同,因此僅用[1:-1]切下列表代表的包裝方括號並不能接近此SQL:

  • u'...'不是有效的SQL字符串文字;
  • 即使您使用UTF-8進行編碼,所以得到的是Python 2字節字符串文字'...' ,其語法在某些方面與SQL有所不同,因此有時只能使用;
  • 例如,反斜杠語法\\\\r不能在SQL字符串文字中轉義;
  • datetime.datetime是Python數據類型,而不是SQL數據類型。

主要錯誤是試圖將值包含在查詢字符串本身中。 即使您單獨手動格式化了這些值,您仍然冒着錯誤地獲取准確的語法/轉義規則的風險,並最終導致SQL Injection安全漏洞。

相反,您應該使用參數化查詢,將第二個參數中的參數值列表傳遞給execute()

cols_str = ', '.join(cols)
params_str = ', '.join(['%s'] * len(vals))
query = 'INSERT INTO %s (%s) VALUES (%s)' % (table_name, cols_str, params_str)
cursor.execute(query, vals)

注:不像在cols_str中, %sparams_str是一個真正的百分比,然后-S序列,沒有東西被替換掉。 它被傳遞給execute()作為vals相應參數值的占位符。

參數占位符看起來與字符串格式的占位符看起來很令人困惑,但這就是pymysql選擇的paramstyle 其他DBAPI模塊是不同的。

也沒有解決:我們沒有轉義表或列的名稱,如果使用SQL關鍵字將它們轉義,並且如果這些名稱來自不受信任的輸入,也會導致SQL注入漏洞,盡管這比它不常見是為了價值。 通常,為了轉義模式名稱,可以將它們用雙引號和雙引號和雙引號引起來,但是MySQL可能需要反引號,具體取決於其配置方式。

所有這些復雜性就是為什么最好使用現有的數據訪問層為您解決這一問題的原因。

我需要一種解決方案,將unicode值直接插入MySQL數據庫。

除了此處的DBAPI層問題之外,您還需要確保使用支持所有字符的排序規則對表/列進行編碼。 這里的默認默認設置是創建Latin-1-Swedish表,這是沒有用的。

您可以在CREATE TABLE之前在CREATE TABLE或初始CREATE DATABASE CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci的每個字符串列定義中包括例如CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM