2017-04-17 118 views
1

我有以下代碼與子查詢的錯誤沒有子查詢結果的Python mysql的更新

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() 

在那裏我有我想更新和文字是一個長文本可以包含來自UTF8表中的任何條目列表。

當我運行代碼,我注意到兩兩件事:

  1. 它運行了一段時間,但沒有得到更新。
  2. 在某些時候,它與錯誤崩潰:

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

這個我不能得到它的抓地力和更我相信,只有一行被更新每個表定義的主因爲如鍵被定義爲(ENTITY_ID,REVISION_ID,δ,刪除,的langCode)

注意:此行爲是重複pymysql和與MySQL客戶端上python3.6

問候, T

+0

您是否嘗試過使用mysql命令行或其他一些GUI客戶端手動執行更新查詢? –

+0

我不能,因爲文本變量包含整個網頁的源代碼。不過,我從表中選擇了where子句,併爲每個查詢返回了1行。這意味着問題是在文本變量的某處....但是我不確定什麼 –

+0

如果文本變量包含單引號或雙引號,查詢將無法執行。由於文本是HTML,所以在存入數據庫列之前,需要對其進行編碼。 –

回答

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的方法。

+0

謝謝你的建議!但是我認爲cursor.close()和conn.close()不在它們的正確位置。我剛剛部署了2個不同的遊標和相應的關閉窗口,但它再次使用_mysql_exceptions.OperationalError崩潰:(1242,'Subquery返回多於1行') –

+0

我已閱讀您的某條評論嘗試一個select,並且它只返回「list_to_update」中的任何元素的一行。但是,也許你可以嘗試在查詢中添加「LIMIT 1」並再次嘗試。 – valeas

+0

我做了其他事情:刪除了創建問題的行。現在更新運行,但在此之後,數據庫中沒有可見的更改。 –

1

找到了答案:

原來,爲了匹配了MySQL的LONGTEXT數據庫應該使用io.String()對象傳遞文本。否則,它不會按預期行事。大多數情況下,你可以期望一個簡單的字符串將被映射到varchar,它應該在最大長度。要小心,因爲varchar can是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()

希望幫助,
託多爾