AccessとLinux

中小企業での販売管理プログラムの作成についての所感

紅楼夢

2008年05月24日 23時49分24秒 | Weblog
最近、紅楼夢を読んでいます。
三国志演義、水滸伝ばかり読んできましたが、少し飽きてきたこともあって紅楼夢を読むことにしました。

中国、四大奇書と言えば、三国志演義、水滸伝、西遊記、金瓶梅です。西遊記はごく最近、毎日新聞で平岩弓枝の連載があり読んでいましたが、妖怪とはいえ悟空がいとも簡単に殺してしまうのはどうもいただけないと思いました。金瓶梅は少女漫画でさわりだけを読みましたが、エロっぽすぎてもう一つ、乗り気がしません。あと有名なところでは紅楼夢ということになります。なんせ長編なので、いきなり、原作を読むのはためらってしまい、やはり最初は漫画(画本)から入りました。あらかた、筋がわかったところで、面白そうなので原作を読み始めました。
画本は「中央公論社 画本 紅楼夢 松枝茂夫訳」です。

手に入りやすい原作の訳本としては松枝茂夫訳のものと伊藤漱平訳のものがあります。ちなみに私は
  岩波文庫 紅楼夢 松枝茂夫訳 全12巻
  平凡社 中国古典文学大系 紅楼夢 伊藤漱平訳 上中下3巻
を持っています。
最初、古本屋で買った文庫(松枝茂夫訳)で3巻まで読んで、続きを中国古典文学大系のハードカバーで読もうとしましたが、伊藤漱平訳だと不思議と面白くないので、岩波文庫の新本を購入して8巻まで読んだところです。曹雪芹作としては8巻までです。

最近エロゲーで紅楼夢のヒロイン、林黛玉の名前を使用したものが発売され問題になりましたが、ゲームで読者を大変に増やした三国志演義と比べると日本では紅楼夢はあまりメジャーとは言えません。

三国志演義、水滸伝は確かに相当面白いですが、武将の家庭生活にはほとんどふれていません。紅楼夢はその家庭生活の部分を扱ったものです。特に水滸伝では女性はもの同然として描かれています。もしくは悪女です。紅楼夢ではその女性が主役です。金陵十二釵という12人の多才な少女、女性が登場します。だいたい中学生くらいの年齢の子が多いです。それらの女性に加えて奴隷身分の女中(これもまた美人ぞろいなのですが)に囲まれた、同じく中学生位の美少年(賈宝玉)が主役です。

ほとんど閉鎖された宏大な住居に美人姉妹と美人メイドに囲まれて気ままな生活を送っている十代の少年の日々。もちろん話はそれだけでなく、代々科挙に合格し役人家業を生業とした貴族の家庭生活でのいざこざ、不祥事が描かれています。

紅楼夢の作者、曹雪芹の家は元々、清、康煕帝の時代には隆々とした貴族で、雍正帝の時代になって家産没収の憂き目にあっており、紅楼夢はその困窮時代に書かれたものです。紅楼夢のさまざまなエピソードはある程度似たようなことがあったと考えられ、絵空事とは思われません。ほぼドキュメントと思って読んでいます。

最初に「ヘー」と思ったのは、中国の奴隷についての認識違いです。主人に生殺与奪権があり、なんら自由のない奴隷、そんな風に思っていまいしたが、家事手伝いをしている奴隷身分の女性たちはもっともっと気ままでしたたかで、主人も彼女たちの評判を大いに気にします。奴隷というより年季奉公で最初にお金をもらって、長期にわたってその家に仕えるという感じです。食事、衣類、化粧品も支給されますし、現金も出ます。貴族の家だけに食事は一般人とは違い高級ですし、住居にしても大変立派なところで清潔な生活が送れます。

彼女達にしてみれば、こんないいところを追い出されてしまうと、大変です。主人はかなり好色ですが、一応、官僚であれば外面的には君子でなければならないので、女中に法外なことはできません。一夫多妻が認められていて、ほしいと思えばチャントした第二、第三夫人としての地位を与えなかればなりません。一度、主人から目を付けられると、なかなか断るのは難しいですが、どうしてもイヤなら出家してしまうという道もあります。

主人にしてみれば、管理するだけで、直接家事を行いたくないので、女中達が不正をしないよう、気を利かせてやってくれるよう期待します。有能な女中もいれば、信頼の置けない人もいます。器量が良くて、よく気の利く良い子が女中頭になります。しかも、容姿端麗なのでお手つき女中になります。

賈家(主人公の家)では慣例として正式に結婚するまでに2人までの女中をお手つき(側室)とすることができることになっており、主人公賈宝玉にも襲人という美人女中がお手つき女中になっています。そこからお部屋様になれれば申し分ないのですが、結局、襲人は他家へ嫁ぐことになります。賈家から嫁に出してやることになるのです。この襲人は奴隷身分です。

他にも色々、面白い生活習慣、風習があって、三国志演義、水滸伝とは違った面白さがあります。

しかし、画本では賈宝玉は弁髪になっていないのですが、清朝なら弁髪だったはずで、登場人物の男性全員が弁髪なら、雰囲気が随分変わってきます。
  
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

クライアントとしてのAccess(5) レコードの更新方法について

2008年05月18日 00時28分39秒 | Weblog
Accessでは一つのことを行う場合でも色々方法があります。テーブルの更新、追加についても同様です。
DAOもあればADOもあります、Docmd.RunSQLで更新することもできるし、CurrentDB.Executeでも行えます。ここでもODBCリンクしたテーブルには制限があります。Seekメソッドが使用できないということです。

通常、Accessではテーブルに検索用インデックスを設定してSeekメソッドを使用して必要なレコードを検索してEditします。しかし、ODBCリンクしたテーブルではインデックスを設定することができないので、Findメソッドを使用することになります。Findメソッドはレコードをいちいち移動して検索することになるので時間がかかります。

Findメソッドがダメならwhere句を指定したSQLを引数としたレコードセットをオープンしてEditすれば良いのです。あるいはCurrentDB.Executeでwhere句を指定してupdateすれば良いです。

そこで、例えば条件を指定したレコードセットを開いてそのレコードセットをDo Until~Loopして特定のフィールドをwhere句の条件として指定しながら、別テーブルを更新する場合どうしたら良いかいうと、私自身はあまり考えもせず、DAOで最初のレコードセットを定義してテーブルの更新にはCurrentDB.Executeで行っていました。このコードもmougでさんざん叩かれました。「DAOとクエリーを同時に使うなんて!」(上記のDocmd.RunSQLを使うなと言った人と同一の人なんですが)

しかし、DAOとクエリーを同時に使用してもチャント処理されています。特に問題なく動作します。このコードが叩かれた背景には、叩いた本人はmdb内のテーブルを参照更新しているものだと想定しているということがあります。こちらはODBCリンクテーブルを想定しています。ODBCリンクテーブルの場合にDAOとクエリーの併用がどうしてダメなのは私には理由がわかりません。

ODBCドライバの設定でログをとることができますが、そのログを見るとサーバーデータベースとAccess間の連絡はSQL以外では行われません。Accessのリンクテーブルは自動でSQLを発行しますが、あくまでSQLです。データベースとその他の連絡手段は無いのです。まあ当然なのですが。そう考えるとDAOだろうがクエリーだろうが関係ありません。どうせSQL文に変換されるのですから。



コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

クライアントとしてのAccess(4) OpenRecordsetについて

2008年05月18日 00時28分10秒 | Weblog
ODBC経由でPostgreSQLを参照、更新していて一番不便に思うのはOpenRecordsetの引数にクエリー名が使用できないということです。SQLを自在に使用できる人なら特に問題ないのでしょうが、SQLがあまり得意でないなら、OpenRecordsetの引数にSQL文を指定しなければならないのはかなり負担です。

複雑なクエリーが必要な場合、クエリデザインを利用してクエリーのクエリーを作ってみたり、クエリー同士をjoinしたりすることは多いです。そうして作成したクエリーをOpenRecordsetの引数として使用できないとなるとやはり不便です。この点がmdb内でプログラムを作成する場合と、別途データベースサーバーを使用する場合の大きな違いです。

この対策としていくつかあります。

1.クエリデザインでクエリーを作成し、SQL表示させてそのクエリーを元に必要なクエリーを作る。
この方法はかなり有効です。クエリーのクエリーというわけには行きませんが、少なくともテーブルをjoinして条件付けした上でselectする場合や複雑な集計クエリーの場合などには有効です。

2.クエリーのクエリーや、クエリー同士をjoinしなければならない場合には、要素となっているクエリーをPostgreSQL側のviewとして定義してしまう。そのviewをテーブルとしてリンクしてクエリーを作成、1同様にSQL文を作成する。
この方法だと、リンクしたviewはAccess側では更新不可能なテーブルとして認識されます。もし、更新が必要ならPostgreSQL側でルールを作成してやります。リンクしたテーブルはAccess側では単なるテーブルなので、そのテーブルを元にしたクエリーなら1と同様にSQL文としてOpenRecordsetの引数として使用できます。

3.クエリーのクエリーや、クエリー同士をjoinしたクエリー名をフォームのレコードソースとしてオープンし、レコードセットとしてsetする。
OpenRecordsetの引数としてはODBCリンクしたテーブルを元にしたクエリー名は指定できませんが、フォームのレコードソースにはなれます。
この方法だとどんなクエリーでもレコードセットとすることができます。通常、レコードセットとして利用するためのフォームなので、表示する必要はないと思います。Hiddenとして開きます。
一端フォームとして開いてしまえば、
set rst = Form_test.Recordset
としてレコードセットとしてsetできます。
難があるとすると、フォームのオープンに時間がかかってしまうということと、デバック時にフォームが開いているので、忘れずに閉じなければならないということです。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

クライアントとしてのAccess(3) RunSQLかCurrentDB.Executeか

2008年05月18日 00時27分44秒 | Weblog
Docmd.RunSQLかCurrentDB.Executeか

いつも読んでいるmougでサンプルプログラムを含めて回答を入れたところ、Docmd.RunSQLを使用しているだけでメチャクチャな酷評をレスされたことがあります。プログラムのその他の部分もまずかったのですが、Docmd.RunSQLを使用しただけで、これほど酷評されるとは。
たしかに、mougを読んでいてDocmd.RunSQLからCurrentDB.Executeに変えた方が良いという記述はよく見ますが、その逆は一度も見たことがありません。

それ以来、Docmd.RunSQLを使用していたところをCurrentDB.Executeに書き換えていますが、よく考えてみるとDomcmd.RunSQLでも良いではないかと最近思っています。

Docmd.RunSQLとCurrentDB.Executeの差はDocmd.RunSQLが非同期実行に対してCurrentDB.Executeが同期実行だということです。実のところ、今まで、Docmd.RunSQLを使用していて特に不都合は一度もありません。敢えて同期実行するCurrentDB.Executeを使用する必要があるのでしょうか。

別途サーバー(PostgreSQL)を用意していて、クライアント側のAccessからSQLを実行する際、PostgreSQLからの終了信号を待って、次の処理を行わなければならないかといことです。このブログを書くに当たって、PostgreSQLのSQL実行順が保証されているか調べてみました。ずばりこれ、といった内容は確認できませんでしたが、pgpoolで「クエリーの実行順を保証するためには」といった文章があり、PostgreSQLでは実行順が保証されているのではないかと推測されます。

同期実行が必要なのはテーブルをupdateして、その内容を直ぐに参照して次の処理を行う場合でしょう。こういったケースがあるかどうか考えてみると、少なくともサーバーのデータに関しては思い当たりません。あえていうと、複雑なレポートを作成する際に一度、mdb内の仮テーブルにレポートのレコードソース用のテーブルを用意して印刷する場合がありますが、この場合でもDocmd.RunSQLを使用していて特に不都合があったことがありません。

同期、非同期とでは処理の終了を確認して次の処理を行う分、同期の方が遅くなるはずなのですが、実際のところ、同期、非同期の違いで処理速度の違いを体感したことはありません。そうなると、あえて非同期のDocmd.RunSQLを使用する必要もないけれど、CurrentDB.Executeでなければならない理由もないのではないかと思っています。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

クライアントとしてのAccess(2) 連結フォームか非連結フォームか?

2008年05月18日 00時26分03秒 | Weblog
やはり一番問題なのは、フォームを連結フォームとして作成するか、非連結フォームとして作成するかという問題だと思います。ここでいうフォームはデータを入力したり、編集したりする場合のフォームです。単に参照するだけのフォームは当然、連結フォームとして作成します。
以前読んだホームページでは、その人はプロのプログラマーだったようですが、「Accessで連結フォームでプログラムを書いたことがない。」という記述がありました。
mdb内(あるいはaccdb内で。以下、mdb内でとします。)でテーブルもフォームも完結している場合、よく入門書にあるように連結フォームとして作成して、レコードセレクターでレコードを選択して更新、「*」をクリックして新規作成といった方法でも可能かもしれません。しかし、本格的なデータベースのクライアントしてAccessを使用する場合、この方法はとれません。
一つにはフォームとテーブルを更新可能なフォームとして連結することで、他のクライアントとレコードがロックする可能性がかなり高くなります。また、テーブルが大きくなるとレコードセレクターでいちいちレコードを移動しならがらレコードを選択するといった作業は実用的とは言えません。フィルターをかけてレコード数を限定したとしてもやはりレコードセレクターでのレコードの移動は面倒です。
更新不可とした参照用フォームからレコードを選んで、更新フォームでは対象となる1レコードのみと連結するかどうかです。このフォームを連結フォームとするか、非連結とするかといった問題です。

パターンとしては次の3種類が考えられます。
1.データベースの1レコードのみをレコードソースとする連結フォーム
2.データベースと同じテーブル構造を持ったmdb内のテーブルと連結したフォーム
2.非連結フォーム

それぞれメリット、デメリットがあります。
1は例えば、サーバーのPostgreSQLのテーブルと1レコードのみ連結したフォームです。この方法では更新時に何らかの理由でフォームが落ちてしまっても、データは変更されています。特に、更新時にクエリーを実行しなくてもデータが変更できます。フォームを閉じてしまえば、更新処理は完了です。Accessの基本的な方法と言えます。デメリットとしては他の人がデータを更新しようとした場合、PostgreSQLのデフォルトでの設定では行ロックがかかってしまいます。設定によって行ロックをかけない方法もあるのかもしれませんが、よくわかりません。また、ロックをかけるべきだと思います。一つのレコードを全く同時に二人の人が編集しているというのは適切でないと思います。

2の方法は更新したいレコードを端末である自分のPC内に一度、取り込んでそれを編集する方法です。フォームが存在するmdb内にテーブルを用意してそのテーブルにデータを取り込みます。フォームはそのテーブルと連結します。この方法だと、フォームが落ちても編集したデータそのものはmdb内に残っています。ただし、編集終了時にはサーバーのテーブルにupdateしてやらなければなりません。この方法で気をつけなければならないのは、VBAでレコードを編集する際、あくまで連結したフォームのテキストボックスの値を書き換えてやらなければならないということです。VBAでいきなり、連結テーブルをupdateしてはいけません。こんなことをすると、フォームとコード両方でフェッチしてしまい。フォームを閉じる時、「他のユーザーが編集しています。」といったメッセージボックスが表示され、フォームで編集したデータが更新されません。あくまで、編集するのはフォームのテキストボックスです。

3番目の方法はアッサリ、非連結フォームにしてしまうという方法です。データ更新時には更新したいレコードをフォームのテキストボックスに代入してやり、終了時にはテキストボックスの値をサーバーのテーブルにupdateします。この方法だとロックがかかったり、「他のユーザーが編集しています。」状態には絶対になりません。Accessの自動的な機能を全く使用しない方法です。

私自身は、販売管理プログラム作成前に上記の「Accessで連結フォームでプログラムを書いたことがない。」という記述を読んでいたために、主として3番目の方法で作成しました。売上伝票入力画面、受注伝票入力画面のように入力行の制限がある(紙伝票の入力可能行数の制限で一度に入力できる明細行数が限られている)場合はこの場合に当たります。

また、仕入伝票入力画面、入金伝票入力画面、支払伝票入力画面は2番目の方法で作成しました。仕入伝票は仕入先から送られてくる納品書を元に入力しますが、1枚の伝票行数を忠実に守る必要はありません。何行でも連続して入力しても全く問題ありません。実際、仕入先から送られてくる伝票1枚の明細行数は一定ではありません。決まった行数しか入力できないフォームは使いにくいです。入金、支払については全くの社内処理なので、入力行数に決まった制限はありません。

実は1番目の方法でフォームを作成したこともあります。比較的最近のブログで書きましたが、サーバーのテーブルと直接連結したフォームを作成して、たまにロックがかかってしまいます。そのフォームというのは本当にたまにしか変更しないマスターファイルです。同時に2つ以上の端末から修正する可能性がほとんどないマスターファイルの修正はこの方法でフォームを作成したものがあります。実際、たいしたコードを書かなくても所用の動作を行うことができるので、一番簡単ではあります。しかし、この方法はあまりよくありません。フォームを閉じた後もロックが残ってしまうと、サーバーのKeepAlive頼みでロック解除を待つしかありません。新規作成の場合もPostgreSQLの主キーをSerial型にしておけば、そのフォームを開いて閉じるだけで新規作成できます。本当に簡単なのですが。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする