第4章 リレーショナルデータベース言語SQL 4.1 4.2 4.3 4.4 4.5 4.6 背景と基本概念 データ定義 アクセス権限 問合せ データ更新 アプリケーションからのデータ操作 4.6 アプリケーションからのデータ操作 ■ホスト言語方式 アプリケーションプログラムの中から使用 する方法。標準的には、埋込みSQLが用いら れる(他の方法もある)。 ■埋込みSQL SQL文そのものの意味は直接起動と同等。 1. ホスト言語方式の課題 (a)ホスト言語中のSQL記述の明確化 (b)SQLとアプリケーションとのデータ受け渡し (c)SQLの実行時エラー通知 (a) ホスト言語中のSQL記述の明確化 SQL記述はホスト言語の文法にはないので、 構文エラーになる。 A.プリプロセッサで記述 を分離して、関数呼び 出しを生成 (C言語でのSQL) EXEC SQL SQL記述; B.特殊な関数を作成する (Microsoft Access) システムごとに 記述が異なりがち (b) SQLからアプリへのデータ受け渡し マルチ集合に対応するデータ型が 通常のホスト言語にない。 カーソルの概念の導入 カーソルが表内の1行を指す (c) SQL実行時エラーの通知 プログラムではエラー時処理を含めて 記述する必要がある。 SQLSTATE :実行状態(5桁の文字コード) 例:00000 正常終了、01005 警告、02000 データなし これ以外はエラー SQLCODE:エラーコード(0~-65535) 例 0:正常,100:データなし, これ以外はエラーコード 2. カーソル アクセスの手順 (a)カーソルの定義 (b)カーソルのオープン (c)1行の処理(繰り返し) (d)カーソルのクローズ (a) カーソルの定義 【書き方】(カーソル宣言) DECLARE カーソル名 CURSOR FOR 問合せ式 カーソルの識別のみ。 問合せ自体は、カーソルのオープンで実行。 (b) カーソルのオープン 【書き方】 OPEN カーソル名 ①カーソル名で識別された問合せ式の実行。 ②問合せ式実行で得られた導出表を作業表という。 ③オープン直後カーソルは先頭行に位置づけられる。 ④ORDER BY句が指定されていないとき処理系の定義 による順序となる(順序不定)。 (c) 1行処理 (1)1行取出し(FETCH) 【書き方】 FETCH [[<取出し方向>] FROM ]カーソル名 INTO パラメータ名 [[INDICATOR 指標パラメータ名] [,パラメータ名 [[INDICATOR 指標パラメータ名]・・・] <取出し方向>で指定される1行の各列の値がINTO句で指定され る各パラメータに代入される。省略したらNEXT。 行が存在しなければ、SQLSTATEにデータが存在しないことが 報告される。 取出し方向 ① NEXT : カーソルを次の行に移動して、その行を取 り出す。 ② PRIOR : 現在位置の1つ前の行を取り出す。 ③ FIRST : 現在位置に関係なく最初の行。 ④ LAST : 現在位置に関係なく最後の行。 ⑤ ABSOLUTE n : 現在位置に関係なく n 番目の行。 ⑥ RELATIVE n : 現在位置から相対的に n 番目の行。n が負 の場合、前方に数える。 パラメータ名 ① プログラム内のデータ領域名を使う。 ② 作業表の列数と同じ数でなければならない。 ③ 列の順番とパラメータの順番は一致していなければならな い。 ④ パラメータが空値である可能性がある場合、INDICATOR 指 標パラメータを指定しなければならない。 INDICATOR指標パラメータ名 ① プログラム内のデータ領域名を使う。 ② 空値のとき"-1"、空値でなければ"0"が設定される。 (2)1行の変更(UPDATE) 【書き方】 UPDATE 表名 SET 列名 = 値式, [列名 = 値式, ・・・] WHERE CURRENT OF カーソル名 ① 表名はカーソル定義中の問合せ指定の FROM 句で指定され ている表名と同じでなければならない。 ② 値式として関数を指定することはできない。 ③ 値式の代わりにNULLを指定することができる。 ④ 更新されるのは作業表のポインタの現在位置に対応する行 であり、そのような行がなければこの文は無効(更新され るのは、表の対応する行であり作業表ではない)。 ⑤ 参照するカーソルは読込み専用であってはならない。 読込み専用のカーソルとは ① ORDER BY 句を含む ② 列名以外を含む値式を含む。 ③ 列名が重複している。 ④ FROM句に2つ以上の表を含む。 ⑤ WHERE句が副問合せを含む。 ⑥ GROUP BY句を含む。 (3)1行の削除(DELETE) 【書き方】 DELETE FROM 表名 WHERE CURRENT OF カーソル名 ① 表名はカーソル定義中の問合せ指定の FROM 句で指定され ている表名と同じでなければならない。 ② 削除されるのは作業表のポインタの現在位置に対応する行 であり、そのような行がなければこの文は無効(削除され るのは、表の対応する行であり作業表ではない)。 ③ 参照するカーソルは読込み専用であってはならない。 (前シート参照) (4)カーソルのクロース(CLOSE) 【書き方】 CLOSE カーソル名 この指定で作業表が閉じられる。 【例1】年収が多い順 (以下、擬似コード) DECLARE 年収順社員作業表 CURSOR FOR SELECT * FROM 社員 ORDER BY 年収 DESC OPEN 年収順社員作業表 repeat FETCH 年収順社員作業表 INTO cid, name, incom, sid INDICATER i-sid Print cid, name,incom, sid until (SQLSTATE<>"00000") CLOSE 年収順社員作業表 DECLARE (以下、擬似コード) DECLARE 年収順社員作業表 CURSOR FOR SELECT * FROM 社員 ORDER BY 年収 DESC OPEN 年収順社員作業表 repeat FETCH 年収順社員作業表 INTO cid, name, incom, sid INDICATER i-sid Print cid, name, incom, sid until (SQLSTATE<>"00000") CLOSE 年収順社員作業表 社員 (年収順社員作業表はこの時点で は作成されない) 社員ID 氏名 年収 課ID 1001 浅田克郎 800 D 1002 佐藤史郎 600 D 1003 田中吉彦 900 S 1004 中原圭吾 800 S 1005 羽田康子 700 S 1006 山田悦子 500 NULL OPEN (以下、擬似コード) 社員 DECLARE 年収順社員作業表 CURSOR FOR SELECT * FROM 社員 ORDER BY 年収 DESC OPEN 年収順社員作業表 repeat FETCH 年収順社員作業表 INTO cid, name, incom, sid INDICATER i-sid Print cid, name, incom, sid until (SQLSTATE<>"00000") CLOSE 年収順社員作業表 社員ID 氏名 年収 課ID 1001 浅田克郎 800 D 1002 佐藤史郎 600 D 1003 田中吉彦 900 S 1004 中原圭吾 800 S 1005 羽田康子 700 S 1006 山田悦子 500 NULL 年収順社員作業表 社員ID 氏名 年収 課ID 1003 田中吉彦 900 S 1001 浅田克郎 800 D 1004 中原圭吾 800 S 1005 羽田康子 700 S 1002 佐藤史郎 600 D 1006 山田悦子 500 NULL (以下、擬似コード) DECLARE 年収順社員作業表 CURSOR FOR SELECT * FROM 社員 ORDER BY 年収 DESC OPEN 年収順社員作業表 repeat FETCH 年収順社員作業表 INTO cid, name, incom, sid INDICATER i-sid Print cid, name, incom, sid until (SQLSTATE<>"00000") CLOSE 年収順社員作業表 FETCH PRINT 年収順社員作業表 社員ID 氏名 年収 課ID 1003 田中吉彦 900 S 1001 浅田克郎 800 D 1004 中原圭吾 800 S 1005 羽田康子 700 S 1002 佐藤史郎 600 D 1006 山田悦子 500 NULL (以下、擬似コード) Print Print 1003,田中吉彦,900,D DECLARE 年収順社員作業表 CURSOR FOR SELECT * FROM 社員 ORDER BY 年収 DESC OPEN 年収順社員作業表 repeat FETCH 年収順社員作業表 INTO cid, name, incom, sid INDICATER i-sid Print cid, name, incom, sid until (SQLSTATE<>"00000") CLOSE 年収順社員作業表 年収順社員作業表 社員ID 氏名 年収 課ID 1003 田中吉彦 900 D 1001 浅田克郎 800 D 1004 中原圭吾 800 S 1005 羽田康子 700 S 1002 佐藤史郎 600 D 1006 山田悦子 500 NULL (以下、擬似コード) Print Print 1003,田中吉彦,900,D DECLARE 年収順社員作業表 CURSOR FOR SELECT * FROM 社員 ORDER BY 年収 DESC OPEN 年収順社員作業表 repeat FETCH 年収順社員作業表 INTO cid, name, incom, sid INDICATER i-sid Print cid, name, incom, sid until (SQLSTATE<>"00000") CLOSE 年収順社員作業表 年収順社員作業表 偽 社員ID 氏名 年収 課ID 1003 田中吉彦 900 D 1001 浅田克郎 800 D 1004 中原圭吾 800 S 1005 羽田康子 700 S 1002 佐藤史郎 600 D 1006 山田悦子 500 NULL (以下、擬似コード) DECLARE 年収順社員作業表 CURSOR FOR SELECT * FROM 社員 ORDER BY 年収 DESC OPEN 年収順社員作業表 repeat FETCH 年収順社員作業表 INTO cid, name, incom, sid INDICATER i-sid Print cid, name, incom, sid until (SQLSTATE<>"00000") CLOSE 年収順社員作業表 FETCH PRINT 1003, 田中吉彦, 900, D 1001, 浅田克郎, 800, D 年収順社員作業表 社員ID 氏名 年収 課ID 1003 田中吉彦 900 S 1001 浅田克郎 800 D 1004 中原圭吾 800 S 1005 羽田康子 700 S 1002 佐藤史郎 600 D 1006 山田悦子 500 NULL (以下、擬似コード) DECLARE 年収順社員作業表 CURSOR FOR SELECT * FROM 社員 ORDER BY 年収 DESC OPEN 年収順社員作業表 repeat FETCH 年収順社員作業表 INTO cid, name, incom, sid INDICATER i-sid Print cid, name, incom, sid until (SQLSTATE<>"00000") CLOSE 年収順社員作業表 Print Print 1003, 田中吉彦, 900, D 1001, 浅田克郎, 800,D 年収順社員作業表 社員ID 氏名 年収 課ID 1003 田中吉彦 900 D 1001 浅田克郎 800 D 1004 中原圭吾 800 S 1005 羽田康子 700 S 1002 佐藤史郎 600 D 1006 山田悦子 500 NULL (以下、擬似コード) DECLARE 年収順社員作業表 CURSOR FOR SELECT * FROM 社員 ORDER BY 年収 DESC OPEN 年収順社員作業表 repeat FETCH 年収順社員作業表 INTO cid, name, incom, sid INDICATER i-sid Print cid, name, incom, sid until (SQLSTATE<>"00000") CLOSE 年収順社員作業表 (以下省略) Print Print 1003, 田中吉彦, 900, D 1001, 浅田克郎, 800,D 年収順社員作業表 偽 社員ID 氏名 年収 課ID 1003 田中吉彦 900 D 1001 浅田克郎 800 D 1004 中原圭吾 800 S 1005 羽田康子 700 S 1002 佐藤史郎 600 D 1006 山田悦子 500 NULL 【例2】年収900万を削除、他、年収1割アップ (以下、擬似コード) DECLARE 社員作業表 CURSOR FOR SELECT * FROM 社員 OPEN 社員作業表 repeat FETCH 社員作業表 INTO cid, name, incom, sid INDICATER i-sid if(incom>=900) then DELETE FROM 社員 WHERE CURRENT OF 社員作業表 else UPDATE 社員 SET 年収=年収*1.1 WHERE CURRENT OF 社員作業表 end if until (SQLSTATE<>"00000") CLOSE 社員作業表 C言語組込みSQLの例 main() { EXEC SQL BEGIN DECLARE SECTION; char SQLSTATE[6]; /* SQL実行結果 */ int incom ; /* 年収 */ EXEC SQL emp_Cur CURSOR FOR SELECT 年収 FROM 社員; EXEC SQL OPEN emp_Cur; EXEC SQL FETCH emp_Cur INTO cid, name, incom, sid INDICATER i-sid; while(strcmp(SQLSTATE,"00000")){ if(incom>=900) EXEC SQL DELETE FROM 社員 WHERE CURRENT OF emp_CUR; else EXEC SQL UPDATE 社員 SET 年収=年収*1.1 WHERE CURRENT OF emp_CUR; EXEC SQL FETCH emp_Cur INTO cid, name, incom, sid INDICATER i-sid; } CLOSE emp_Cur; }
© Copyright 2025 ExpyDoc