pymysql中的Unicode值插入查询

时间:2018-02-12 15:24:09

标签: python mysql unicode pymysql

我正在尝试使用pymysql插入Unicode值并在WITH XMLNAMESPACES ('87jjhanM' AS n) SELECT A.value('.', 'VARCHAR(100)') AS [Field] FROM TBL CROSS APPLY [xml].nodes('/n:START/Send/Supplier/Deals/Deal/*[local-name()="Field1" or local-name()="Field2"]') x(A); 查询中出现语法错误。但是当我使用utf8对值进行编码时,它可以正常工作,这是我不想要的。

这是我的代码:

Field

这会引发语法错误,

  

pymysql.err.ProgrammingError:(1064,u“你的SQL语法有错误;请查看与你的MySQL服务器版本相对应的手册,以便在''第4章'附近使用正确的语法,u'Objective: \ r \ n \ r \ n *退出使用\ u'在第1行“

之前完成的任何mininet发布

当我使用utf8对值进行编码时,插入成功,但这也会对像\ u201cmn \ u2013c \ u201d这样的值进行编码,而我的应用无法对其进行解码。

我需要一个解决方案来将我的unicode值插入我的MySQL数据库中。

任何人,请帮忙。

1 个答案:

答案 0 :(得分:0)

"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语法非常不同,所以只需切换列表repr用[1:-1]包装方括号并不接近制作这个SQL:

  • u'...'不是有效的SQL字符串文字;
  • 即使您编码为UTF-8,因此您获得了Python 2字节字符串文字'...',语法在几个方面与SQL不同,因此它有时只能工作;
  • 例如反斜杠语法\\r不是SQL字符串文字中的转义符;
  • datetime.datetime是一种Python数据类型,而不是SQL数据类型。

主要的错误是尝试将您的值包含在查询字符串本身中。即使您单独手动格式化值,您仍然有可能会错误地获取确切的语法/转义规则,并最终导致SQL注入安全漏洞。

相反,您应该使用参数化查询,将第二个参数中的参数值列表传递给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不同,%s中的params_str是真正的百分比然后s序列,而不是被替换掉的东西。它会作为execute()中相应参数值的占位符传递给vals

参数占位符看起来与字符串格式化占位符相同,但p paramstyle pymysql选择了CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,这非常令人困惑。其他DBAPI模块也不同。

也没有解决:我们没有转义表名或列名,如果使用SQL关键字会出错,如果这些名称来自不受信任的输入,也会导致SQL注入漏洞,尽管这是比价值更不常见。通常,要转义模式名称,请将它们用双引号括起来,内部使用双引号和双引号,但MySQL可能需要反引号,具体取决于它的配置方式。

所有这些复杂性都是使用现有数据访问层的好主意,为您解决这个问题。

  

我需要一个解决方案来将我的unicode值插入我的MySQL数据库中。

除了此处的DBAPI层问题之外,您还需要确保使用支持所有字符的排序规则对您拥有的表/列进行编码。这里的默认默认设置是创建Latin-1-Swedish表,这是无用的。

您可以在CREATE TABLE中的每个字符串列定义中包含CREATE DATABASE,或在创建表格之前在初始type A e = Array Int e data Cartesian v = Cartesian { _dimensions :: [Int] , _values :: A v } deriving (Show, Eq, Ord, Functor, Foldable, Traversable) -- # Some helper functions. autoListArray :: [a] -> A a autoListArray xs = listArray (0, pred (length xs)) xs -- | Get elements of an array such that they all belong to the -- congruence class c modulo n. getByCongruentIndices :: Int -> Int -> A v -> [v] getByCongruentIndices n c arr = let (low, high) = bounds arr in (arr !) <$> [low + c, low + c + n.. high] arr :: [v] -> A v arr = autoListArray unarr :: A v -> [v] unarr = elems congr :: Int -> Int -> A v -> [v] congr = getByCongruentIndices congr0 :: Int -> A v -> [v] congr0 n = congr n 0 中添加。{/ p>