ネストされたループ内の単一のsqliteデータベースで複数のカーソルを使用する際に問題が発生しました。私は自分に合った解決策を見つけましたが、それは限られており、この特定の問題がオンラインで文書化されているのを見たことがありません。私はこれを投稿しています:
- 明確な問題/解決策が利用可能です
- より良い解決策があるかどうかを確認するには
- おそらく私は
sqlite3
Pythonモジュールに欠陥を見つけました
私のPythonアプリは、社会関係データをsqliteに保存しています。データセットには、myConnectionsとsharedConnectionsの2つのテーブル間の1対多の関係が含まれています。前者には、接続ごとに1つの行があります。sharedConnectionsテーブルには、共有される接続の数に応じて、0:N行があります。構造を構築するために、ネストされたループを使用します。外側のループでは、myConnectionsの各行にアクセスします。内側のループで、sharedConnectionsテーブルにデータを入力します。コードは次のようになります。
curOuter = db.cursor()
for row in curOuter.execute('SELECT * FROM myConnections'):
id = row[0]
curInner = db.cursor()
scList = retrieve_shared_connections(id)
for sc in scList:
curInner.execute('''INSERT INTO sharedConnections(IdConnectedToMe, IdShared) VALUES (?,?)''', (id,sc))
db.commit()
結果は奇妙です。テーブルは、の最初の2つのレコードのsharedConnections
重複エントリを取得しますmyConnections
。それらは少し照合されています。Aの接続、Bの接続、A、Bの順に続きます。最初のスタッターの後、処理は正しいです!例:
myConnections
-------------
a
b
c
d
sharedConnections
-------------
a->b
a->c
b->c
b->d
a->b
a->c
b->c
b->d
解決策は不完全です。外側のループカーソルからイテレータを使用する代わりに、I SELECT
、次にfetchall()
、結果のリストをループします。私のデータセットはかなり小さいので、これは問題ありません。
curOuter = db.cursor()
curOuter.execute('SELECT * FROM myConnections'):
rows = curOuter.fetchall()
for row in rows:
id = row[0]
curInner = db.cursor()
scList = retrieve_shared_connections(id)
for sc in scList:
curInner.execute('''INSERT INTO sharedConnections(IdConnectedToMe, IdShared) VALUES (?,?)''', (id,sc))
db.commit()
そこにあります。ネストされたループ内の同じsqliteデータベース内の異なるテーブルに対して2つのカーソルを使用することは、機能していないようです。さらに、失敗することはなく、奇妙な結果をもたらすだけです。
- これは本当に最良の解決策ですか?
- より良い解決策はありますか?
- これは対処すべき欠陥ですか?