HOME > R3D > R3Dでできること



R3Dでできること



 R3Dは従来のプログラミングの考え方とその考え方に違いがあります。
  その「考え方の違いについてはここ」をご覧下さい。

 それでは、次の目次に沿って具体例を示しながら説明していきましょう。
  また「説明で利用するデータベースの定義についてはここ」をご覧下さい。

目次
 1.同一テーブル内でのフィールド間の演算
  ①フィールド間での四則演算
  ②自動的に日付をセット
  ③自動的に売上日をセット
  ④行番号の自動採番
 2.異なるテーブル間の演算
  ①コード値による名称の自動取得
  ②同じコードを持つ名称の一斉自動更新
  ③読出しのみの関数
  ④条件文を使う
  ⑤自動集計関数
  ⑥請求書データの自動作成
 3.異なるデータベース間の演算
  ①他データベースとのデータ同期
  ②他データベースとの非同期関数
 4.異なるサーバ間の演算
  ①リンクサーバの登録
  ②R3Dでの異なるサーバの記述
 5.自動コード付
 6.自動ログ書出し
 7.統計データの自動作成
 8.データ内容のチェック
 9.ストアードプロシージャをR3Dの導出定義文から利用する
10.EXCELとの連携
11・データの依存関係の表示





1.同一テーブル内でのフィールド間の演算
① フィールド間での四則演算
フィールド間で四則演算を行います。その一例を示します。

導出定義文 テーブル=受注明細
フィールド:合計 = f.数量*f.単価

上記の例は、「合計」が「数量」と「単価」を掛けることによって求められると定義した例です。次に、自動的に計算されるところをコマンドプロンプトからosqlを起動してその様子を見ます。f.はフィールドであることを示しています。

1>select 受注番号,行番号,商品コード,商品名,数量,単価, 合計
2> from 受注明細 where 受注番号=100 order by 行番号
3>go
受注番号 行番号 商品コード 商品名 数量  単価 合計
 100    1    A001   マヨネーズ   2  198   369 
 100    2    A002   納豆      3   98   294
(2件処理されました)
1>insert into 受注明細(受注番号,行番号,商品コード,数量)
2> values(100,0,'A003',5) *1
3>go
(1件処理されました)
1>select 受注番号,行番号,商品コード,商品名,数量,単価,合計
2> from 受注明細 where 受注番号=100 order by 行番号
3>go
受注番号 行番号 商品コード 商品名 数量  単価 合計
 100    1    A001   マヨネーズ   2  198   369 
 100    2    A002   納豆      3   98   294
 100    3    A003   砂糖      5  208  1040
(3件処理されました)
1>

*1 Insert命令での行番号が0になっていますが、行番号が0のとき、その受注番号で最大値を自動的に取ってくるR3D記述があるとします。
*1 同様にInsert命令で、商品コード(A003)と数量(5)を与えるだけで、商品名(「砂糖」)と単価(208円)が商品マスターから自動的に持って来られて数量(5)と掛けられて1040円となった例です。


② 自動的に日付をセット
自動的に日付を入れます。以下はその一例です。

導出定義文 テーブル=受注明細
フィールド:修正日時 = getdate()

テーブル内の任意のフィールドが変更されたときに、日付と時間を「修正日時」に代入するという例です。先ほどの①の例でinsertした商品の「数量」を変更して、「修正日付」に日付と時間が自動的に代入されるところを見ます。なお、「getdate()」は、DBMSの標準関数です。

1>update 受注明細 set 数量=6
2> where 受注番号=100 and 行番号=3
3>go
  (1件処理されました)
1>select 受注番号,行番号,商品名,数量,単価,合計,修正日時
2> from 受注明細 where 受注番号=100 order by 行番号
3>go
 受注番号 行番号 商品名   数量 単価 合計 修正日時
  100     1   マヨネーズ   2  198  369 2007-10-1 12:10:10 
  100     2   納豆      3   98   294 2007-10-1 12:11:12
  100     3   砂糖      6  208  1248 2007-10-2 14:15:17 *1
1>

*1 修正日時には、自動的に本日の日付が入ります。


③ 自動的に売上日をセット
売上が上ったときに自動的に売上日がセットされるようにします。その一例です。

導出定義文 テーブル=受注明細
フィールド:売上合計 = f.売上数*f.単価
フィールド:売上日 = if f.売上合計 is not null
   { convert(nvarchar(10),getdate(),111) }

先ほどinsertしたデータに対して「売上数」に値を入れることによって、売上合計を自動的に求め、かつ、売上合計に値が入れられた(nullでない)ことをもって売上日に本日を代入する例です。

1>update 受注明細 set 売上数=6
2> where 受注番号=100 and 行番号=3 *1
3>go
  (1件処理されました)
1>select 受注番号,行番号,商品名,単価,売上数,売上合計,売上日
2> from 受注明細 where 受注番号=100 order by 行番号
3>go
 受注番号 行番号 商品名   単価 売上数 売上合計 売上日
  100     1   マヨネーズ  198 
  100     2   納豆      98
  100     3   砂糖      208   6    1248  2007-10-2 *2
1>

 

*1 ここで売上を立てています。つまり、売上数に6をセットしますと、自動的に売上額が計算され、さらに、売上日も入っています。 *2


④ 行番号の自動採番
受注番号単位に行番号が自動的に最大値に1プラスしてセットされる様にします。

導出定義文 テーブル=受注明細
フィールド:行番号 = if insert{
getmax(f.行番号[where f.受注番号=f.受注番号])+1
}


上記の例は、受注明細がinsertされたときは、自動的にその受注番号での行番号の最大値+1を持ってきて、それを行番号に代入しています。
getmaxはR3D関数で最大値を読み出す意味です。

1>insert into 受注明細(受注番号,行番号,商品コード,数量)
2> values(100,0,'A003',5)
3>go
(1件処理されました)
1>select 受注番号,行番号,商品コード,商品名,数量,単価,合計
2> from 受注明細 where 受注番号=100 order by 行番号
3>go
受注番号 行番号 商品コード 商品名 数量  単価 合計
 100    1    A001   マヨネーズ   2  198   369 
 100    2    A002   納豆      3   98   294
 100    3    A003   砂糖      5  208  1040 *1
(3件処理されました)
1>

*1 Insert命令で新たに格納したデータです。insert時での行番号は仮に0を指定していますが、自動的に行番号が3になっています。(注)行はキーなので、指定しないとnullになりエラーとなってしまいます。



2.異なるテーブル間の演算
① コード値による名称の自動取得
以前ではデータストレージ(HDDディスクなど)の価格が高かったことと、正規形のデータモデルを重視してデータを重複して持つことはしませんでしたが、最近ではむしろ処理パフォマンスを重視し、処理の重いViewを使わず、むしろデータを重複して持たせることも多くなりました。そのときに問題となるのが、関連するテーブルからのデータの取得とそのメンテナンスです。R3Dでは、これらの処理をR3D関数で簡単に記述することができます。
次の例は、マスターテーブルからコード値を与えて名称,単価を得る例です。

導出定義文 テーブル=受注明細
フィールド:商品名 = val(t.商品マスター.商品名[
where t.商品マスター.商品コード=f.商品コード])
フィールド:単価 = val(t.商品マスター.単価[
where t.商品マスター.商品コード=f.商品コード])

商品コードが与えられたときに、商品名や単価が商品マスターから自動的に持って来られて代入される例です。 「t.」はテーブルであることを示しています。

1>select * from 商品マスター *1
2>go
商品コード 商品名  商品種別 単価 単位  在庫数
 A001   マヨネーズ 食品   198  本    300
 A002   納豆     食品    98  パック   70
 A003   砂糖     食品   208  袋     150
 A004   バター    食品   168  個     200
(4件処理されました)
1>insert into 受注明細(受注番号,行番号,商品コード,数量)
2> values(100,0,'A003',5) *2
3>go
(1件処理されました)
1>select 受注番号,行番号,商品コード,商品名,数量,単価,合計
2> from 受注明細 where 受注番号=100 order by 行番号 *3
3>go
受注番号 行番号 商品コード 商品名 数量  単価 合計
 100    1    A001   マヨネーズ   2  198   369 
 100    2    A002   納豆      3   98   294
 100    3    A003   砂糖      5  208  1040
(3件処理されました)
1>

*1 まず商品マスターの内容を見ます。
*2
次に、商品コード「A003」を格納します。
*3
行番号3に、A003が商品マスターから「商品名」「単価」が自動的に持って来られ、合計が計算されたところを見ます。


② 同じコードを持つ名称の一斉自動更新
ある商品コードの商品名が変わったとき、全てのその商品コードを持つ商品名は、自動的に変更されます。つまり、コードの値とそのコードを持つデータの内容とがR3Dによって常に同期を取られるということです。以下はその一例です。

導出定義文 テーブル=受注明細
フィールド:商品名 = val(t.商品マスター.商品名[
where t.商品マスター.商品コード=f.商品コード])
フィールド:単価 = val(t.商品マスター.単価[
where t.商品マスター.商品コード=f.商品コード])

商品マスターの中のコードが「A002」の名称が「納豆」であるところを「自然納豆」に変更します。 そうしますと、受注明細のそのコードを持つデータの名称も一斉に更新される例です。

1>update 商品マスター set 商品名='自然納豆'
2> where 商品コード='A002' *1
3>go
(1件処理されました)
1>select 受注番号,行番号,商品コード,商品名 
2> from 受注明細 where 商品コード='A002' *2
3>go
受注番号 行番号 商品コード 商品名
   90    1    A002   自然納豆
   92    4    A002   自然納豆
   100    3    A002   自然納豆
   101    1    A002   自然納豆
   105    6    A002   自然納豆
(5件処理されました)
1>

*1 商品マスターのコード「A002」の商品名「納豆」を「自然納豆」に変更します。
*2
商品コードが「A002」を持つ受注明細データの全てが変ったことを確認します。


③ 読出しのみの関数(非同期関数)
伝票データなどにおいて、データ作成時の内容でそのまま保存しなければならない場合があります。
その場合、初期にデータを格納するときには、マスターからデータを引いてセットしますが、セットした後は、マスターの内容が変更されても、連動して内容が変更されないように定義することもできます。 その定義は、R3D関数名の前に"get"をつけることによって可能となります。以下に例を示します。

導出定義文 テーブル=受注明細
フィールド:商品名 = getval(t.商品マスター.商品名[
where t.商品マスター.商品コード=f.商品コード])
フィールド:単価 = getval(t.商品マスター.単価[
where t.商品マスター.商品コード=f.商品コード])

こうすることによって、たとえ商品の単価が変動しても、過去の伝票の内容は変更されません。 もちろん、新規に受注明細データを登録する場合には、その時点での商品マスターに登録されている単価が自動的に持って来られます。
この関数を使うことによって、リアルタイムにデータの同期した更新をせず、 あとでまとめて(バッチで)データ更新をして処理パフォマンスを上げることもできるようになっています。


④ 条件文を使う
値を代入するに当たって、無条件に代入するのではなく、条件を付けたいことも多くあります。 その場合は、通常の手続きプログラムと同様に「if」文を使います。 このif文を使うことによって、通常のプログラムと同じ処理を行うことができます。以下はその一例です。

導出定義文 テーブル=受注明細
フィールド:商品名 = if update(f.商品コード) {
getval(t.商品マスター.商品名
[where t.商品マスター.商品コード=f.商品コード])
}
フィールド:単価 = if update(f.商品コード) {
getval(t.商品マスター.単価
[where t.商品マスター.商品コード=f.商品コード])
}

この例は、商品コードが変更された(insertを含みます)ときのみ商品名や、単位を持って来るという記述例です。
例えば、新規に伝票を入力する際、商品コードを指定すれば自動的に商品名が商品マスターから読み出して持って来られますが、 その商品名を自由に書き換えたいときなどに指定します。 もし、このif文の指定がない場合は、商品マスターと同期がとられますので、商品名が変更されても、 その時点で商品マスターから登録されている商品名が再度持って来られその変更に上書きされてしまいます。 逆に、常にマスターの値と同期を取って同じとしたい場合は、if文は不要です。


⑤ 自動集計関数
sumなどのR3Dの集計関数によって他テーブル内にあるデータの合計値を自動的に集計してセットします。 また、集計の元データが変更された場合でも、自動的に集計値が連動して変更されます。以下に例を示します。

導出定義文 テーブル=受注マスター
フィールド:受注額 = sum(t.受注明細.合計[
where t.受注明細.受注番号=f.受注番号])
フィールド:売上額 = sum(t.受注明細.売上合計[
where t.受注明細.受注番号=f.受注番号])

受注明細にデータを追加したら上位テーブルの合計額も自動的に集計されセットされるところを見ます。

1>insert into 受注明細(受注番号,行番号,商品コード,数量)
2> values(100,0,'A003',5) *1
3>go
(1件処理されました)
1>select 受注番号,行番号,商品コード,商品名,数量,単価,合計
2> from 受注明細 where 受注番号=100 order by 行番号 
3>go
受注番号 行番号 商品コード 商品名 数量  単価 合計
 100    1    A001   マヨネーズ   2  198   369 
 100    2    A002   納豆      3   98   294
 100    3    A003   砂糖      5  208  1040 *2
(3件処理されました)
1>select * from 受注マスター where 受注番号=100
2>go
受注番号 顧客番号  受注日   納期     受注額 
  100     10    2007-10-1 2007-10-3  1703 *3
(1件処理されました)
1>

*1 受注番号100番に新たな受注を追加しました。
*2追加された行です。
*3上位のテーブルの受注番号100に、受注明細の合計額の集計値が自動的に1703になっています。


⑥ 請求書データの自動作成
締日ごとの請求書を自動的に作成します。以下は、締日に従って請求書が作成される例です。

導出定義文 データベース=販売データベース
テーブル:請求書マスター = relation R請求書[ to t.受注明細
where t.受注明細.顧客コード=f.顧客番号 and
t.受注明細.売上日 between
dateadd(m,-1,dateadd(d,1,f.今月締日)) and f.今月締日]

導出定義文 テーブル=請求書マスター

フィールド:総額 = sum(t.受注明細.売上合計[relation R請求書])

顧客番号10番の顧客の締日が毎月20日とします。
2007年9月20付の請求書を作成します。
その場合、売上日が、8月21日~9月20日までの売上額が請求額となります。

1>insert into 請求書マスター
2> (請求書番号,顧客番号,今月締日)
3> values(0,10,'2007-09-20') *1
3>go
(1件処理されました)
1>select * from 請求書マスター
2> where 顧客番号=10 order by 今月締日
3>go
請求書番号 顧客番号  顧客名  今月締日  今月請求額
    87     10    ABC商事  2007-08-20  12345
   102    10     ABC商事  2007-09-20  14933 *2
(2件処理されました)
1>

*1 10番の顧客に対して今月の締日(2007-09-20)の請求書をinsertしています。
*2
10番の顧客に対して過去も含めて請求書を印字しました。
2007-09-20の締日の請求書を見ますと、自動的に売上日が2007年8月21日から2007年9月20日までの売上データが集計されて14,933円になっています。 getsumではありませんので、もし、後から受注明細の売上データの更新があれば、自動的にここの今月請求額も更新されます。




3.異なるデータベース間の演算
① 他データベースとのデータ同期
他データベースに存在するマスターテーブルの内容を持って来て、データの同期を取ります。以下はその一例です。人事データベースと販売データベースがあり、人事データベースの内容を販売データベースで同期して利用するときの例です。

関係定義文 データベース=販売データベース
テーブル:社員テーブル = relation R社員M
[to d.人事データベース.社員マスター
where d.人事データベース.社員マスター.社員番号=f.社員番号]
when not found then insert delete me

導出定義文 テーブル=社員テーブル

フィールド:社員名 = val(d.人事データベース.社員マスター.社員名
[ relation R社員M])

人事データベース内の社員マスターの社員名が変更されたなら販売データベース内の社員名も自動的に更新されます。 「d.」はデータベースであることを示しています。もし新規に人事データベース内の社員マスターに社員が追加されたならば、自動的に追加(insert)されますし、削除されたならば、自動的に削除(delete)されます。 もちろん削除されるときは、外部キー制約が満たされないと削除されません。

1>select * from 社員テーブル
2>go
社員番号 社員名
 100   山田太郎
 101   井上花子 *1
(2件処理されました)
1>update 人事データベース.dbo.社員マスター
2> set 社員名='山田花子'
3> where 社員番号=101 *2
4>go
(1件処理されました)
1>select * from 社員テーブル
2>go
社員番号 社員名
 100   山田太郎
 101   山田花子 *3
(2件処理されました)
1>

*1 元の社員番号101の社員名は、「井上花子」さんでした。
*2 大元の人事データベースの「井上花子」さんの名前を、「山田花子」さんに変更しました。
*3 そうすると、販売データベース内の社員テーブルの「井上花子」さんが「山田花子」さんに変更されました。

この場合は、val関数を使っていますので、双方のデータの内容は同期が取られます。すなわち、人事データベースの社員マスターの社員名が変更されますと、販売データベースの販売員マスターの社員名も自動的に更新されます。
また、販売データベースの販売員マスターの社員名を変更したとしても、人事データベースの社員マスターの社員名に戻されますので、データの一貫性が保たれることになります。



② 他データベースとの非同期関数
他データベースに存在するマスターテーブルの内容を持って来ますが、"get"関数を用いることによって同期を取らなくすることもできます。以下に例を示します。

導出定義文 テーブル=社員テーブル

フィールド:社員名 = getval(d.人事データベース.社員マスター.社員名
[where d.人事データベース.社員マスター.社員番号=f.社員番号])
この場合は、社員テーブルの社員名は自由に変更できます。



4.異なるサーバ間の演算
① リンクサーバの登録
異なるサーバ上にあるデータを参照したり同期して更新するためには、
あらかじめリンクサーバとして下記のようにクエリアナライザ等で相手サーバ名
を登録しておきます。

「TokyoServer」と「NYServer」を登録します。

exec sp_addlinkedserver 'TokyoServer', N'SQL Server'
exec sp_addlinkedsrvlogin 'TokyoServer', 'false', NULL,'sa', 'pass777'

exec sp_addlinkedserver 'NYServer', N'SQL Server'
exec sp_addlinkedsrvlogin 'NYServer', 'false', NULL, 'sa','pass789'


② R3Dでの異なるサーバの記述
自分のサーバが、例えば京都支店にある場合、東京本社にある「TokyoServer」内の全社的な商品マスターの内容を参照します。 また、もし東京本社の「TokyoServer」の商品マスターが変更されれば、同期を取って自分の京都支店のサーバ内の商品名や単価も同時に更新されることになります。
ただ、異なるサーバ間でデータベースを扱う場合には、OSの通信のためのオーバヘッドが余分にかかりますので、頻繁に参照/更新されるデータには適しないことがありますので事前のテストが重要となります。

関係定義文 データベース=京都支店データベース
テーブル:商品マスター = relation R全社商品M
[to s.'TokyoServer'.全社DB.全社商品マスター
where s.'TokyoServer'.全社DB.全社商品マスター.商品コード=f.商品コード]
when not found then insert delete me

導出定義文 テーブル=商品マスター

フィールド:商品名 = val(s.'TokyoServer'.全社DB.全社商品マスター.商品名
[ relation R全社商品M])
フィールド:単価 = val(s.'TokyoServer'.全社DB.全社商品マスター.単価
[ relation R全社商品M])

リンクされたサーバを指定する場合は、「s.」と入力しますと、リンクサーバの一覧が表示されますので、その一覧から使用するサーバを選択することができます。

1>select * from 商品マスター
2>go
商品コード 商品名   単価 在庫数 最終入荷日
 A001   マユネーズ  298    98  2008-05-11
 A002   自然納豆    98   125  2008-05-14 *1
(2件処理されました)
1>update [TokyoServer].全社DB.dbo.商品マスター
2> set 商品名='天然納豆'
3> where 商品コード='A002' *2
4>go
(1件処理されました)
1>select * from 商品マスター
2>go
商品コード 商品名 単価 在庫数 最終入荷日
 A001   マユネーズ  298    98  2008-05-11
 A002   天然納豆    98   125  2008-05-14 *3
(2件処理されました)
1>

*1 自分のサーバ内の商品マスターテーブルの内容を表示。
*2 TokyoServer内の全社DBの商品マスターの「A002」の「自然納豆」を、「天然納豆」に変更しました。
*3 そうすると、自分のサーバ内の商品マスターテーブルも「自然納豆」から「天然納豆」に変更されました。



5.自動コード付
 マスターファイルのコード番号付は、大変重要ではありますが面倒な作業でもあります。 そのために、一般のDBMSでは、identity機能が用意されており自動的に番号を作成してくれますが、これはあくまでも数値となります。

そこで次にR3Dによって、商品マスターの商品コードを商品種別に従って、自動採番する例を示します。
フィールド:商品コード = declare @code nvarchar(20)
declare @no int
if insert{
if f.商品種別='食品'
{ set @code=getmax(f.商品コード[where f.商品種別='食品'])
set @no=convert(int,right(@code,len(@code)-1))+1
set @code=convert(nvarchar(3),@no)
'A'+replicate('0',3-len(@code))+@code
}
if f.商品種別='衣料'
{ set @code=getmax(f.商品コード[where f.商品種別='衣料'])
set @no=convert(int,right(@code,len(@code)-1))+1
set @code=convert(nvarchar(3),@no)
'C'+replicate('0',3-len(@code))+@code
}
if f.商品種別='家具'
{ set @code=getmax(f.商品コード[where f.商品種別='家具'])
set @no=convert(int,right(@code,len(@code)-1))+1
set @code=convert(nvarchar(3),@no)
'F'+replicate('0',3-len(@code))+@code
}
}

この例は、商品種別が「食品」のときは、Aから始まる4桁のコードにし、「衣料」のときは、Cから始まり、「家具」のときは、Fから始まるコードの自動作成をしている例です。
自動的にコードがふられるところを見ます。

1>insert into 商品マスター(商品コード,商品名,商品種別)
2> values('0','インスタントラーメン','食品') *1
3>go
(1件処理されました)
1>select 商品コード,商品名,商品種別 from 商品マスター
2>go
商品コード 商品名      商品種別
  A001  マヨネーズ       食品
  A002  納豆           食品
  A003  砂糖           食品
  A004  バター          食品
  A005  インスタントラーメン  食品 *2
(5件処理されました)

*1 商品種別は食品の新しい商品を商品マスターに登録します。insertする場合、商品コードがnullではエラーとなりますので、ここで仮に'0'を入れています。そのあとに新コードが取られます。
*2
インスタントラーメンが、A005番で登録されたところの表示です。




6.自動ログ書出し
 あるデータが更新されたならば、その履歴データを残しておきたいことがよくあります。 通常この処理をプログラムを書いて行いますが、プログラムミスによって書き出されなかったと言うこともよく起こります。 もし履歴データが自動的に出力されるなら、プログラム作成は大変楽になります。以下にその一例を示します。

次のテーブルを販売管理データベースに追加します。

フィールド
属性
備考
主キー
数値
identity で自動番号付与
更新日時
日付
 
商品コード
文字
 
商品名
文字
 
商品種別
文字
 
単価
数値
 
単位
文字
 
在庫数
数値
 
履歴ステータス
文字
「登録」「更新」「削除」をセットします。

 商品マスターが更新されるたびに商品マスター履歴が自動的に格納されるようにします。

関係定義文 データベース=販売データベース

テーブル:商品マスター履歴 = relation R商品履歴
[to t.商品マスター history ]

 「to テーブル名」のあとにhistory句を指定することによって、「to テーブル名」で指定されたテーブルに変更が加えられたならば、 常に左辺の=の前のテーブルがInsertされるようにすることができます。 この場合主キーは、例えばidentityを指定することによって、自動的に採番されるようにしておけば便利でしょう。 例では、商品マスターに新たなデータがinsertされたときは「登録」を、商品マスターの任意のデータがupdateされたときは「更新」を、 また、商品マスターのデータがdeleteされたときは「削除」を履歴ステータスに代入するように、導出定義文にif 文を使って記述しています。

導出定義文 テーブル=商品マスター履歴

フィールド:更新日時 = getdate()
フィールド:商品コード = getval(t.商品マスター.商品コード[relation R商品履歴])
フィールド:商品名 = getval(t.商品マスター.商品名[relation R商品履歴])
フィールド:商品種別 = getval(t.商品マスター.商品種別[relation R商品履歴])
フィールド:単価 = getval(t.商品マスター.単価[relation R商品履歴])
フィールド:単位 = getval(t.商品マスター.単位[relation R商品履歴])
フィールド:在庫数 = getval(t.商品マスター.在庫数[relation R商品履歴])
フィールド:履歴ステータス = if insert(t.商品マスター){ '登録' }
if update(t.商品マスター){ '更新' }
if delete(t.商品マスター){ '削除' }

次に、商品マスター履歴が格納されるところを見ます。

1>update 商品マスター set 在庫数=在庫数-2
2> where 商品コード='A002' *1
3>go
(1件処理されました)
1>select 商品コード,商品名,在庫数 from 商品マスター
2> where 商品コード='A002' *2
3>go
商品コード 商品名 在庫数
A002 納豆 68
(1件処理されました)
1>select * from 商品マスター履歴
2> where 商品コード='A002' order by 更新日時 *3
3>go
主キー 更新日時 商品コード 商品名 単価  単位 在庫数 履歴ステータス
 123 09/20 09:30:10 A002  納豆   98  パック  120   登録
 334 09/25 10:10:15 A002  納豆   98  パック   70   更新
 557 10/01 08:55:10 A002  納豆   98  パック   68   更新
(3件処理されました)
1>

*1 商品コードA002の在庫が2個減らされました。
*2 今在庫が何個になったかを見ます。68個になっています。
*3 商品コードA002の在庫履歴を、古いもの順に出します。70個が68個になったことがよく分かります。




7.統計データの自動作成
統計データの作成についても、システム開発者にとっては、技術面だけでなく運営面からもミスが起こらないようにするためむつかしい問題を持っています。 そこで、それほど大量のトランザクションを取り扱う事のないシステムでは、R3Dによって自動化することが可能です。 そこで、販売データベースに次のテーブルを追加して、統計データの自動取得を行います。

 年統計
   月統計    日統計
フィールド
属性
備考
年
日付
主キー1
種別
文字
主キー2
金額
数値
 
 
フィールド
属性
備考
年
日付
主キー1
月
日付
主キー2
種別
文字
主キー3
金額
数値
 
 
フィールド
属性
備考
年
日付
主キー1
月
日付
主キー2
日
日付
主キー3
種別
文字
主キー4
金額
数値
 

 なお、種別には「受注」「売上」「発注」「仕入」などが入るものとします。 でも例では売上だけを扱うものとします。

関係定義文 データベース=販売データベース

テーブル:年統計 = relation R年[to t.月統計
   where t.月統計.年=f.年 and
       t.月統計.種別=f.種別]
   when not found then insert me
テーブル:月統計 = relation R月[to t.日統計
   where t.日統計.年=f.年 and
       t.日統計.月=f.月 and
       t.日統計.種別=f.種別]
   when not found then insert me
テーブル:日統計 = relation R日[to t.受注明細
   where t.受注明細.売上日=f.日 and
       f.種別='売上']
   when not found and t.受注明細.売上日 is not null then insert me
   with no key change

「when not found」句を指定することによって、where以下の条件が見つからないときは、自分自身をinsertすることができます。また、その際、売上日に日付が入っているときだけ実行されるように、売上日がnullでないときの条件を付加することもできます。
さらに、「with no key change」句を指定することによって、売上日が変更されたとしても日統計のキーである日付データまで変更されないようにすることができます。これは、売上計上後にその計上日が変更されることはよくあることだからです。
また、年統計,月統計,日統計テーブルのフィールドの導出定義文には、次の様に記述を行います。

導出定義文 テーブル=年統計

フィールド:年 = val(t.月統計.年[relation R年]when not null)
フィールド:種別 = val(t.月統計.種別[relation R年]when not null)
フィールド:金額 = sum(t.月統計.金額[relation R年])

 導出定義文 テーブル=月統計

フィールド:年 = val(t.日統計.年[relation R月]when not null)
フィールド:月 = val(t.日統計.月[relation R月]when not null)
フィールド:種別 = val(t.日統計.種別[relation R月]when not null)
フィールド:金額 = sum(t.日統計.金額[relation R月])

 導出定義文 テーブル=日統計

フィールド:年 = set @売上日=val(t.受注明細.売上日[relation R日])
 convert(datetime,convert(nchar(4),year(@売上日))+'/01/01')
フィールド:月 = set @売上日=val(t.受注明細.売上日[relation R日])
 convert(datetime,convert(nchar(4),year(@売上日))+'/'
       +convert(nchar(2),month(@売上日))+'/01')
フィールド:日 = val(t.受注明細.売上日[relation R日])
フィールド:種別 = '売上' /* 例では売上のみ */
フィールド:金額 = sum(t.受注明細.売上合計[relation R日])

統計データが作成されるところを見ます。

1>select * from 日統計 where 月='2007-10-01' *1
2>go
   年        月        日       種別   金額
 2007-01-01  2007-10-01  2007-10-01    売上   12345
 2007-01-01  2007-10-01  2007-10-02    売上   12555
  (2件処理されました)
1>insert into 受注明細 (受注番号,行番号,商品コード,
2> 数量,売上数,売上日)values
3> (100,0,'A002',3,3,'2007-10-03')  *2
4>go
  (1件処理されました)
1>select * from 日統計 where 月='2007-10-01
' *3
2>go
   年        月        日       種別   金額
 2007-01-01  2007-10-01  2007-10-01    売上   12345
 2007-01-01  2007-10-01  2007-10-02    売上   12555
 2007-01-01  2007-10-01  2007-10-03    売上    294
  (3件処理されました)
1>select * from 月統計 where 月='2007-10-01'  *4
2>go
   年        月      種別    金額
 2007-01-01  2007-10-01   売上   25194
  (1件処理されました)
1>

*1 まず現時点での10月(2007-10-01となる)の統計データを見ます。
*2 10月3日に売上が追加されました。294円でした。
*3 再度、10月の統計データを見ます。10月3日のデータが増えています。
*4 さらに月統計も自動的に集計されているところを見ます。年統計は省略されていますが、月データが年で自動的に集計されます。




8.データ内容のチェック
データベースに投入されるデータのチェックは、DBMSのcheck句によって行う事が出来ると言うことは広く知られています。 しかしながら、少し複雑な条件によるチェックを行いたい場合には、データベースにアクセスするプログラム内で行うしかありませんでした。
しかしながら、R3Dでは、各フィールド毎に手続文でのチェックロジックを定義することができますので、データベース内にデータの正当性ロジックを埋め込むことができます。以下はその例です。

導出定義文 テーブル=社員マスター

フィールド:性別 = if me<>1 and me<>2
   { display '性別がまちがっています。' rollback }
フィールド:生年月日 = if me>dateadd(yy,-10,getdate())
   { display '10才以下の社員は登録できません。' rollback }
  性別は、1が男 2が女 とします。



9.ストアードプロシージャをR3Dの導出定義文から利用する
R3Dは、手続文によって複雑なロジックを記述することが可能ですが、さらにデータベースを検索した結果をR3Dロジック内で扱ったり、複雑な演算をしたい場合もあります。 その場合は、あらかじめストアードプロシージャを登録しておき、導出定義文から呼び出して利用することができます。以下はその一例です。

ストアードプロシージャの例 
(導出定義文内では、Select文を使えないのでストアードプロシージャ内でselect検索する)
create procedure P_性別
(@入力 int, @出力 nvarchar(10) output)
as
set @出力=null
select @出力=性別 from コードマスター
where コード=@入力
if @出力 is null
begin
set @出力='性別不正'
end
return

 導出定義文 テーブル=社員マスター

フィールド:性別 = set @性別=''
     execute P_性別 me,@出力=@性別 output
     print '性別は'+@性別+'です。'

この例は、商品種別が「食品」のときは、Aから始まる4桁のコードにし、「衣料」のときは、Cから始まり、「家具」のときは、Fから始まるコードの自動作成をしている例です。
自動的にコードがふられるところを見ます。

1>insert into 社員マスター
2> (社員番号,社員名,性別,生年月日,住所)
3> values(7,'山田太郎',1,'1980-07-07','東京都')
4>go
  性別は男です。 *1
  (1件処理されました)
1>

*1 「男」がストアードプロシージャから返されて表示した例。




10.EXCELとの連携(R3D Sheet)
表形式でデータ表示・修正等を行う表計算ソフト,たとえばマイクロソフト社のEXCELなどは、その使い勝手の良さで広く利用されています。
BookやSheetにまたがってデータを集計したり、連鎖的にデータの更新ができるところが重宝されています。しかしながら、大量のデータが扱えないことと、複数の作業者で共有して使用することができないという最大の難点を持っています。R3Dは、EXCELの様に連鎖的なデータの更新を可能とし、しかも、多数の作業者にてデータの共有を可能とするデータベースの特徴をも合わせ持っています。
そこで、R3Dで連鎖的に更新されたデータベース内のデータをEXCELに渡し、EXCEL上でそれらのデータの取扱を行うインターフェースを用意しています。 そのインターフェイスのことをR3D Sheetと言い、DLL形式のR3DS関数を利用することによって、Excel上でリアルタイム(DBに対する直接更新や更新後での即時読み出し)でのデータベースの利用を可能とします。

       



11.データの依存関係の表示
R3Dの特長は、あるデータの更新が引き金となって、そのデータ内容が影響を与えるデータを連鎖的に更新するところにあることを述べました。
これらは、R3Dによって水面下で自動的になされますので、どのデータの変更が、どのデータの変更を引き起こすかという事を把握しておく事が必要となります。この事をデータの依存関係の把握と言いますが、何らかのツールがなければむつかしいものです。R3Dでは以下の様な画面を用意して、この項目は、どの項目の変更によって連鎖的に変更されるかを知る事ができます。



表中「関連」がつけられたデータベース名,テーブル名,フィールド名が、影響を与える元となるデータを示しています。なお、()で囲まれたフィールド名は、getが付けられた関数によってデータの読み出しのみが行われ、その内容の変更は、連鎖的に変更されない事を意味しています。




pagetop