2016-12-21 4 views
0

私はクローンローにプログラムを作成しています。それは私の行を選択し、いくつかの値を編集し、それらを挿入して戻って動作します。結果セットをループしている間に行を挿入する

また、私は後で他のリンクテーブルをクローンすることができるように、新しく挿入されたrowIDsを既存のものと一緒に保存する必要があります。

私のコードは次のようになります。

import mysql.connector 
from collections import namedtuple 

con = mysql.connector.connect(host='127.0.0.1') 
selector = con.cursor(prepared=True) 
insertor = con.cursor(prepared=True) 

user_map = {} 
selector.execute('SELECT * FROM users WHERE companyID = ?', (56,)) 
Row = namedtuple('users', selector.column_names) 

for row in selector: 
    curr_row = Row._make(row) 
    new_row = curr_row._replace(userID=None, companyID=95) 

    insertor.execute('INSERT INTO users VALUES(?,?,?,?)', tuple(new_row)) 
    user_map[curr_row.userID] = insertor.lastrowid 

selector.close() 
insertor.close() 

このコードを実行すると、私は次のエラーを取得する:

mysql.connector.errors.InternalError: Unread result found

私はINSERTを実行しようとしていますので、これはあると仮定しています私はまだSELECTをループしていますが、しかし私は2つのカーソルを使ってそれを修正すると考えました。なぜ複数のカーソルでこのエラーが発生するのですか?

fetchall()を使用して解決策を見つけましたが、あまりにも多くのメモリを使用すると、SELECTから返された何千もの結果がある可能性があります。

import mysql.connector 
from collections import namedtuple 

con = mysql.connector.connect(host='127.0.0.1') 
cursor = con.cursor(prepared=True) 

user_map = {} 
cursor.execute('SELECT * FROM users WHERE companyID = ?', (56,)) 
Row = namedtuple('users', cursor.column_names) 

for curr_row in map(Row._make, cursor.fetchall()): 
    new_row = curr_row._replace(userID=None, companyID=95) 

    cursor.execute('INSERT INTO users VALUES(?,?,?,?)', tuple(new_row)) 
    user_map[curr_row.userID] = cursor.lastrowid 

cursor.close() 

これは機能しますが、それほど高速ではありません。私はではないと考えていたfetchall()を使用してを使用していますが、私は完全な結果セットを取得しない場合、MySQLは私の叫び声。

全体の結果セットをフェッチなしを設定し、結果をループ行にしばらくを挿入する方法はありますか?

答えて

1

Is there a way to insert rows while looping over a result set without fetching the entire result set?

はい。読み込み用と書き込み用の2つのMySQL接続を使用します。

同じMySQLサーバーに接続しようとしているプログラムのインスタンスが何千もない場合、パフォーマンスへの影響はそれほど悪くありません。

1つの接続で結果セットが読み込まれ、もう1つは同じテーブルの末尾に行が挿入されるため、デッドロックは発生しません。新しい行を古い行と区別する方法がある場合は、挿入する行を明示的に除外できます。

多少の選択肢がないため、2つの接続によるパフォーマンスへの影響は、ある程度は重要ではありません。あなたがしたいことをやり遂げる他の唯一の方法は、プログラム内のRAMに結果セット全体をスローし、読み込みカーソルを閉じてから書き込むことです。

関連する問題