Filemaker to Python (4) - Insertを試す
中国語学習のDBのプラットフォームとして、Filemakerを使ったのはいくつか理由があるのですが、大きかったのは当時WinとMac両方の環境を使っていた事と、途中からFilemaker Goが出てきたので、そのままiPadとかでも勉強できるかも(実際にはやらなかったので、今でもこのレベルですがw)という考えたのが大きかったと思います。
その後、日本への帰国だったりで熱意が薄れ、結局3年ほど放置してしまいましたが、その後PythonやNLTKと出会って、何かゴニョゴニョしたいなという段になって、こうして資産として再利用できています。
さて、本日のお題はInsertです。
あれ?更新されない
実際にPython側からDBにエントリを追加する頻度は高くないと思いますが、間口を空けておけば、今後いろいろな形で使えるだろうということで実験してみました。
>>> cxcn = pyodbc.connect('DSN=CWord;UID=xxxxxx;PWD=xxxxxxxxxx') >>> cursor = cxcn.cursor >>> cursor = cxcn.cursor() >>> cursor.execute("insert into CWordsDB (Word, Pinyin) values ('爱国', 'ai4 guo2')") <pyodbc.Cursor object at 0x10277ff90> >>>
何でこの単語?というツッコミはさておき、さくっと戻って来ました。これだとエントリが実際に追加されたかどうかが分かりませんね。ということで、Filemaker側で確認してみたのですが、
・・・エントリが追加されていない
ダメだったらダメとなにかエラーを返しておくれよと考えること一晩(寝ただけ)。Filemaker側にWordIDという入力必須のシリアル番号を入れる項目があるのですが、ひょっとしてこいつも指定してやらないとダメなんじゃないかなどと考えてしました。
だとしても、Insertに失敗したならそれなりの情報がどこかに書き込まれるはずなのになぁ。
Commit をお忘れなく
で、一晩寝て、Google先生に尋ねてみました。もうタイトルでばれてますが、Commitしないと保存されないよという話でした。昨日の晩からSleep状態にしておいたMacから渾身の一撃を与えてみました。
>>> cxcn.commit()
はい、あっさりとエントリが追加されていました。
Filemaker側で自動入力させるような項目については、入力必須であってもPython側から値を渡してやらなくても大丈夫なようです。
ちなみに本当に入力必須な項目を忘れるとどうなるのか?Filemakerって、色んな意味で緩い(柔軟という事だよ)ので中途半端な形で登録されてしまったらどうしようと心配になったので試してみました。
>>> cursor.execute("insert into CWordsDB (Word, Pinyin) values ('', 'ying2 guo2')") Traceback (most recent call last): File "<stdin>", line 1, in <module> pyodbc.Error: ('HY000', '[HY000] [FileMaker][FileMaker] (509): Field failed required value validation test (509) (SQLExecDirectW)')
なるほど、ちゃんとエラーを返してくれるようです。必須項目の妥当性テスト(validation test)というのをやってるんですね。
ついでにコードも書いてみた
再利用も考えて、一応コードも書いてみました。
# -*- coding: utf-8 -*- import pyodbc class AccessCWordFM: def __init__(self): self.TabName = 'CWordsDB' self.DSN = 'DSN=CWord;UID=xxxxxx;PWD=xxxxxxxxxx' self.FieldList = ['Word', 'Pinyin', 'POS', 'Meaning', 'Source', 'Status', 'Batch'] self.cxcn = pyodbc.connect(self.DSN) self.cursor = self.cxcn.cursor() def add_new_cword(self, cwdata): sqlString = [] sqlString.append('insert into') sqlString.append(self.TabName) sqlString.append('(') for i in range (7): sqlString.append(self.FieldList[i]) if i < 6: sqlString.append(',') sqlString.append(')') sqlString.append('values') sqlString.append('(') for i in range(7): sqlString.append("'" + cwdata[i] +"'") if i < 6: sqlString.append(',') sqlString.append(')') sqlCommand = " ".join(sqlString) # print sqlCommand self.cursor.execute(sqlCommand) self.cxcn.commit()
もちろんInsertだけではなくてSelect用のモノなども作ってみましたが一例と言うことで。
これを使うときは、こんな感じにすれば良いと。
>>> reload(accesscwordfm) <module 'accesscwordfm' from '/Users/ken/Documents/workspace/NLTK Learning/scripts/accesscwordfm.py'> >>> from accesscwordfm import * >>> cword = AccessCWordFM() >>> cword.add_new_cword(['搬运工', 'ban1 yun4 gong1', '名詞', '運ぶ人', '本', 'New', '1']) insert into CWordsDB ( Word , Pinyin , POS , Meaning , Source , Status , Batch ) values ( '搬运工' , 'ban1 yun4 gong1' , '名詞' , '運ぶ人' , '本' , 'New' , '1' )
最初のReloadは、ソース直した後に読み込んだから。通常はimportでOKですね。あとは、生成されたSQL文が見たかったのでPrint文が追加してあります。個人的には、" ".join(x)にこんな使い方が出来たとはというのがツボだったりします(笑)。
イメージとしては、外部ファイルを読み込んでそれをリストに形成してあげる。そのリストをパラメータにして、このファンクションを呼んでDBに登録するという流れになるかと思います。もちろん、それの前に妥当性&重複チェックを組み込む必要はあるだろうし、複数レコード処理を想定した場合は、Commit()はこのファンクションから外出しして、処理が終わったところ(or 任意のタイミング)でCommit出来た方が良いかも知れませんね。
あと、それとなくスルーしていた文字コードの問題とかも。。。
・・・・先は長いっすな。