ラベル FileMaker講習 の投稿を表示しています。 すべての投稿を表示
ラベル FileMaker講習 の投稿を表示しています。 すべての投稿を表示

2014-11-26

『FMEasy在庫』 とiPadによる棚卸と在庫誤差調整(1) ―― 棚卸入力を実装する

 今回は、iPadによる棚卸入力モジュールの開発方法をご紹介していきます。

FMEasy在庫 R1.0/R1.5 に棚卸入力モジュールを実装する

 ここでは弊社製品 FileMaker 在庫管理テンプレート『FMEasy在庫 IWP/WD R1.5』に沿って解説を進めていきますが、『FMEasy在庫 R1.0』を利用することもできます。

Q. 棚卸入力モジュールを使うと、倉庫の商品のバーコードを iPad で読み取って商品個数を入力するだけで、素早く、簡単に棚卸作業が進められるようになるの?

A. (最初から期待を裏切ってしまうかもしれませんが)微妙です。
 皆様は棚卸作業の時、商品リストを印字して、倉庫に持っていき、一人が商品をカウントして読み上げ、もう一人が数量をリストに書き込む、というような作業をされいると思います。

 リスト上の商品が棚番でソートされているようであれば、カウントした商品数を素早くリストに書き込むことができ、リストに書き込んだ数値をExcelや在庫管理アプリに入力するというのも、立派なやり方と思います。

 ただ、棚番管理ができていない等の理由により、リスト紙ベースの棚卸がうまく機能していないようであれば、iPadなどの携帯端末による棚卸を検討されてはいかがでしょうか。 

 iPad/iPhoneによる バーコードスキャンは慣れが必要です。スキャンをすばやく実行できるようになれば、棚卸入力モジュールはかなり有望と思います(自画自賛><)。


 それでは、以下の2つの機能に分けて、その作成方法をご説明していきます。

 1. iPad および FileMaker Go 13 のバーコード読み取り機能による棚卸入力モジュール
 2. 上記で入力した棚卸在庫数とシステム上の在庫数の誤差を修正する調整伝票作成機能

  今回は 1. の棚卸入力モジュールにいて説明しますが、その前に少しだけ用語のご説明……


【用語解説】

在庫数 ― システム上の在庫数。『FMEasy在庫 R1.0/1.5』で入出庫登録を行った結果、算出・表示される商品画面上の[在庫数]。以下の[棚卸在庫]とは異なる可能性がある

棚卸在庫 ― 実際の存在する商品の在庫数、または『FMEasy在庫 R1.0/1.5』に入力されたその値。システム上の在庫数(=[在庫数])とは異なる可能性がある



棚卸 ―  実際に存在する商品の数を(カスタマイズ後の)『FMEasy在庫 R1.0/1.5』に入力すること

在庫誤差調整 ―  「システム上の在庫数」と「棚卸在庫」の誤差を入庫/出庫の調整伝票を作成することにより修正すること、またはその機能

iPadによる棚卸モジュールを作成する

まずは、こちらの動画をご覧ください。



 倉庫の商品棚のバーコードを iPad で読み取り、各々の商品の個数をタッチパネルで入力している様子です。

 操作手順は以下のとおり。
  1. 画面上部の[JAN]フィールドをタップしてカメラをアクティグにする
  2. バーコードにフォーカス。フォーカスが合うと、iPadが勝手に商品を検索してくれて、[棚卸在庫]がアクティブに。
  3. 値一覧(1~9)の数値をクリックするか、テンキーから実際の在庫数を入力。

    以下、1~3 を繰り返して、各商品の[棚卸在庫]を入力していきます。

 さて、ご覧のように、バーコードは棚に貼りつけておくと、素早くスキャンできると思います。

 この動画では、私が棚卸作業をしていますが、バーコード読み取り時にカメラのフォーカスを合わせたり、数値をスムーズに入力したりするには少々コツがいります。
 慣れればかなり速くスキャンができるようになると思います。

 商品をひとつひとつ手に取り商品上のバーコードをスキャンすることもできますので、どちらが御社に適しているのか、検討してみてください。

 それでは、この棚卸作業用の画面を開発してみましょう。

【開発レベル】
中級(レイアウト修正、テーブル修正、スクリプト修正について理解している)

【用意するもの】
1. 『FMEasy在庫 R1.0』または『FMEasy在庫 IWP/WD R1.5』
『FMEasy在庫』はこちらからダウンロードできます。
2. iPad/iPad Mini
3. FileMaker Go 13 (iPad にインストール)
FileMaker Go 13 はこちらからダウンロードできます。


注意:
1. 作業を始めるまえに、必ず『FMEasy在庫』のバックアップをお取りください。
2. 作業の際、修正場所を間違えると、既存の機能が動作しなくなる可能性があります。

1. 取扱商品の JAN コードを商品マスタに登録

 社内の取扱商品の JAN コードを商品マスタに登録しておきます。
 商品マスタへのJAN コードフィールドの配置方法と登録のしかたについては、こちらの記事をご参照ください。

 iPad のバーコードスキャンで入庫伝票を作成 ― FMEasy在庫のカスタマイズ


2. 商品テーブルに棚卸作業用のフィールドを追加

 棚卸作業をするにあたり、以下のフィールドを EasyData15.fmp12/EasyData.fmp12 の商品テーブルに追加します。

 [棚卸担当ID] (数値型) ― 棚卸担当の[社員ID]を入力するためのフィールド
 [棚卸在庫](数値型) ― 倉庫棚の在庫数を入力するためのフィールド



3. JANコード検索用のフィールドを UI テーブルに追加

 棚卸用バーコードスキャン用のフィールドを EasyApp15.fmp12/EasyApp.fmp12 の UI テーブルにグローバルテキストフィールドとして追加します。




4. 棚卸担当者の氏名情報と担当者の過去の棚卸実績を照会するためのリレーションを追加


 以下の 3 つの TO を追加します。

 1) 社員_棚卸担当ID (社員テーブル)
 2) self_棚卸担当ID (商品テーブル) 任意
 3) self_商品ID(商品テーブル) 任意


1) [棚卸担当ID]と社員マスタのリレーション

 商品TOの[棚卸担当ID] と社員_棚卸担当ID TO の[社員ID]を関連付けます。



 2) 同じ[棚卸担当ID]が過去に棚卸処理をした商品を調べるためのリレーション

 商品 TO の [棚卸担当ID] と self_棚卸担当ID TO の [棚卸担当ID] どうしを関連づけます。


 これにより、ある担当者が過去に実行した棚卸実績を閲覧できるようになります。
 棚卸機能としては必須のリレーションではありませんが、棚卸作業もれや棚卸ミスをチェックできますので、用意しておくと便利でしょう。

 3) 棚卸実績の[商品ID]からその商品の情報に移動するためのリレーション

 上記で用意した self_棚卸担当ID TO の[商品ID] と self_商品ID TO の [商品ID] フィールドを関連づけます。


 これにより、棚卸実績の中からその商品情報に移動(照会)できるようになります。
 棚卸機能としては必須のリレーションではありませんが、棚卸作業時には、商品情報照会の操作性がアップしますので、用意しておくと便利でしょう。

5. 棚卸作業用のレイアウトを追加

 EasyApp15.fmp12/EasyApp.fmp12 のレイアウトモードで新規レイアウトを作成します。
 FileMaker Pro 13 では、下図のように視覚的にレイアウトを作成できます。




 このとき、表示するレコードは「商品」、レイアウト名は ipad 用の棚卸画面とわかる名前を指定しておきます。

 また、ここでは縦置きを前提にしたレイアウト選択を行っていますが、運用時に縦置きと横置きとでどちらが使い勝手が良くなるかを事前によく検討しておくと、後々のレイアウト調整の手間が省けます。

 あとは上記で用意した TO とリレーションを使って、[棚卸担当ID]、[棚卸在庫]、[gJAN] (スキャン用)などのフィールドを配置していきます。

 たとえば、レイアウトの加工例はこのようになります。
 最低限のユーザ入力が必要になるフィールドには赤囲みを付けておきますので、参考にしていただけると幸いです。



 図中、「タップでスキャン開始」となっているフィールドは UI TO の [gJAN] フィールドになります。
 操作では、このフィールドをタップした瞬間にバーコード読み取りモードに移り、iPad のカメラが起動させるようにします。


7. バーコード読取スクリプトを編集(または作成)

 iPad からバーコードを読み取るためのスクリプトを用意します。
 スクリプトの作成方法の詳細については、こちらの記事をご参照ください。

 iPad のバーコードスキャンで入庫伝票を作成 ― FMEasy在庫のカスタマイズ

たとえば、バーコード読取スクリプトの編集例はこのようになります。


8. JAN コードによる商品呼出スクリプトを追加

 ユーザが UI の [gJAN] フィールドにスキャンした JAN コードを使って商品検索を行うスクリプトを作成します。

 たとえば、以下の図のようになります。



9. [gJAN] フィールドにスクリプトトリガを実装

 [gJAN] フィールドを iPad でタップした瞬間(OnObjectEnter) にバーコード読取が実行されるようにスクリプトトリガを設定します。

 また、[gJAN]へのバーコード読み取りが終了した瞬間(OnObjectSave) に JAN コード検索が実行されるようにスクリプトトリガを設定します。

 たとえば、以下のようになります。



 ここまでできたら、iPad に FileMaker Go 13 をインストールして、棚卸入力テストを行ってみてください。

 本記事の棚卸操作のような動きになれば成功です。


【棚卸実績を表示させる】

 ここでは、画面右の棚卸実績ポータルの作り方について解説します。
 ご覧のように、同じ棚卸担当者(例:土屋)が行った棚卸実績が一覧表示されていると、棚卸在庫数とチェック漏れの確認ができて便利ですね。



 棚卸実績表示用のリレーションシップの設定については、前述の「4. 棚卸担当者の氏名情報と担当者の過去の棚卸実績を照会するためのリレーションを追加」をご覧ください。


 ポータル指定の際に使うリレーションは「self_棚卸担当ID」となります。


 
 このリレーションの参照先が商品テーブルとなっていますので、[商品名]と[棚卸在庫]を配置しておけばよいでしょう。

 本稿では省略しますが、“照”ボタンをクリックすることによって、その行の商品の詳細情報を別ウィンドウで表示させたりすると、より使い勝手がよくなるでしょう。



 在庫誤差調整機能については、次回の記事でご紹介したいと思います。

 「iPadでバーコードスキャンして、棚卸表ができました!」というだけでは「で?」と突っ込まれそうなので、入力した[棚卸在庫]とシステム上の在庫数の誤差を調整伝票を発行して修正する機能もつくりました。
 続きはこちらの記事をご覧ください。

 『FMEasy在庫』 とiPadによる棚卸と在庫誤差調整(2) ―― 在庫誤差調整伝票の作成 


(亀)

2014-06-30

インスタント Web/WebDirect対応在庫管理テンプレート『FMEasy在庫 IWP/WD R1.5』を本日リリース

 本日、『FMEasy在庫 IWP/WD R1.5』(フリー版)のダウンロードと販売を開始。


 ホントは昨年末にインスタントWeb(IWP)に対応の「FMEasy在庫 IWP R1.5」としてリリースする予定が、同時期に IWP の後継WebDirect(WD)を含む FileMaker Pro 13 がリリースされ、「タイミング、悪!ヽ(`Д´)ノ」、 と思いつつ、「WDにも対応させよう」と思い直し、艱難辛苦の末、今日を迎えることができました\( ̄▽ ̄;)/。


 以下、 本製品についての若干のご説明。


製品概要


  『FMEasy在庫 R1.0』 に検索・入力支援機能を付加し、インスタントWebとWebDirectに対応させたのが本製品です。


製品種類

  • フリー版(無料) ― データ入力無制限
  • 開発版(価格:¥54,000、税込) ― FileMaker Pro 12/13 Advancedにより開発可

 本製品リリース後も、在庫管理テンプレート『FMEasy在庫 R1.0』(フリー版/開発版 ¥26,250)は引き続きダウンロード/購入可。

開発方針


こんな感じで開発してみました。

  1. インスタントWeb(IWP)/WebDirect(WD)の両方に対応させる
  2. 入出庫・在庫の基本機能は『FMEasy在庫 R1.0』をそのまま踏襲
  3. FileMaker/IWP/WD間で、できるだけレイアウトを共有する(下記※参照)
  4. 検索・入力支援機能 ― 取引先または商品のレコードが千~1万件を超す場合、FileMaker標準の 関連フィールドによる値一覧は実用に耐えない(特にWeb環境下) ― ので、検索・入力支援機能を搭載する(後述)
  5. 検索・入力支援機能の流用性 ― 本製品をカスタマイズして売上/入金/仕入/支払/受注/発注等々の機能を付加する場合、取引先、得意先、仕入先、商品の入力が必要となるが、その時に検索・入力支援機能を簡単に流用できるように設計する
  6. 検索・入力支援機能は FileMaker/IWP/WD の3プラットフォームで利用できること
  7. WDの実行速度を落とさないように、レイアウトテーマは前版「FMEasy在庫 R1.0」の「レトロ」から「クラッシック」に変更 ― この為、本製品R1.5と前版R1.0の画面がかなり異なっている

※レイアウト共有で工数減?

 レイアウトを共有するとレイアウトだけでなくスクリプトも共有できる可能性が高まり、工数削減につながりそうだが、レイアウトを弄る度にFileMaker/IWP/WD、3つのプラットフォームでレイアウトのズレを気にしなければならなくなり、実際の工数減に繋がるかは微妙です。
 おおざっぱな方 ― 多少、オブジェクトが被ったりズレたりしても気にしない人はレイアウト共有し、細かいことが気になる人はレイアウトを分けた方が幸せかもしれないです。

 それともかく、本製品はIWPの入力更新系画面を除き、できるかぎり3プラットフォーム間でレイアウトを共有しています。

検索・入力支援機能


本製品のキモはなんと言っても検索・入力支援機能。
下図はWebDirect環境のChromeの画面。

[取引先の検索・入力支援機能]

※取引先画面で検索支援機能を使う
“検索支援”クリック検索支援画面が開く→取引先名を入力して“表示”表示された一覧から目的とする取引先を選択クリック元の取引先画面に戻り選択した取引先が表示される。

※出庫/入力画面で入力支援機能を使う
“選”クリック入力支援画面が開く得意先または仕入先名を入力して“表示”表示された一覧から目的とする得意先/仕入先を選択クリック元の出庫/入庫画面に戻り選択した得意先/仕入先が入力される

注:実行元の画面により、検索・入力支援画面に表示されるボタン、表記、機能が若干異なります。



[商品の検索・入力支援機能]

※商品画面で検索支援機能を使う
“検索支援”クリック検索支援画面が開く商品名を入力して“表示”表示された一覧から目的とする商品を選択クリック元の商品画面に戻り選択した商品が表示される

※出庫/入力画面で入力支援機能を使う
明細の“選”クリック入力支援画面が開く商品名を入力して“表示”表示された一覧から目的とする商品を選択クリック元の出庫/入庫画面に戻り選択した商品が入力される
  • 実行元の画面により、検索・入力支援画面に表示されるボタン、表記、機能が若干異なります。
  • 入力支援画面で[伝票単価][数量]を入力すると、その値が入出庫明細の単価と数量に入力されます。



Blog連動


 いくつかの問題もあります。 例えば、インスタントWeb(IWP)/WebDirect(WD)では満足な印刷ができない。これは FileMaker Serverの問題ですが、回避策がないこともないです。
 それは、ネットワーク上に印刷専用の FileMaker クライアント(FileMaker Robot)を常に起動しておき、IWP/WDクライアント(ブラウザ)から印刷リクエストがないか常に監視し、リクエストがあればFileMaker Robotから印刷を行うようにスクリプトを作成し、そのスクリプトを常に実行した状態にしておきます。

 別の問題として、IWPではダイアログボックス表示のスクリプトステップが使用できないため、レコード削除実行時に確認のダイアログが表示されずに即刻レコードが削除されてしまう、ということがある。

 また、 WDは各種ブラウザとの互換性が低いがFileMaker クライアントの再現性が高いのでインストラネットで、IWPは各種ブラウザとの互換性が高いので不特定多数対象のインターネットで使用したいが、WD/IWPの同時使用は可能か…等。 こうした問題・課題について、できるだけ本Blogで取り上げていきたいです。


サポート

前版インシデント2→今版5インシデント(365日間有効)に!

 ご質問については、Blog 記事として回答させて頂くこともあります →例1とか例2とか。


講習とか


 本製品をベースに在庫管理を学んでみたいという方はこんなのとか、IWPをやってみたいという方はこんなのとか、WDとはなんぞやという方はこれとか、あります。

 それでは足りない!、開発支援とかコンサルティングを!という方はこちら

 その他の在庫関連記事を読む
 その他の WebDirect 関連記事を読む

(土屋)

2013-07-25

簡単? FileMakerで在庫管理(6) ―― 場所別在庫レコードの作成方法

 ブログ記事「簡単? FileMakerで在庫管理(3) ―― 倉庫など場所別に在庫数を把握する」では、倉庫等の場所別の在庫数算についてご紹介しました。
 今回は、同機能のキモとも言える場所別在庫レコードの作成方法についてユーザ様よりお問い合わせをいただいたので、以下にその概要をご紹介します。

場所別在庫レコードの作成方法

1.場所別在庫テーブルとそのレコードの作成方針


 先の記事で紹介した場所別在庫算出方法では、下図のような場所別在庫テーブルが必要となります。



 ここで必要十分なレコードは、在庫場所テーブルと商品テーブルのデカルト積となります。


例:
在庫場所TBのレコード
A(倉庫)
B(倉庫)
C(倉庫)

商品TBのレコード
X(商品)
Y(商品)
Z(商品)

場所別在庫TBレコード
AX
AY
AZ
BX
BY
BZ
CX
CY
CZ

 さて、場所別在庫テーブルでデカルト積となるようにレコードを生成すると、各倉庫の在庫(=[c場所別在庫数])に漏れはなくなりますが、倉庫に一度も入出庫が発生していない商品がある場合、余分なレコードが存在することになってしまいます。

 たとえば、倉庫Aにおいて商品Xは入出庫したことがあるが、商品Y、Zについては入出庫が一度も発生していない場合、AXレコードは必要ですが、AY、AZレコードは、通常は不要です。
 処理速度が遅くテーブル結合が貧弱な FileMaker では、余分なレコードを極力作成しないように設計すべきでしょう。

 ということで、今回の仕様においては、入出庫登録を行う際に場所別在庫テーブルに当該商品のレコードの登録有無をチェックして、未登録の場合のみ、レコード登録を行うようにします。


2.実装概要


◇リレーションシップ

場所別在庫_入出明細#出庫 (新設、出庫明細TBと場所別在庫TBのリンク用)
場所別在庫_入出明細#入庫 (新設、入庫明細TBと場所別在庫TBのリンク用、下図)
[このリレーションを使用して、このテーブルでのレコード作成を許可]の✔を忘れずに

◇スクリプト

g確定Btn (変更、OnRecordCommitで実行されるスクリプト)
  • 入庫/出庫画面のレコード確定(OnRecordCommit)時に、入出明細ポータルをチェックし、場所別在庫レコードが存在しなければ、同レコードを作成します。
    下図の赤いフィールドは場所別在庫_入出庫明細#入庫::在庫場所IDフィールドですが、これが空欄であるということは、[在庫場所ID]=5(座間倉庫)の当該商品の場所別在庫レコードが存在しないということを意味します。その場合は、[入庫場所ID]の値を[場所別在庫_入出庫明細#入庫::在庫場所ID]に入れ、場所別在庫レコードを作成します。
  • 本スクリプト実行時になんらかのエラーが発生した場合は、エラーが発生した旨のダイアログを表示し、ダイアログ内の“OK”ボタンでレコード確定を中止し、“レコード復帰”ボタンで明細行の作成をキャンセルするようにします。
    場所別在庫レコードの作成に失敗しているにも関わらず入出明細レコードのみ確定されると、その入庫数分の在庫はシステムから消失してしまうので注意が必要です。

3.その他

  • 万が一、関連する場所別在庫レコードがない入出明細レコードが発生した場合に備え、入庫/出庫テーブルに[c在庫場所ErrMsg]フィールドを作成し、エラーが発生した場合にのみ画面に表示する、というのは用心深い良いプラクティスと言えるでしょう。
  • 場所別在庫テーブルは巨大化しやすいので、場所別在庫が0で且つ入出庫が最近発生していない場所別在庫レコードを削除するバッチ処理を検討しておくことが望ましいです。

2013-05-14

分離モデルにおけるSUM/ExecuteSQL関数の問題と対策

FileMakerの分離モデルにおいてSUMなどの集計関数を使用すると、計算結果が正しく表示されないことがある。

例:
App.fmp12(アプリファイル)とData.fmp12(データファイル、売上/売上明細テーブルを保持)があり、App側でDataにある2のテーブルを以下のようにリレートする。


◇売上テーブルの計算フィールド
SUM売上:SUM(売上明細::金額)、
SQL売上:ExecuteSQL("SELECT SUM(\"金額\") FROM \"売上明細\" WHERE " & 売上::Id & "=\"fk\"";"";"")


◇レイアウト



上図は新規の売上レコードを作成し、売上明細(ポータル)に入力しているところだが、[SUM売上]と[SQL売上]には本来「40」と表示されるべきところ、誤った値が表示される。

一方、データビューアで、上記の2つの計算フィールドで設定した式を入れてみると、ExecuteSQL側は(恐らく)常に正しい値 40 を表示するが、Sum(売上明細::金額)は正しい値を表示しない。

次にレコードをコミット(保存)してみると、下図のようにすべての4つの項目で正しい値 40 が表示される。


ということで、分離モデルでは上記に関する対策を講じなければならないが、考えられる対策は以下の通り。

  1. レコードをコミット(保存)するようにユーザを教育する。
  2. 数量、単価を変更したときには、コミットを求めるメッセージを画面に表示する。
  3. 計算フィールドの使用を避け、数値型の売上フィールドを用意。ユーザが数値、単価を変更したときには売上フィールドの値が適正に更新されるように設計を行う(スクリプトとスクリプトトリガを利用。このとき、EcecuteSQLの使用が有効と思われる)。
上記1は開発者には一番楽であるが、寛大なユーザばかりとは限らない。
上記2は実装は簡単だが、Webアプリならまだしも、デスクトップアプリ/LANアプリでユーザに操作負担を求めるのはどうか、というのはある。
最後の3の実装はかなり面倒となる。

また、数量や単価を変更したときに、毎回自動コミットするように設計するというのはあり得るが、あまりに美しくない。

ちなみに、小社でリリースしている『FMEasy在庫 R1.0』は上記2を、『売上猫くん Standard R1.0』と『売上猫くん on MySQL R5β』では上記3を採用している。



(土屋)

【関連リンク】
FileMaker の分離モデル
FileMaker の分離モデル - 2


土屋企画の講習 ― 分離モデルに基づく請求書システムを作る(対象者:中級、4時間×2日)




2013-01-29

簡単? FileMakerで在庫管理(4) ―― ExecuteSQLによる在庫数算出

 これまで FileMaker Pro による在庫算出の基本、繰越処理の考え方、複数倉庫の在庫算出方法についてご紹介してきましたが、今回は商品在庫を求める方法として、3 つのパターンをご紹介したいと思います。

在庫算出の 3 つのパターン

パターン1: FileMaker Pro で在庫算出専用の TOG を構成する方法


 弊社で配布しているシンプルな入出庫・在庫管理システム/テンプレート 「FMEasy 在庫」では、以下のようなリレーションシップを構成することによって、特定時点の商品在庫を算出しています。

ここでは |×| 以外のリレーションは無視して下さい。

※「簡単? FileMakerで在庫管理(1) ―― 在庫算出の基本」に類似リレーションの解説がありますので、参考にしてみてください。

 ユーザが商品レイアウト上の [g在庫基準日1]に任意の日付を指定すると、在庫算出開始点となる日付[g在庫基準日2]を決定します。
 [g在庫基準日2]~[g在庫基準日1]の範囲内の日付で発生した商品の[入庫数]と[出庫数]が対象となるようにリレーションシップを組み、対象となった[入庫数]、[出庫数]、および商品側の[繰越在庫数]を使って[g在庫基準日1]の在庫を求めます。

 このように考えた場合、商品テーブルの [c在庫数]の計算式は、たとえば次のようになります。

Case(IsEmpty(繰越情報::繰越日付) or g在庫基準日1 < 繰越情報::繰越日付; 導入時在庫数;繰越在庫数) - Sum(入出明細_商品::出庫数量) + Sum(入出明細_商品::入庫数量)

 この計算式は比較的単純ですが、リレーションが不細工なことと、[g在庫基準日1]や[g在庫基準日2]という管理フィールドを商品テーブルに持たせざるを得ない点には、スマートさがあまり感じられませんね。


パターン2:ExecuteSQL関数を使用する方法(JOINなし)


 FileMaker Pro 12 に新たに追加された ExecuteSQL 関数を使うことによって、商品の在庫を算出します。

 この方法を採用すると、入出庫数絞り込みのためのリレーションシップが不要となります。
 また、商品テーブルの[g在庫基準日1]フィールドおよび [g在庫基準日2]フィールドも不要となります。
 ユーザが日付を指定する[g在庫基準日1]は、ユーザインタフェース専用テーブル UI に移動してしまいましょう。



 上記のように、 入出明細TO さえあればリレーションは不要となります。単純なのがいいですね!
 それでは、商品テーブルの方に在庫算出用計算フィールド[cNoJoin在庫数]を追加し、計算式を以下のようにしてみましょう。


//$date は期間開始日、$date~ UI::g在庫基準日1 の入出庫の計を加減して在庫数を算出
Let ( 
    $date = 
      Case(
        IsEmpty(繰越情報::繰越日付) or UI::g在庫基準日1 < 繰越情報::繰越日付; Date( 1; 1; 1 );
        繰越情報::繰越日付 = UI::g在庫基準日1; 繰越情報::繰越日付 +1;
        繰越情報::繰越日付 +1
      );

    Case( IsEmpty( 繰越情報::繰越日付 )  or  UI::g在庫基準日1 < 繰越情報::繰越日付; 商品::導入時在庫数;商品::繰越在庫数 )
  - ExecuteSQL ( "SELECT SUM( \"出庫数量\" ) FROM \"入出明細\" WHERE \"商品ID\" ="  &  商品::商品ID & " AND (\ "入出庫日\" BETWEEN '" &
   GetAsText ( $date ) & "' AND '" & GetAsText ( UI::g在庫基準日1 ) & "') "; ""; "")
  + ExecuteSQL ( "SELECT SUM( \"入庫数量\" ) FROM \"入出明細\" WHERE \"商品ID\" ="  &  商品::商品ID & " AND ( \"入出庫日\" BETWEEN '" &
   GetAsText ( $date ) & "' AND '" & GetAsText ( UI::g在庫基準日1 ) & "') "; ""; "")

)

 ここでは $date が [g在庫基準日2]フィールドに代わって期間開始日となるため、 [g在庫基準日2]フィールドは不要となります。


パターン3:ExecuteSQL関数でJOINする方法


 最後は、ExecuteSQL に結合(LEFT JOIN)を組み込み在庫を算出する方法です。ここでは出庫テーブルと入庫テーブルを入出明細テーブルに JOINし、出庫.出庫日 と 入庫.入庫日 を WHERE 句で使用できるようにするため、入出明細テーブルの[入出庫日]も不要となります。

 パターン2と同様、配置するのは 入出明細TO のみで、リレーションは不要です。



 結合にはLEFT JOIN を使用していますが、INNER JOIN も使えます。RIGHT JOIN は FileMaker が非対応のようです。商品テーブルで商品在庫を求める計算フィールド[cSqlLeftJoin在庫数]を追加し、以下のような計算式を組み立てます。

Let (
    $date =
        Case(
            IsEmpty( 繰越情報::繰越日付 ) or UI::g在庫基準日1 < 繰越情報::繰越日付; Date( 1;1;1 );
            繰越情報::繰越日付 = 商品::g在庫基準日1; 繰越情報::繰越日付 +1;
            繰越情報::繰越日付 +1
        );

    Case( IsEmpty( 繰越情報::繰越日付 ) or UI::g在庫基準日1 < 繰越情報::繰越日付; 商品::導入時在庫数;商品::繰越在庫数 ) -

    (
        ExecuteSQL ( "SELECT SUM( \"出庫数量\" ) FROM \"入出明細\" LEFT JOIN \"出庫\" ON \"入出明細\".\"出庫No\" = \"出庫\".\"出庫No\" WHERE \"商品ID\" ="  &  商品::商品ID & " AND ( \"出庫日\" BETWEEN '" & GetAsText ( $date ) & "' AND '" & GetAsText ( UI::g在庫基準日1 ) & "' ) "; ""; "" )
    )
    +
    ExecuteSQL ( "SELECT SUM( \"入庫数量\" ) FROM \"入出明細\" LEFT JOIN \"入庫\" ON \"入出明細\".\"入庫No\" = \"入庫\".\"入庫No\"WHERE \"商品ID\" ="  &  商品::商品ID & " AND ( \"入庫日\" BETWEEN '" & GetAsText ( $date ) & "' AND '" & GetAsText ( UI::g在庫基準日1 ) & "' ) "; ""; "" )

)

 このように商品テーブルの[g在庫基準日1]フィールドと[g在庫基準日2]フィールド、在庫算出用のリレーションに加え、入出明細テーブルの[入出庫日]フィールドが不要となります。また、入出明細テーブルに[入出庫日]を設定するというスクリプトによる面倒な制御も不要になります。


 ExecuteSQL 関数のメリット


 ExecuteSQL を利用すると、本来不要なリレーションやグローバルフィールドを省けるため、データベースの正規化がしやすくなります。また、結合を使用すれば、スクリプトによる余分な制御も不要となります。

 ただ、実行速度的にパターン1~3 のどれが一番有利かは検証が必要です。それについては機会を改めてやりたいとは思っています。



(亀澤)

2012-12-20

簡単? FileMakerで在庫管理(3) ―― 倉庫など場所別に在庫数を把握する

 弊社では在庫管理システムの講習を行っていますが、時折「うちは在庫の保管場所が複数あるので、保管場所毎に在庫を管理したいのだが、おたくの講習は対応できる?」との問い合わせを受けることがあります。 

 実のところ、複数の在庫場所に対応した在庫管理システムの構築は難度が上がってしまうのですが、なんとかコアの部分だけでも本記事でご説明させていただきます。

倉庫など場所別に在庫数を把握する


 ここでは、『FMEasy在庫 R1.0』で複数の在庫場所を管理できるように、仕様変更してみることにします。
 これまでに弊社の在庫管理講習を受講された方、または『FMEasy在庫R1.0(開発版)』ユーザ、倉庫別在庫管理の考え方を学びたい方の参考になれば幸いです。

  1. テーブル設計
    1. 在庫場所テーブル (新設、倉庫/保管場所等管理用マスタ)
      • ID(主キー)
      • 場所名(テキスト)
    2. 場所別在庫TB(新設)
      • ID(主キー)
      • 場所ID(外部キー)
      • 商品ID(外部キー)
      • 導入時在庫数(数値、導入時に元々あった商品在庫数を在庫場所別に記録)
      • 繰越在庫数(数値、繰越処理実行時に特定時点の商品在庫数を在庫場所別に記録)
      • c場所別在庫数(場所別在庫算出用計算フィールド)
      • g在庫基準日1/g在庫基準日2(入出庫の期間特定用グローバルフィールド)
    3. 入庫テーブル/出庫テーブル(変更)
      • 入庫場所ID/出庫場所ID(新設、入出庫場所を登録)
    4. 入出明細TB(変更)
      • 在庫場所ID(新設、入庫テーブル/出庫テーブルの入庫場所ID/出庫場所IDをコピーする)

  2. リレーションシップ設計

  3. レイアウト(LAY)/スクリプト設計
    1. 在庫場所LAY(新設、場所別の在庫数をポータルに表示)
    2. 入庫LAY/出庫LAY(変更)
      • 入庫場所ID/出庫場所IDを配置する
      • OnRecordCommitで入庫場所ID/出庫場所IDを入出明細テーブルの在庫場所IDフィールドにコピー
      • OnRecordCommit時、必要に応じて場所別在庫レコードを作成(4-a参照)

  4. 考慮すべき事項
    1. 場所別在庫レコードを作成するタイミング
    2. 複数倉庫がある等、場所別に在庫を管理しようとすると、FileMakerの場合、どうしても場所別に商品を登録しておく専用テーブル(場所在庫テーブル)が必要になる。そこで、場所別在庫レコードを登録するタイミングが問題となる。余分なレコードをテーブルに極力保持しないためには、入出庫レコード登録時(OnRecordCommit)に、未登録商品の場所別在庫レコードを登録するように制御する。 
    1. 倉庫間移動に対応
      • 出庫時、倉庫1の出庫伝票を、入庫時、倉庫2の入庫伝票を作成
      • 倉庫2の入庫伝票作成漏れを防ぐ
      • 倉庫2の入庫伝票作成後の関連伝票更新をどう考えるか?
    2. 出入庫同時作成機能(商品の近接場所間移動時)
    3. その他


リレーションシップ


 まず、テーブルでキモとなるのが場所別在庫テーブルですね。このテーブルにより、場所別に商品在庫数の算出が可能となります。
 ここで特に重要なフィールドは、在庫場所ID、商品ID、c場所別在庫数(計算フィールド)です。なお、下図で場所名と商品名は商品テーブルと在庫場所テーブルを参照しています。

【場所別在庫テーブルを表形式レイアウトに表示】



在庫算出部分のリレーション。

↓ 


 入出明細テーブルには商品ID/在庫場所ID(出庫元/入庫先の在庫場所ID)と入出庫数が登録されているわけだから、入出明細テーブルと場所別商品在庫テーブル上記のようにリレートして、以下のように計算式フィールをを作ればよいでしょう。 

元々ある在庫+特定期間のSum(入庫数)-特定期間のSum(出庫数)

注:
 「元々ある在庫」は繰越処理が未実行であれば[導入時在庫数]、実行済であれば[繰越在庫数]となり、「特定期間」はユーザが指定する[g在庫基準日1]と、[g在庫基準日1]のOnObjectValidate/Saveで起動するスクリプトにより制御された[g在庫基準日2]の値により決まります。
 [g在庫基準日2]の設定値については、「簡単? FileMakerで在庫管理(2)」の図が参考になると思います。

 他にもリレーションシップの追加はあるのですが、難しくないので省略します。


レイアウトとスクリプト


 入庫/出庫レイアウトには、それぞれのテーブルで新設した[入庫場所ID]と[出庫場所ID](入出庫した場所を示すID)を登録し、OnRecordCommit時に入出庫明細テーブルの[在庫場所ID]にコピーします。
 なお、Commit時に、入出明細テーブルに入力されている[商品ID]で場所別在庫テーブルに未登録の商品は登録するという、第2のキモともいうべきスクリプトについては、できれば機会を改めて書きたいと思います。

【出庫レイアウト】


 最後に在庫場所別に商品在庫数を表示するレイアウト。ユーザが[在庫基準日]に日付入力することにより、その日付時点の各商品の在庫数が表示されます。


【在庫場所レイアウト】

ポータル部分に在庫数(=場所別在庫::c場所別在庫数)と商品テーブルの情報が表示されます。
以上、『FMEasy在庫』というテンプレートをベースにカスタマイズしてみましたが、半日強の時間でとりあえず場所別在庫数は表示できるようになりました。
 上述の場所別在庫のレコード作成処理や、繰越処理は別途作成しなければなりませんが、意外と実装に時間はかかりませんでした。


 (土屋)

2012-07-06

MySQL Workbench の EER モデリングツールでリレーションシップ検証 3 (リレーションシップアイコンの種類と使い方)

前回、前々回の記事で、外部キーの設定と制約の定義方法について説明してきましたが、今回は EER モデリングツールのリレーションシップアイコンの種類と使い方について説明します。

EER モデリングでリレーションシップの設定を行う場合は、画面の左下に並ぶ 6 種類のアイコンを使います。




 既存のテーブル列を使ってリレーションシップを設定する

大抵の場合は、先に基本的なテーブルを予め定義しておき、後でリレーションシップを設定する作業手順となるでしょう。そのような場合は、上記赤囲みの一番下のアイコンを使用します。

このアイコンを使って作成されたリレーションは、たとえば次のようになります。




青囲みの列に注目してください。ブランドテーブルの [ブランドID]、および取扱商品テーブルの [ブランドID] は共に既存の列にが使われています。


 外部キー専用の列を子テーブルに新規追加し、1対1 の非依存型(non identifying)リレーションシップを設定する


子テーブルに外部キー用の列が作成されていない場合に、親テーブルと 1対1 の非依存型のリレーションシップを設定する場合は、一番上のアイコンをクリックします。
非依存型(non identifying)リレーションシップについては、こちらの記事をご覧ください。

このアイコンを使って作成されたリレーションは、たとえば次のようになります。



青囲みの列に注目してください。ブランドテーブルの [ブランドID]はそのままですが、取扱商品テーブルには、 [ブランド_ブランドID] という専用の列が新たに追加されています。
また、ブランドテーブル側、および取扱商品テーブル側の支線は枝分かれしていないため、このリレーションシップが 1対1 の関係となっていることがわかります。

非依存型リレーションシップの場合、コネクタは破線で表現されます。


 外部キー専用の列を子テーブルに新規追加し、1対多の非依存型(non identifying)リレーションシップを設定する

子テーブルに外部キー用の列が作成されていない場合に、親テーブルと 1対多の非依存型リレーションシップを設定する場合は、上から二番目のアイコンをクリックします。
非依存型(non identifying)リレーションシップについては、こちらの記事をご覧ください。

このアイコンを使って作成されたリレーションは、たとえば次のようになります。



青囲みの列に注目してください。ブランドテーブルの [ブランドID]はそのままですが、取扱商品テーブルには、 [ブランド_ブランドID] という専用の列が新たに追加されています。
また、ブランドテーブル側の支線が枝分かれしていないのに対し、取扱商品テーブル側の支線が三つに枝分かれしているため、ブランド 1 に対し、取扱商品が多の関係になっていることがわかります。

非依存型リレーションシップの場合、コネクタは破線で表現されます。


 外部キー専用の列を子テーブルに新規追加し、1対1 の依存型(identifying)リレーションシップを設定する

子テーブルに外部キー用の列が作成されていない場合に、親テーブルと 1対1 の依存型のリレーションシップを設定する場合は、上から三番目のアイコンをクリックします。
依存型(identifying)リレーションシップについては、こちらの記事をご覧ください。

このアイコンを使って作成されたリレーションは、たとえば次のようになります。



青囲みの列に注目してください。ブランドテーブルの [ブランドID]はそのままですが、取扱商品テーブルには、 [ブランド_ブランドID] という専用の列が新たに追加されています。
また、ブランドテーブル側、および取扱商品テーブル側の支線は枝分かれしていないため、このリレーションシップが 1対1 の関係となっていることがわかります。

依存型リレーションシップの場合、コネクタは実線で表現されます。


 外部キー専用の列を子テーブルに新規追加し、1対多の依存型(identifying)リレーションシップを設定する


子テーブルに外部キー用の列が作成されていない場合に、親テーブルと 1対多の依存型リレーションシップを設定する場合は、上から四番目のアイコンをクリックします。
依存型(identifying)リレーションシップについては、こちらの記事をご覧ください。

このアイコンを使って作成されたリレーションは、たとえば次のようになります。



青囲みの列に注目してください。ブランドテーブルの [ブランドID]はそのままですが、取扱商品テーブルには、 [ブランド_ブランドID] という専用の列が新たに追加されています。
また、ブランドテーブル側の支線が枝分かれしていないのに対し、取扱商品テーブル側の支線が三つに枝分かれしているため、ブランド 1 に対し、取扱商品が多の関係になっていることがわかります。

依存型リレーションシップの場合、コネクタは実線で表現されます。



 多対多のリレーションシップを設定する



子テーブルに外部キー用の列が作成されていない場合に、親テーブルと多対多のリレーションシップを設定する場合は、下から二番目のアイコンをクリックします。

このアイコンを使って作成されたリレーションは、たとえば次のようになります。




多対多の場合は、子テーブルの外部キーと親テーブルの主キーを結び付けると、テーブル名_has_テーブル名 という名前のテーブルが新たに作成されます。
このテーブルは、子テーブルに対する外部キーおよび親テーブルに対する外部キーをそれぞれ持っている点に注目してください。

上図の場合では、ブランド_has_取扱商品 というテーブルに、取扱商品テーブルの主キーに対する外部キー、およびブランドテーブルの主キーに対する外部キーが作成されることを示しています。


外部キーを確認すると、以下のようになっています。


○ブランドテーブルに対する外部キー



ブランドテーブルの主キー[ブランドID]に対する外部キーが作成されています。



○取扱商品テーブルに対する外部キー




取扱商品テーブルの主キー[商品ID]に対する外部キーが作成されています。



【関連リンク】
MySQL Workbench 基礎講習コース





2012-07-04

MySQL Workbench の EER モデリングツールでリレーションシップ検証 1 (Identifying と Non identifying)

MySQL Workbench の便利な機能に EER モデリングツールがあります。


MySQL Workbench の EER モデリング例 


EER モデリングツールを使うことによって、データベースの基本設計を行い、それを使って MySQL  データベース本体を生成したり(フォワードエンジニアリング)、既存の MySQL データベースを EER モデリングツールに読み込ませて(リバースエンジニアリング)設計内容を修正した後で再び MySQL データベースに同期(シンクロナイジング)させたりすることができます。

EER モデリングツールの魅力は、何といってもデータベース設計を視覚的に行えるところにあることでしょう。
テーブル定義、列定義はもちろんのこと、テーブルオブジェクトの配置、リレーションシップの設定などもマウスクリックや簡単な入力作業である程度の設計が可能です。

MySQL Workbench は、MySQL の公式サイトからダウンロードできます。

ダウンロード先:MySQL Workbench 5.2


今回より、MySQL Workbench の EER モデリング機能で設定可能なリレーションシップの種類と、その動作の違いについて数回に分けて説明します。

リレーションシップの種類には、一対一、一対多、多対多、自己リレーションなどがありますが、それらの基本的な概念は他のサイトでも多く触れられているため、本記事では省略します。


【Identifying と Non identifying】

EER でリレーションシップ設定を行い、外部キーの設定情報を確認したときに以下のようなチェックボックスが気になった方もいらっしゃるのではないでしょうか。



そこで、今回は、上記のリレーションの外部キー属性となる、identifying と non identifying の違いについて説明します。


Identifying relationship (依存リレーションシップ)--- 子テーブルの外部キーの一部に親テーブルの主キーが組み込まれた形となり、親テーブルなしでは成り立たない関係。


たとえば、ブランド契約で販売する商品が、撤退時に商品の取扱いも同時に終了するように、ブランドテーブルと取扱い商品テーブルを関連づける場合、[商品ID] および[ブランドID] の組み合わせで外部キーを作り、[ブランドID]  が存在しなければその商品は存在し得ないような厳密な設計を行います。



本来、子テーブル側の主キーは一つ([商品ID])ですが、依存型リレーションシップの場合は親テーブル側のIDを識別するための列([ブランドID])も主キー扱いとなりますので、上図のように子テーブルの主キーは二つとなります(どちらも欠かせません)。
 
 EERモデリングでは、identifying リレーションのコネクタは、上図のように実線で表現されます。

 この場合、外部キー設定がされている取扱商品テーブル構成をダンプ(SQL表記)させると、以下のようになります。
 太字表記の部分が今回のチェック項目になりますが、特に赤字の部分に注目してください。[商品ID] および [ブランドID] の両方が主キー となっています。

--
-- Table structure for table `取扱商品`
--

DROP TABLE IF EXISTS `取扱商品`;
SET @saved_cs_client     = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `取扱商品` (
  `ブランドID` int(11) NOT NULL,
  `商品ID` int(11) NOT NULL AUTO_INCREMENT,
  `商品名` varchar(45) CHARACTER SET utf8 DEFAULT NULL,
  PRIMARY KEY (`商品ID`,`ブランドID`),
  KEY `fk_取扱商品_ブランド` (`ブランドID`),
  CONSTRAINT `fk_取扱商品_ブランド` FOREIGN KEY (`ブランドID`) REFERENCES `ブランド` (`ブランドID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;


Non identifying relationship(非依存リレーションシップ)--- 親テーブルの主キーと子テーブルの外部キーでリレーションシップを構築するが、子テーブルに外部キーとは独立した主キーを持っている関係。


前述のモデルの応用例として、ブランド管理が廃止され商品だけが残った場合にも、在庫商品を処分(販売)できるように、ブランドを問わず商品を管理して扱う場合は、親テーブルが削除された場合にも、子テーブルの商品だけは残して管理できるように設計します。





EERモデリングでは、non-identifying リレーションのコネクタは、上図のように破線で表現されます。


この場合、外部キー設定がされている取扱商品テーブル構成をダンプ(SQL表記)させると、以下のようになります。
太字表記の部分が今回のチェック項目になりますが、特に赤字の部分に注目してください。[商品ID] のみが主キー となっています。
--
-- Table structure for table `取扱商品`
--


DROP TABLE IF EXISTS `取扱商品`;
SET @saved_cs_client     = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `取扱商品` (
  `ブランドID` int(11) NOT NULL,
  `商品ID` int(11) NOT NULL AUTO_INCREMENT,
  `商品名` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`商品ID`),
  KEY `fk_取扱商品_ブランド` (`ブランドID`),
  CONSTRAINT `fk_取扱商品_ブランド` FOREIGN KEY (`ブランドID`) REFERENCES `ブランド` (`ブランドID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET character_set_client = @saved_cs_client;



【関連リンク】
MySQL Workbench 基礎講習コース


2012-06-16

『売上猫くん on MySQL』開発日記 - 番外25 - 行ロックについて

小社主催の「FileMaker+MySQL開発の講習」の受講者の方から「FileMakerとMySQLのシステムで、FileMaker(単体システム)のような行ロックってできないの?」との質問を講習前に頂いた。
FileMaker単体のシステムでは、ユーザがあるレコードを編集中に他のユーザが同レコードを編集しようとしても「他のユーザが編集中」旨が表示され、他のユーザは先行するユーザが編集を終了するまで編集することができなくなる。質問の趣旨はこれをFileMaker/MySQLのシステムでも実現したいということ。 
FileMaker標準機能では、FileMaker/MySQL 環境下で排他的行ロックはできない。 が、方法としては2つある。一つはMySQLのロック機能(select for update)を使用する方法(MySQLの排他的行ロック)、もう一つはMySQLテーブルにロックフラグを用意し、最初に編集を開始したユーザがそのフラグに自分のIDを書き込み、後続の他ユーザの編集を禁じるようにごりごりスクリプトで制御方法(FileMaker単体の行ロックと似ているという意味で、FileMakerライクなロック)。 以下はこの2つのロックの実装方法について。

1.MySQLの排他的行ロック
まず、MySQLの排他的行ロック機能を使うと、FileMakerはどのように反応するのか、試してみる。

MySQLコマンドラインで、

  begin;
  select 売上No from 売上ヘッダ where 売上No=1 for update;


を実行する。 次にFileMakerの売上画面で売上No=1のレコードを開いてみると、何事もなく表示される。次にこのレコードの任意のフィールド値を変更してみると普通に変更できる。 さらに、レコードをCommitすると… 出た、必殺のコーヒーマーク! これがMySQLの排他的行ロックである。 ここで、MySQLコマンドラインで、


 commit;


を実行すると、コヒーマークは消えて、レコードがCommitされた。 MySQLの排他的行ロック(select for update)は他ユーザがレコードをselectすることを妨げず、よってFileMakerのレイアウト上にも表示される。 また一旦表示されたレコードは、他のユーザが編集していたとしても、後発ユーザの編集を妨げるよなFileMaker的ロックは行われない。 しかし、いざCommitを実行しようとすると、コーヒーマックが出て、select for update を実行したユーザのトランザクションがCommitかRollbackされるまで、コヒーマークが出たまま、つまりロックされた状態となる。
【FileMakerとMySQLコマンドライン】
select ~ for update 後にFMで編集→確定ボタンすると、コーヒーカップが… 
注:
通常、ロックが発生から60秒後に、「[MySQL][ODBC 5.1 Driver][mysqld-5.1.58-community]Lock wait timeout exceeded; try restarting transaction」というエラーが返る。レコード確定ステップ実行後に後処理がある場合は、このエラーをトラップして処理を中止するなど適切な処理を行わないと、システムが暴走する可能性があるので要注意
FileMakerからも「SQLを実行」スクリプトステップに上記内容を直書きしたり、ストアドプロシージャをCALLすれば、ロックやトランザクションを利用できる。試しに


BEGIN
start transaction;
 select * from 売上ヘッダ where 売上No=1 for update;
 select sleep(60);
 rollback;
END;


というストアドプロシージャを作成して、「SQLを実行」ステップからこれをCALLしてみる。 問題なく実行でき、結果、60秒の間そのレコードは更新できなくなる。しかし 「SQLを実行」 ステップはクライアントPCにDSN登録がないと実行できない、という問題があるため、FileMakerからMySQLトリガを発生させてストアドを実行したい(この方法については『売上猫くん on MySQL』開発日記 - 3 - FMからストアド、トリガを参照)。 ということでトリガから上記のストアドを実行しようとすると、「 Not allowed to return a result set from a trigger」というエラーが出るので、レコードセットが返らないように下記のようにストアドを書きなおした。

BEGIN
    declare temp int;
    start transaction;
        select Count(*) into temp from 売上ヘッダ where  売上No =1 for update;
        select sleep (60) into temp;
        update appliasons set ret="OK" where ID=appId;
    commit;
END
ところが残念なことが重なる。今度は「Explicit or implicit commit is not allowed in stored function or trigger.」というエラーが返ってくる。 これでMySQLのトリガではトランザクションが使用できないことがわかった。まえに小生が書いた記事『売上猫くん on MySQL』開発日記 - 番外12 - トリガの制約に、この件をちらっと書いていた(恥)。 
結論としては、ストアドを直接実行すればMySQLのロックを実行できるが、トリガを介したストアド実行によるロックは不可、ということになる。

尚、FM12の新関数ExecuteSQL関数では、MySQLのロックは利用できない(つか、この関数、相当中途半端な上、意味不明なクエリを発する。書いた通りの動きをしないこともあるし…。この辺りは後日機会があれば)。


2.FileMakerライクなロック
次にFileMakerライクなロック。これは開発者が自分でゴリゴリ書かなくてはならないのでかなり面倒だ。 以下は小社のFileMaker/MySQL講習テキストから実装方法を引用する。
【実装】
“編集”ボタンを用意し、レコードを変更する必要があるユーザには“編集”ボタンを実行して「編集モード」にすることを義務付ける。編集モードでなければレコードの変更は実行できないよう制御するとともに、“編集”ボタン実行時には、当該レコードのロックフラグフィールド(cntLockId)にユーザ固有のIDをセット。このフラグが解除されない間は他ユーザが当該レコードの変更を行えないように制御。ユーザがレコードの更新を終えCommitした瞬間にこのロックフラグフィールドを解除するように設計する。
名称
種類
仕様
cntLockId
フィールド
(
テキスト)
編集ボタンを実行するとこのフィールドにユーザ固有のID=Get ( 持続 ID )が入力され、このIDを持たない他ユーザは編集不可となる。 
cntLockTiime
フィールド
(
タイムスタンプ)
編集ボタン実行時に[cntLockId]とともに本フィールドにはサーバのタイムスタンプ(現日時)が入力される。 このタイムスタンプによりデッドロックになっていないかを判断し、管理者は適切な処理をおこなう。
cntLockAC
フィールド
(
テキスト)
必要に応じて作成。編集ボタン実行時にGet ( アカウント名 )が入力される。 これを利用すれば、編集実行者を画面上に表示することができる。
(ユーザが手入力可能なフィールド)
フィールド
OnObjectEnterスクリプトトリガを用いて、[cntLockId<> Get ( 持続 ID )の場合は、フィールドに入れない(フィールド値を変更できない)ように制御。
編集
ボタン
上記のcntLockId/ cntLockTiime/ cntLockAC参照。左記3フィールドに値を入力後にレコードを確定する。これによりそのレコードは他ユーザによる編集が不可となる。
確定
ボタン
上記のcntLockId/ cntLockTiime/ cntLockACの値をクリア(ロックを解除)後、レコードを確定する。
復帰
ボタン
デッドロックしないよう([cntLockId]の値が残らない)ように制御。
他のボタン
ボタン
削除ボタン、削ボタン(売上明細削除用)など、当該レコードを変更する可能性があるボタン、スクリプトは[cntLockId]に他ユーザのIDがある場合は、実行出来ないように制御する。

【編集ボタンによるFileMakerライクなロック】

[cntLockId]と同じGet(持続ID)を持つユーザのみが編集可となり、確定ボタンが完了すると[cntLockId][cntLockTime][cntLockAC]はnullとなり、他のユーザも編集可能となる。


注:
サーバのRemote Desktop Service を介して複数人でFileMakerを使用する場合、Get(持続ID)は重複すると思われる。この場合、他の方法で個別IDを取得すること。

(土屋)