}I言語の学習 3. CREATE,DROP,INSERT,UPDATE,DELETE


(◆はSQL文,◇はSQLの説明、★はI言語の命令、☆はI言語の説明です,◇は共通の説明です)
3.1 CREATE TABLECREATE TABLE テーブル名(列名 データ型 [NOT NULL][DEFULT 内容][,...])([]は省略可能の意味で,...は繰り返しの意味) 
3.1.1◆CREATE TABLE TA(STUDY_C CHAR(4) NOT NULL DEFAULT ' ',STUDY_N NCHAR(4) NOT NULL DEFAULT ' ',STUDY_D DECIMAL(5,2) NOT NULL DEFAULT 0)を実行(実行ボタンをクリックします)します。
=CREATE_TABLE{?_WORK_TABLE?A}{STUDY_C,C,4,STUDY_N,N,4,STUDY_D,D,5,2};
☆I言語でテーブルを作るプログラムは、同じクライアントでも複数の画面を立ちあげて実行する事が出来ます、テーブルを作る事は当然同じ名前では作れないので、画面ごとにテーブル名を変える必要があります、その為テーブル名はシステム変数(システム変数はシステムから提供されている変数で、先頭がアンダーバー(_)です)を使って画面毎に別の名前に出来るようにしています、それが?_WORK_TABLE?で、テーブルが複数有る事を想定し最後に英字1文字を付加するルールとしています。
☆I言語の列名はシステム内でユニークである必要が有るので、個々のシステム毎にまとまるような単語を先頭に付加する事を推奨します、今回はSTUDY_を付けています。
☆I言語では?で囲まれた物は最初にその名前の内容で置き換わるルールと成っています。
☆CREATE_TABLEではI言語が使用する列が8個余分に作られます。何時,どこで、誰が、作成、修正、削除したがの履歴を記憶します。

◇メッセージに「コマンドは正常に完了しました。が出てテーブルが作られます。
◇「NOT NULL」を指定するとNULL(値が存在しない意味)値を作成する事が出来なく成ります、NULLが有ると予想外の動きのをする可能性が増えるので、「NOT NULL」を必ず設定する事を推奨します。
◇「DEFAULT 内容」を指定する事で、この列に何も作成しないSQLを書いても内容が自動で設定されエラーと成らないので、「DEFAULT 内容」を必ず設定する事を推奨します。
3.1.2◆CREATE TABLE TA(STUDY_C CHAR(4) NOT NULL DEFAULT ' ',STUDY_N NCHAR(4) NOT NULL DEFAULT ' ',STUDY_D DECIMAL(5,2) NOT NULL DEFAULT 0)を再度実行します。
◇メッセージに「メッセージ 2714、レベル 16、状態 6、行 1」「データベースに 'TA' という名前のオブジェクトが既に存在します。が出てエラーと成り既に作成されている事が分かります。
3.2 ALTER TABLEALTER TABLE テーブル名 ...
◇ALTERテーブルでは色々な事が出来ます、ここでは主キーとなるPRIMARY KEYの設定をしてみます。
3.2.1◆ALTER TABLE TA ADD CONSTRAINT TA0 PRIMARY KEY(STUDY_C,STUDY_N)を実行します。
=CREATE_INDEX{?_WORK_TABLE?A,0,,STUDY_C,STUDY_N};
☆CREATE_INDEXの「テーブル名,0,,」の「0」でPRIMARY KEYを設定出来る文法と成っています。
☆主キーの設定以外に外部キー(FOREIGN KEY)による、他のテーブルの制約キーが設定出来る機能が有りますが、I言語の削除は物理的に削除しない論理削除をする関係で、外部キー制約を設定しても削除データも作成できてしまう問題が有り、I言語では外部キーは設定しても意味が無いので、使わないで下さい。
=CREATE_TABLE{?_WORK_TABLE?A,STUDY_C,C,4,STUDY_N,N,4}{STUDY_D,D,5,2};
☆CREATE_TABLEでテーブル直後にPRIMARY KEY列を書けば、テーブル作成と当時にPRIMARY KEYを設定出来ます。

◇メッセージに「コマンドは正常に完了しました。が出てプライムキーが作成されました。
◇PRMARY KEYは普通のCREATE INDEXのインデクスとは異なり、NULLを作成でないので、NOT NULL指定の無い列は設定出来ないので、注意して下さい。
3.2.1◆ALTER TABLE TA ADD CONSTRAINT TA0 PRIMARY KEY(STUDY_C,STUDY_N)を再度実行します。
◇メッセージに「メッセージ 1779、レベル 16、状態 0、行 1」「テーブル 'TA' には、そのテーブルに定義された主キーが既に含まれています。「メッセージ 1750、レベル 16、状態 0、行 1」 「制約またはインデックスを作成できませんでした。」「以前のエラーを調べてください。」と出て、既にプライムキーが作成されている事が分かります。
3.3 DROP TABLEDROP TABLE テーブル名
3.3.1◆DROP TABLE TAを実行します。
BEGIN_END
☆BEGIN_END以降の命令は起動時と終了時の両方で実行されます。テーブルが何らかの異常で残ってしまっても問題が出ないように処理の最初で一旦削除し、更に処理の終了で必ず削除したいので「BEGIN_END」を最初に書き対応します。
NAME=DROP_TABLE_WORK"
☆NAME=で名前を付けた物をCOPY=でどこでも実行出来るように成っています、開始と終了以外でも実行出来るようにNAME=で名前を付けています。
REPEAT=?_A_A?
☆PEPEAT=で繰り返しの処理ができます、複数のテーブルを消す事を想定しREPEAT=を付けています。
☆?_A_A?は英字のAがアルファベットの何番目かの数値を返すシステム変数で?_A_A?は1と成ります。
=DROP_TABLE{?_WORK_TABLE??_A##?};
☆ここでテーブルを消しますが、テーブルが無くてもエラーと成らないで正常終了するように成っています。
☆?_A##?の##は特別な物でREPEAT=の中に書かれていると最初に繰り返しの回数で置き換えます、##が1に置き換えられ?_A1?と成ります、これは英字のアルファベットの1番目を表す意味で'A'と成り?_A2?であれば’B'と成ります。
REPEAT=
☆ここまで繰り返しが終了します。
NAME= (DROP_TABLE_WORK)
☆ここまでで名前の終わりと成ります。

◇メッセージに「コマンドは正常に完了しました。が出てテーブルが消されました。
3.3.2◆DROP TABLE TAを再度実行します。
◇メッセージに「メッセージ 3701、レベル 11、状態 5、行 1」「テーブル 'TA' を 削除 できません。存在しないか、権限がありません。と出てエラーと成りテーブルが既に削除されている事が分かります。
3.3.3◆CREATE TABLE TA(STUDY_C CHAR(4) NOT NULL DEFAULT ' ',STUDY_N NCHAR(4) NOT NULL DEFAULT ' ',STUDY_D DECIMAL(5,2) NOT NULL DEFAULT 0)を実行し再度テーブルを作ります。
3.4 INSERT(1/2)INSERT INTO テーブル名 [(列名[,...])] VALUES(内容[,...])[,(内容[,...]),...]
3.4.1◆INSERT INTO TA (STUDY_C,STUDY_N,STUDY_D) VALUES('ABCD','EF''H',123.35)を実行します。
=PROGRAM{2,?_WORK_TABLE?A,W2.STUDY_D=123.35}{WC.STUDY_C='ABCD',WN.STUDY_N='EF''H'}{};
☆SQLのINSERTの簡単な方法は「PROGRAM{2,」を使います、2が作成を意味します。
☆PROGRAMでは「項目名=内容」で内容も設定できます。
☆Wで始まる項目名は特別で事前に宣言しなくても即つかえます、2文字目に意味が有り,CがCHAR用,NがNCHAR用,数値が小数部の桁数を表現しています。
☆テーブルを更新する列名は最後の「.」以降の名前STUDY_D,STUDY_C,STUDY_Nと成ります。
=INSERT{?_WORK_TABLE?A,W2.STUDY_D=123.35,WC.STUDY_C='ABCD',WN.STUDY_N='EF''H'};
☆INERTで実行したい場合の書き方です。
=INSERT_FILE{?_WORK_TABLE?A,ファイル名,文字コード,STUDY_C,STUDY_N,STUDY_D};
☆ファイルからINSERTで作成する事も出来ます。

◇メッセージに「(1 行処理されました)と出てデータが作成されました。
◇ここでデータ型の説明をします、STUDY_CはCHAR(4)と有りますが、これは半角文字(英数字と特殊文字の7ビットアスキー文字)を4文字登録する為のデータ型です、一方NCHAR(4)は全角文字(日本語等,National Caracter)を4文字登録する為の文字ですが、実際にはどちらにも半角文字も全角文字も作成出来ます、ただし、全角の場合登録文字数が異なります。
◇SQLで文字列を書く場合は一重引用符で囲む必要が有ります、尚、一重引用符をデータとしたい場合は2個,連続して書くと一個の一重引用符と成ります、つまり、'EF''H'は内容が「EF'H」と成ります。
◇◇DECIMALは(5,2)は数値で有効桁数5桁で小数部2桁の意味が有ります、SQLに数値を書く場合は一重引用符は不要です。
◇データ型は他にも沢山ありますが、CHARとNCHARとDECIMALが有れば事務処理系のシステム作りには支障が無いので、必要になった時点で勉強いて下さい、特に日を扱うDATE型は、RDBMS毎に大きく動きが異なり、予想の出来ない動きをする場合が有るので、注意が必要です。
3.4.2INSERT INTO TA (STUDY_C) VALUES('日本')を実行します。
◇メッセージに「(1 行処理されました)と出てデータが作成されました。
3.4.3◆INSERT INTO TA (STUDY_N) VALUES('日本')を実行します。
◇メッセージに「(1 行処理されました)と出てデータが作成されました。
3.4.4◆INSERT INTO TA (STUDY_C) VALUES('日本語')を実行します。
◇メッセージに「メッセージ 8152、レベル 16、状態 14、行 1」「文字列データまたはバイナリ データが切り捨てられます。「ステートメントは終了されました。」と出て作成できません。
◇CHAR(4)は全角1文字でCHARを2文字使ってしまうので、6文字分必要で作成出来ません。
3.4.5◆INSERT INTO TA (STUDY_N) VALUES('日本語')を実行します。
◇メッセージに「(1 行処理されました)と出てデータが作成されました。NCHAR(4)ですので全角文字4文字まで作成できます。
◇このように全角文字はCHARとNCHARでは文字数が異なるので注意が必要です。
☆I言語ではCHARには全角文字は使えないルールと成っています。
☆I言語ではNCHARには全角文字が使えますが、CHARと同じ様に全角は2文字とし計算するルールと成っています。(これは画面表示が、全角1文字で半角2文字分を必要とする為、表示する時の文字数を考慮してのルールです)

3.4.6◆INSERT INTO TA (STUDY_D) VALUES(1234.56)を実行します。
◇メッセージに「メッセージ 8115、レベル 16、状態 8、行 1」「numeric をデータ型 numeric に変換中に、算術オーバーフロー エラーが発生しました。「ステートメントは終了されました。」と成り作成できません。
◇有効桁数5桁で内2桁が小数部ですので、整数部は3桁以内の必要がありますが、4桁有る為作成できないでエラーと成ります。
☆このようにリレーショナルデータベースでは文字の桁数や数値の有効桁数以上のデータを作成しようとするとエラーとなってしまいます。データベースは効率良く記憶し、効率良く検索出来るようにする為このようになっているので、仕方のない事ですが、今までのプログラミング言語は桁数もプログラム内に書いて対応していた物が多く、簡単には変更出来ない問題がありました。I言語では列情報を列名単位にデータディクショナリに持ってプログラム側はデータディクショナリとテーブル情報から桁数も含めて列の設定情報をもらい、プログラムには列名を持てば良いようにして、列情報の変更が起きてもプログラムの修正をしなくても良いようにし、容易に列情報の変更が出来るように成っています。

3.4.7◆INSERT INTO TA (STUDY_D) VALUES(123.356)を実行します。
◇メッセージに「(1 行処理されました)と出てデータが作成されました。
◇小数部の桁数が多い場合は該当位置で四捨五入が行われて123.36として登録されるようになっています。

3.5 INSERT(2/2)INSERT INTO テーブル名 [(列名[,...])] SELECT 式[,...] FROM テーブル名 [...]
◇insertには別の書き方も有ります。
3.5.1◆INSERT INTO TA (STUDY_C,STUDY_N,STUDY_D) SELECT STUDY_C,STUDY_N,STUDY_D FROM TAを実行します。
◇メッセージに「(5 行処理されました)と出て、今まで作成した行数分の同じ物が作成されました。
◇SELECT以下は検索のSQL文と同じ物です。
3.6 UPDATE(1/2)UPDATE テーブル名 SET 列名=内容[,...] [WHERE 条件]です。
3.6.2◆UPDATE TA SET STUDY_D=999.99 WHERE STUDY_C='WXYZ'を実行します。
◇メッセージに「(0 行処理されました)と出て何も処理しないで、エラーにもなりませんでした、これは条件が「STUDY_C='WXYZ'」でSTUDY_Cが'WXYZ'の物が1件も存在しない為です。
◇何も修正する対象が無くても、正常終了と成るので、プログラムを作る場合に注意が必要です。
3.6.3◆UPDATE TA SET STUDY_D=999.99 WHERE STUDY_C='ABCD'を実行します。
=PROGRAM{3P,?_WORK_TABLE?A,W2.STUDY_D=999.99}{WC.STUDY_C='ABCD'}{};
☆3が修正ですが、PROGRAMは通常1件処理が基本です、2件以上ある事が想定される場合はP(plural)を付加すればエラーになりません。

◇メッセージに「(2 行処理されました)と出て2件の行が処理されました。
◇SQLでは条件に合う物の全ての行が対象に成るので、2件が同時に修正出来ます。

3.7 UPDATE(2/2)UPDATE 別名1 SET 列名=内容[,...] FROM テーブル名1 別名1,テーブル名2 別名2 WHERE 結合条件等です。
◇修正は別のテーブルのデータを使って行う事もできます。
◇この書き方はSQL Serveのみで可能で、他のRDBMSでは書き方が異なるので注意して下さい。
3.7.1◆CREATE TABLE TB(STUDY_C CHAR(4) NOT NULL DEFAULT ' ',STUDY_N NCHAR(4) NOT NULL DEFAULT ' ',STUDY_D DECIMAL(5,2) NOT NULL DEFAULT 0)で別テーブルを作ります。
=COPY_TABLE{?_WORK_TABLE?B,?_WORK_TABLE?A,NOT};
☆全く同じ構造のテーブルを作る場合はNOT付きのCOPY_TABLEで作る事も出来ます。

3.7.2◆INSERT INTO TA (STUDY_C,STUDY_N,STUDY_D) VALUES('A','B',1)で元テーブルにデータを作成します。
3.7.3◆INSERT INTO TB (STUDY_C,STUDY_N,STUDY_D) VALUES('A','B',9)で別テーブルにデータを作成します。
3.7.4◆UPDATE O SET STUDY_D=I.STUDY_D FROM TA O,TB I WHERE O.STUDY_C=I.STUDY_C AND O.STUDY_N=I.STUDY_N AND O.STUDY_D!=I.STUDY_Dを実行します。
=UPDATE{?_WORK_TABLE?A,STUDY_D}{I.STUDY_D}{?_WORK_TABLE?B I WHERE O.STUDY_C=I.STUDY_C AND O.STUDY_N=I.STUDY_N AND O.Z_CANCEL=' ' AND I.Z_CANCEL=' '};
☆I言語ではRDBMSが異なっても同じ書き方で対応出来る文法に成っています。

◇メッセージに「(1 行処理されました)と出てデータが修正されました。
◇複数の条件を設定する場合、ANDで両者の条件、ORでどちらかの条件で成立します、ANDとORが混在している場合はANDを先に判定します、ORを先に判定したい場合はカッコ「()」で括ります、またNOTで否定条件とする事も出来ます。
3.7.5◆UPDATE O SET STUDY_D=I.STUDY_D FROM TA O,TB I WHERE O.STUDY_C=I.STUDY_C AND O.STUDY_N=I.STUDY_N AND O.STUDY_D!=I.STUDY_Dを実行します。
◇メッセージに「(0 行処理されました)と出てデータが修正されませんでした、
◇既に修正されており「O.STUDY_D!=I.STUDY_D」成り立たない為に、処理されなかった事が分かります。
3.8 DELETEDELETE FROM テーブル名 [WHERE 条件]
3.8.1◆DELETE FROM TA WHERE STUDY_C='ABCD'を実行します。
=PROGRAM{1P,?_WORK_TABLE?A}{WC.STUDY_C='ABCD'}{};
☆1が削除ですが、PROGRAMは通常1件処理が基本です、2件以上ある事が想定される場合はP(plural)を付加すればエラーになりません
☆削除と言ってもDELETEでは無くUPDATEによる論理削除ですのでSQLは同じでは有りません。

◇メッセージに「(2 行処理されました)と出て2件の行が処理されました。
3.8.2◆DELETE FROM TA WHERE STUDY_C='ABCD'を再度実行します。
◇メッセージに「(0 行処理されました)と出て既に削除されているので何も処理されないで、正常終了します。
◇処理対象が無くてもエラーとはならないので、プログラムではUPDATE同様に処理件数の確認が必要です。
3.9 CREATE INDEXCREATE [UNIQUE] INDEX インデックス名 ON テーブル名(列名[,...])
3.9.1◆CREATE INDEX TA1 ON TA(STUDY_C,STUDY_N)を実行します。
=CREATE_INDEX{?_WORK_TABLE?A,1,,STUDY_C,STUDY_N};
☆CREATE_INDEXの「テーブル名,1,,」の「1」で普通のインデックス(PPRIMARY KEYでは無い)を設定出来ます。

◇メッセージに「コマンドは正常に完了しました。と出てインデックスが作成されました。
3.9.2◆CREATE UNIQUE INDEX TA2 ON TA(STUDY_C,STUDY_N)を実行します。
=CREATE_INDEX{?_WORK_TABLE?A,2,UNIQUE,STUDY_C,STUDY_N};
☆インデックスは1から9までの9個まで作れます。
☆UNIQUEを付けると重複を認めない設定と成ります。

◇メッセージに「メッセージ 1505、レベル 16、状態 1、行 1」「オブジェクト名 'dbo.TA' およびインデックス名 'TA2' に重複したキーが見つかったので、CREATE UNIQUE INDEX ステートメントは終了しました。重複したキーの値は (...)です。 」「ステートメントは終了されました。」と出てインデックスが作成出来ませんでした。
◇「UNIQUE」で重複を認めない設定にしましたが、既に重複データが存在する為に作れなかった訳です。
◇メッセージに「オブジェクト名 'dbo.TA'」と有りますが、「dbo.」はスキーマ名です、テーブルには必ずスキーマ名が付いていますが、SQL Serverの場合デフォルト値(スキーマと指定しない時の省略値、ログインしたユーザーID毎にデフォルト値が設定されています)がdboとなっています、一応スキーマ名が付いている事だけは記憶にとどめて下さい。
◇尚、スキーマ名の上位には更にデータベース名が有ります、現在は「master」のデータベース名を使っているので、テーブル名はデータベース名.スキーマ名.テーブル名で「master.dbo.TA」がフルネームとなっています。
3.9.3◆DELETE FROM TAで一旦全てのデータを削除をします。
◇メッセージに「(8 行処理されました)と出て8行全てが消されました、
◇WHEREの条件を指定しない場合は全てのデータが削除されます。
3.9.4◆CREATE UNIQUE INDEX TA2 ON TA(STUDY_C,STUDY_N)を実行します。
◇メッセージに「コマンドは正常に完了しました。と出て今度は成功しました。
3.9.5◆INSERT INTO TA (STUDY_C,STUDY_N,STUDY_D) VALUES('A','B',1),('A','B',2)で試しに重複するデータを作成してみます。
◇メッセージに「メッセージ 2601、レベル 14、状態 1、行 1」「一意インデックス 'TA2' を含むオブジェクト 'dbo.TA' には重複するキー行を挿入できません。重複するキーの値は (A , B ) です「ステートメントは終了されました。」と出ました。
◇重複キーが有るとエラーと成り重複作成出来ない事が分かります。
3.10 DROP INDEXDROP INDEX インデックス名 ON テーブル名
3.10.1 ◆DROP INDEX TA2 ON TAを実行します。
=DROP_INDEX{?_WORK_TABLE?A,2};

◇メッセージに「コマンドは正常に完了しました。と出てインデックスが削除されました。
All Rights Reserved, Copyright (C) 2017-2017 Nobumichi Harasawa.