2009-03-12 26 views
6

経由でADOを使用してMS Accessデータベースにデータを挿入[編集2:以下の答えではより多くの情報やデバッグ...]問題のPython

私は、テキストのシリーズにMS AccessデータベースをエクスポートするPythonスクリプトを書いています既存のソリューションを使用していないのはなぜですか?制限は技術的な性質ではないと言いましょう。

私は正常にcomtypesライブラリを介してADOとADOXを使用してデータベースの完全な内容と構造をエクスポートしましたが、データを再インポートする際に問題が発生しています。

私はそうのように、各ライン上のリストをテキストファイルに各テーブルの内容をエクスポートしています:

[-9, u'No reply'] 
[1, u'My home is as clean and comfortable as I want'] 
[2, u'My home could be more clean or comfortable than it is'] 
[3, u'My home is not at all clean or comfortable'] 

と言ったファイルをインポートするには、次の機能:

import os 
import sys 
import datetime 
import comtypes.client as client 
from ADOconsts import * 
from access_consts import * 

class Db: 
    def create_table_contents(self, verbosity = 0): 
     conn = client.CreateObject("ADODB.Connection") 
     rs = client.CreateObject("ADODB.Recordset") 
     conn.ConnectionString = self.new_con_string 
     conn.Open() 
     for fname in os.listdir(self.file_path): 
      if fname.startswith("Table_"): 
       tname = fname[6:-4] 
       if verbosity > 0: 
        print "Filling table %s." % tname 
       conn.Execute("DELETE * FROM [%s];" % tname) 
       rs.Open("SELECT * FROM [%s];" % tname, conn, 
         adOpenDynamic, adLockOptimistic) 
       f = open(self.file_path + os.path.sep + fname, "r") 
       data = f.readline() 
       print repr(data) 
       while data != '': 
        data = eval(data.strip()) 
        print data[0] 
        print rs.Fields.Count 
        rs.AddNew() 
        for i in range(rs.Fields.Count): 
         if verbosity > 1: 
          print "Into field %s (type %s) insert value %s." % (
           rs.Fields[i].Name, str(rs.Fields[i].Type), 
           data[i]) 
         rs.Fields[i].Value = data[i] 
        data = f.readline() 
        print repr(data) 
        rs.Update() 
       rs.Close() 
     conn.Close() 

数値は(doubleとint)がゼロとして挿入されている以外はすべて正常に動作します。問題が自分のコード、eval、comtypes、またはADOにあるかどうかに関するアイデアはありますか?

編集:私は数字を挿入することで問題を解決しました - 文字列(!)でそれらをキャストすることは、二重フィールドと整数フィールドの両方の問題を解決するようです。

しかし、以前は上記のように不明瞭になっていた別の問題がありました。データ型に関係なく、すべての行の最初のフィールドが0に設定されています。

答えて

4

答えを見つけました。

rs = client.CreateObject("ADODB.Recordset") 

する必要があります今、私はちょうどその理由を検討する必要がある

rs = client.CreateObject("ADODB.Recordset", dynamic=True) 

。ちょうどこの質問が他の人に数時間を節約してくれることを祈っています。

+0

そして、残りの解決策は "rs.Fields [i] .Value = data [i]"を "rs.Fields [i] .Value = str(data [i])"に変更することでしたか? – BIBD

+0

いいえ、いいえ。明示的に言っておかなければならないことは、dynamic = Trueが数値の元の問題を解決し、フォローアップの問題が変数結果を解決したということです。一度それがうまくいけば、rs.Fields [i] .Value = data [i]はうまくいき、実際には数値を文字列としてキャストすると型の不一致エラーが発生しました。 – mavnn

+0

Kewl、答えにはっきりしていなかった。この時点で、私はあなた自身の答えにAcceptedと印を付けます。 – BIBD

0

data[i]は文字列として扱われますか? rs.Fields[i].Valueを設定したときにint/doubleとしてキャストするとどうなりますか?

また、rs.Fields[i].Valueの内容を設定した後で印刷するとどうなりますか?

+0

編集を参照してください - bizarrely私はint/doubleから文字列に変換する必要があります。 – mavnn

0

まだ完全な回答ではありませんが、更新中に問題が発生しているようです。私は、次の(更新されている単一の列の一例)を生成する挿入過程でいくつかのさらなるデバッグコードを追加しました:

Inserted into field ID (type 3) insert value 1, field value now 1. 
Inserted into field TextField (type 202) insert value u'Blah', field value now Blah. 
Inserted into field Numbers (type 5) insert value 55.0, field value now 55.0. 
After update: [0, u'Blah', 55.0] 

各「挿入...」行の最後の値が呼び出しの結果でありますrs.Update()を呼び出す前にrs.Fields [i] .Value。 「After ...」行は、rs.Update()を呼び出した後にrs.Fields [i] .Valueを呼び出した結果を示します。

さらに迷惑なのは、確実に失敗しないということです。同じ上の正確な同じコードを再実行すると、数分後に生成されたレコード:あなたが見ることができるようにあなたがそれらを、そして...ではないコミットするまで

Inserted into field ID (type 3) insert value 1, field value now 1. 
Inserted into field TextField (type 202) insert value u'Blah', field value now Blah. 
Inserted into field Numbers (type 5) insert value 55.0, field value now 55.0. 
After update: [1, u'Blah', 2.0] 

が、結果は信頼性があります。