I言語技術情報2(データベース関連)


データベース関連。
データベース関連は、SQLが使えるので改善の対象にしなくても良いとも言えますが、 それでは大幅な生産性の改善は出来ないので、データベース関連においても徹底的に改善を試みました。
(1)まず、データーベースへの接続関連は全てI言語側で行います。生産性改善の意味もありますが、 システム開発者がパスワードを知る必要が無い点で、セキュリティ上の脅威を軽減できます。
念のため接続時の文字列を示しておきます。
ログインIDは”I_[システム名]_[REAL/TEST]_[DBO/INP/OUT]_[許可]”です, 使用の条件に合わせてログインIDが切り替わります。
(テスト中はTESTで本番はREALです)
(メニューがOUTPUTはOUTでINPUTはINPですが、I言語自身が使用する場合はDBOです)
(許可はメニューで指定した物が使われますが、I言語自身が使用する場合はZZZZを使用します)
①MSSQLの接続文字列(using System.Data.SqlClient)
Data Source=[サーバー名][¥インスタンス名];User ID=[ログインID];Password='[パスワード]';Connect Timeout=[30]
(注意:MSSQLの場合データベース名の指定はありません、 ログインID別に接続するデータベース名が決まっており、 I_[システム名]_[REAL/TEST]_MAST_[許可]に成ります。 ただし、I言語としてはテーブルで陽にデータベース名まで指定するので、 接続されるデータベースが何であるかを想定する必要はありません、 問題が出た時のヒントとしては覚えていても損はないです)
②PostgreSQLの接続文字列(using Npgsql)
SERVER=[サーバー名];DATABASE=i_[システム名(小文字)];USER ID=[ログインID(小文字)];PASSWORD=[パスワード];ENCODING=UNICODE;
③IBM DB2の接続文字列(using IBM.Data.DB2)
Server=[サーバー名];Database=I_[システム名];User ID=[ログインID];Password='[パスワード]';
(注意:サーバーインストール時に下記の処理を行っています)
db2cmd -c db2 catalog tcpip node I_[システム名] remote [サーバー名] server 50000
db2cmd -c db2 catalog database I_[システム名] at node I_[システム名]
④Oracleの接続文字列(using System.Data.OracleClient)
データソース名は(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = [サーバー名])(PORT = 1521))) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = xe)))です。
(注意:データソース名は長いですがクライアントの設定をしないで接続時に陽に指定しています、SERVICE_NAMEはExpressがxeで以外がorclになります)
Data Source=[データソース名];User ID=[ログインID];Password='[パスワード]'
(2)SQLでは更新用SQL文として作成はINSERT、修正はUPDATE、削除はDELETEが有ります。一方、I言語ではDELETEは基本的に使用しない事にしたため削除はUPDATEでZ_CANCELに日付けを入れる論理削除としています、理由は問題発生時の原因究明を可能にするための更新履歴を残したいためです。 よって、I言語では作成はINSERT又はUPDATE(削除データの復活)、修正と削除はUPDATE(ただし、削除データはNG)となります。 これを全てプログラムする事は大変ですしミスも多くなるので、ほとんどをI言語にまかせました。 通常のテーブル更新は全てI言語が行います、一方、個別に対応する場合はPROGRAM{}命令を作りましたので、これを使う事で簡単に出来ます。
(3)RDBMS(リレーショナルデータベースマネージメントシステム)で使用方法がかなり違う物があります、 この部分に関しても改善をしています、
まず、表現の異なる部分はシステム変数を利用することで解決しています、たとえば文字列結合する場合の"_C"です、 SQL Serverは"+"になり以外のRDBMSは"||"となる事で、 プログラム上は同じコーディングで良いことになります。
これでも解決出来ない場合は、データベース別に行を選択できる行制御命令を用意しました。
更に、SQL関連の命令もRDBMS別に異なるSQL文を組み立てる事で違いを吸収しています。
(4)SQLとI言語間のデータの受け渡し方法については、 他の言語ではSQL文の文法を変えて対応する方法が多いですが、 I言語では一番分かりやすい事を重視しSQL文をそのまま利用する方法を取っています。 そこで、SQLからデータを受け取る方法を2種類用意しました。
1個目は1件のデータのみ受け取る場合で、SQL_SET{I言語側データ名[,...]}{SQL文}です。
2個目は複数のデータを受け取る方法で、SQL1{SQL文}(またはSQL2)でSQLを発行し、 SQL1_NEXT{I言語側データ名[,...]}(またはSQL2_NEXT)で1件づつデータを受け取ります。
(注意:I言語としては最初のSQL1で全てのデータをクライアントのメモリー上に受け取ります、 大量のデータを受け取るとクライアントのメモリーが圧迫されるので注意が必要です、 尚、これを行っている理由はサーバーのメモリーを早く開放しサーバー側の負荷を極力下げる事を狙っています)
一方、SQLに渡す方法はSQL文内に直接書きます、 そこでデータ名の前後に”?”を付ける事でそのデータ名の内容に置き換わる事としました。
尚、SQL文の場合文字列には引用符を付ける必要があります、また、NCHARの場合は先頭にNを付ける必要があります、 数値は逆に引用符を付けない(ただし、SQL Serverの場合は付けてもエラーになりません)ようにする必要があります、 これを個々に対応する事はミスの元ですのでこの部分も含めて記入する変数も用意しました、 たとえばSQL ServerでNCHARのX1.~~_DATA(X1.~~_DATAがSET=,DATA=,WORK=で宣言されている事が条件)を扱う場合 「?_VE&X1.~~_DATA?」と書く事で「X1.~~DATA=N'?X1.~~_DATA?'」としてくれます。 この場合は、先頭の_がシステム変数で2番目のVがVALUEで右側を値とする、 3番目がEqual(=)の意味とI言語が解釈します。
尚、文字列変換の結果、引用符の中身が空になってしまった場合、OracleではNULLと解釈し誤動作してしまうので、I言語が気を利かせて空白を追加します。
(4)命令単位の細かな説明。
①作業用テーブルについて。
作業用テーブルは消し忘れが結構出ますので、I言語では?_WORK_TABE?に英字1文字を付加する事を推奨しています。消し残りを対応するため最初に使用作業テーブル分のテーブルを消す事が良いです。3個の場合の消すプログラムは次のように出来ます。
100 REPEAT=_A_C
200 DROP_TABLE{?_WOEK_TABLE??_A##?};
300 REPEAT=
_A_Cの内容は3です、つまり、Cはアルファベットで3番目を意味しています。
?_A##?の方は順番に'A','B','C'となります。
DROP_TABLEはテーブルが無い場合はエラーとならないで正常終了するので、無い場合の対処は不要です。。
尚、メニュー起動ジョブの場合BEGIN_ENDの下に書けば最初と最後に実行できます。時間起動の場合はNAME=DROP_TABLEとNAME=で挟み最後にCOPY=DROP_TABLEとします。
次に作業用テーブルを作る方法ですが、2種類を用意しました。1個目はすでに有るテーブルと同じ構造の物を作りたい場合です。
400 =COPY_TABLE{?_WORK_TABLE?A}{?_M?_SAMPLE_TABLE}{NOT};
テーブルをコピーする命令で作りますが、{NOT}とする事でデータ自体はコピーしません。 ちなみに、NOTを空にするとコピーし,NOTでも空でもない場合はコピーのSQL文に記入内容を付加します。
2個目は新たに作る場合です。
500 =CREATE_TABLE{?_WORK_TABLE?B}
600 = {~~_KEY1_SAMPLE,*,~~_KEY2_SAMPLE,*}
700 = {~~_CHAR,*,~~_INT,*,~~_DECIMAL,*,~~_DATE,*};
最初(500)がテーブル名で次(600)がキー項目の列で最後(700)が従属項目の列です。 *とする事で型や長さをデータ辞書から設定します。当然直接指定する事もできます。
尚、CREATE_TABLEではZ_CANCEL等のI言語指定の列も作られます、これを付けたくない場合はCREATE_TABLE2(最後に2を付加)とすれば付きません。
②ファイル連携について。
他のシステムと連携する場合はSQL Serverであればリンクサーバーの機能を使うことでSQL内で連携できますが、SQL Server以外では出来ません。この場合はファイルを使って連携する事になります。
連携できるファイルの構造を2種類用意しました。1個目がTAB形式と呼びます がデータをTABで区切る構造で、2個目はCSV形式でカンマで区切るものです。 (データの中にカンマ又は2重引用符が有った場合がデータを2重引用符で囲み2重引用符は2個連続にします)。 I言語では拡張子がCSVの物はCSV形式で以外は全てTAB形式と判断します。
ファイルを作る命令は以下です。
SQL_FILE{付加ファイル名}{[OT,ADD]}{[エンコード]}{SQL文}..;
尚、SQL_FILEは¥I¥TMP上に_JOB名が先頭について作られますが別の所にファイル名を指定して作る場合はSQL_FILE2を使います。
(注意:¥I¥TMP上のファイルは2日以上経つとI言語が消しますので注意下さい)
ファイルからテーブルにINSERTする命令は以下です。
INSERT_FILE{テーブル名}{列名,...}{ファイル名}{エンコード}..;
尚、INSERTで作りますのでテーブルは空である事を推奨します(キーが重複するとエラーとなる)よって通常は作業テーブルにINSERTしマスタテーブルに対しては以下の命令を使用します。
REPLACE_ALL{出力テーブル名}{入力テーブル名}{キー列名,..}{データ列名,..}{出力条件}{入力条件}..;
All Rights Reserved, Copyright (C) 2009-2010 Nobumichi Harasawa.