1

我有以下代码

conn = MySQLdb.connect(server, user, password, database, autocommit=True, charset='utf8')
    for e in list_to_updpate:
        nid = e[0]
        vid = e[1]
        text = e[2]
        delta = e[3]
        deleted = e[4]
        langcode = e[5]
        to_update = e[6]
        if (to_update == 1):
            with conn.cursor() as cursor:
                cursor.execute("""update node__body set body_value=%s 
                                     where entity_id=%s AND revision_id=%s AND
                                     delta=%s AND deleted=%s AND langcode=%s;""" , 
                               (MySQLdb.escape_string(text) , int(nid), 
                                int(vid), int(delta), int(deleted), langcode, ))
            conn.commit()
    conn.close()

我有要更新的条目列表,文本是一个 LONG TEXT,它可以包含 UTF8 表中的任何内容。

当我运行代码时,我注意到两件事:

  1. 它运行了一段时间,但没有任何更新。
  2. 在某些时候它会因错误而崩溃:

    _mysql_exceptions.OperationalError: (1242, 'Subquery returns more than 1 row')
    

这我无法掌握它,而且我确信只有一行得到更新,因为根据表定义,主键被定义为(entity_id,revision_id,delta,deleted,langcode)

注意:此行为在 pymysql 和 python3.6 上的 MySQL-client 中重复

问候,T

4

2 回答 2

1

找到了答案:

事实证明,为了匹配 mysql db 的 LONGTEXT,应该使用 io.String() 对象来传递文本。否则,它不会按预期运行。大多数情况下,您可以期望将一个简单的字符串映射到最大长度的 varchar。请注意,由于 varchar 可以是 LONG TEXT 的子集,因此您可以预期,如果查询提交,则不会引发错误,并且如果输入提交到数据库,则输入将被裁剪。为什么在这种特殊情况下它从未承诺(参见问题中的讨论)我仍然不清楚。现在工作代码:

conn = MySQLdb.connect(server, user, password, database, autocommit=True, charset='utf8')
for e in list_to_update:
    cursor = conn.cursor()
    nid = e[0]
    vid = e[1]
    text = e[2]
    delta = e[3]
    deleted = e[4]
    langcode = e[5]
    to_update = e[6]
    if to_update == 1:
        cursor.execute(
            "update node__body set body_value=%s where entity_id=%s AND revision_id=%s AND delta=%s AND deleted=%s AND langcode=%s",
            (io.StringIO(text), nid, vid, delta, deleted, langcode))
        conn.commit()
    cursor.close()
conn.close()

请注意,这是 Python3。对于 Python2 使用 StringIO.String()

希望有帮助,
托多

于 2017-04-17T14:58:00.363 回答
0

在发布代码之前,我想指出一些事情。

首先,不需要 escape_string,因为只要您将元组中的参数作为第二个元素包含在内,execute 就会为您完成。

我怀疑你的问题在光标附近。似乎在提交任何内容之前正在打开、使用和关闭。

如果在更新列表中的所有元素所需的时间内没有任何元素不利于打开光标,我建议使用这种方法。

conn = MySQLdb.connect(server, user, password, database, autocommit=True, charset='utf8')
cursor = conn.cursor()
for e in list_to_update:
    nid = e[0]
    vid = e[1]
    text = e[2]
    delta = e[3]
    deleted = e[4]
    langcode = e[5]
    to_update = e[6]

    if to_update == 1:
        cursor.execute("update node__body set body_value=%s where entity_id=%s AND revision_id=%s AND delta=%s AND deleted=%s AND langcode=%s" , 
                               (text , nid, vid, delta, deleted, langcode))
        conn.commit()
    cursor.close()
    conn.close()

如果您只需要进行一次提交,则在最后,您只需编辑提交行删除一个缩进即可。另外,请注意我已经添加了cursor.close,因为我没有使用这种with方法。

于 2017-04-17T13:52:15.227 回答