プログラミング · Oracle · PL/SQL · SQL
Oracle PL/SQL構文のタイピング練習
Oracle PL/SQL(19c 以降)の構文37個を、初級・中級・上級の3つのリストで打って覚えます。SET SERVEROUTPUT ON、DECLARE・BEGIN・END の匿名ブロック、DBMS_OUTPUT.PUT_LINE、変数と定数などを練習できます。
3リスト・37語
無料・ログインなしで練習できます。押すとこのパックをフォローし、すぐに練習が始まります。
収録している言葉
Oracle PL/SQL構文(初級)
| 打つ言葉 | 意味・補足 |
|---|---|
| -- SQL/PLはOracleのPL/SQLとして整理 | Oracle PL/SQL:対象・用語(Db2 SQL PL・PostgreSQL PL/pgSQLとは別。Oracle 19c以降の主要構文を中心に記載) |
| SET SERVEROUTPUT ON | 出力を有効化(SQL*Plus等のクライアントコマンド。PL/SQL構文ではない) |
| DECLARE v_name users.name%TYPE; BEGIN NULL; END; | %TYPE:列等から型を継承(users表・name列が必要。制約・既定値をすべて継承するわけではない) |
| DECLARE v_user users%ROWTYPE; BEGIN SELECT * INTO v_user FROM users WHERE id = 1; END; | %ROWTYPE:行構造を変数化(users表が必要。SELECT INTOは正確に1行が必要) |
| DECLARE i PLS_INTEGER := 0; BEGIN LOOP i := i + 1; EXIT WHEN i >= 3; END LOOP; END; | LOOP / EXIT WHEN:無限ループから脱出 |
| DECLARE i PLS_INTEGER := 0; BEGIN WHILE i < 3 LOOP i := i + 1; END LOOP; END; | WHILE LOOP:条件反復 |
| BEGIN FOR i IN REVERSE 1..3 LOOP DBMS_OUTPUT.PUT_LINE(i); END LOOP; END; | FOR / REVERSE:整数範囲の反復(両端を含む。制御変数は暗黙宣言) |
| BEGIN DELETE FROM users WHERE id = 1; END; | DELETE:削除(実データ削除。COMMITまたはROLLBACKを判断) |
| BEGIN RAISE NO_DATA_FOUND; EXCEPTION WHEN NO_DATA_FOUND THEN RAISE; END; | RAISE:例外を再送出(意図的に例外が伝播) |
| BEGIN RAISE_APPLICATION_ERROR(-20001, '不正な入力'); END; | RAISE_APPLICATION_ERROR:アプリ用エラー(通常-20000〜-20999) |
| DECLARE v_result NUMBER; BEGIN double_value(p_in => 2, p_out => v_result); END; | 名前付き呼出:引数名で指定(double_valueが定義済み) |
| CREATE OR REPLACE PACKAGE math_api AS FUNCTION twice(n NUMBER) RETURN NUMBER; END; | PACKAGE / PACKAGE BODY:宣言と実装を分離(呼出はmath_api.twice(2)等) |
| SELECT name, type, line, position, text FROM user_errors ORDER BY name, sequence; | USER_ERRORS:コンパイルエラー確認(SQL。SHOW ERRORSはクライアントコマンド) |
Oracle PL/SQL構文(中級)
| 打つ言葉 | 意味・補足 |
|---|---|
| DECLARE v_name VARCHAR2(100) := 'Pomo'; BEGIN DBMS_OUTPUT.PUT_LINE(v_name); END; | DECLARE BEGIN END:匿名ブロック(/はSQL*Plus・SQLcl等の実行区切り。API送信時は通常付けない) |
| BEGIN IF 2 > 1 THEN DBMS_OUTPUT.PUT_LINE('yes'); ELSIF 2 = 1 THEN NULL; ELSE NULL; END IF; END; | IF ELSIF ELSE:条件分岐 |
| BEGIN FOR i IN 1..3 LOOP CONTINUE WHEN i = 2; DBMS_OUTPUT.PUT_LINE(i); END LOOP; END; | CONTINUE:次の反復へ |
| BEGIN UPDATE users SET name = 'New' WHERE id = 1; DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT); END; | UPDATE / SQL%ROWCOUNT:更新件数(直前の対応SQLの件数。WHEREなしは全行) |
| BEGIN FOR r IN ( SELECT id, name FROM users ORDER BY id ) LOOP DBMS_OUTPUT.PUT_LINE(r.name); END LOOP; END; | カーソルFORループ:行を順に処理(OPEN・FETCH・CLOSEを自動管理) |
| DECLARE TYPE user_rec IS RECORD(id NUMBER, name VARCHAR2(100)); r user_rec; BEGIN r.id := 1; r.name := 'Pomo'; END; | RECORD:複合値 |
| CREATE OR REPLACE PROCEDURE double_value(p_in IN NUMBER, p_out OUT NUMBER) AS BEGIN p_out := p_in * 2; END; | PROCEDURE / IN OUT:手続きを定義(スキーマへの定義権限が必要) |
| CREATE OR REPLACE FUNCTION add_one(p_n IN NUMBER) RETURN NUMBER AS BEGIN RETURN p_n + 1; END; | FUNCTION / RETURN:戻り値を返す |
| CREATE OR REPLACE PACKAGE BODY math_api AS FUNCTION twice(n NUMBER) RETURN NUMBER IS BEGIN RETURN n * 2; END; END; | PACKAGE / PACKAGE BODY:宣言と実装を分離(呼出はmath_api.twice(2)等) |
| DECLARE v_name VARCHAR2(100); BEGIN EXECUTE IMMEDIATE 'SELECT name FROM users WHERE id=:id' INTO v_name USING 1; END; | EXECUTE IMMEDIATE / USING:パラメーター付き動的SQL(値をバインド。識別子の未検証連結を避ける) |
| BEGIN SAVEPOINT before_change; UPDATE users SET name = 'New' WHERE id = 1; ROLLBACK TO before_change; END; | COMMIT / ROLLBACK / SAVEPOINT:確定・取消・復帰地点(例は更新を戻す。DDLは暗黙COMMITが生じるため別扱い) |
| DECLARE v_id users.id%TYPE; BEGIN SELECT id INTO v_id FROM users WHERE id = 1 FOR UPDATE; END; | SELECT FOR UPDATE:行をロック(ブロック終了だけでは取引終了しない。COMMIT/ROLLBACKまで保持) |
Oracle PL/SQL構文(上級)
| 打つ言葉 | 意味・補足 |
|---|---|
| DECLARE v_age PLS_INTEGER := 20; c_limit CONSTANT PLS_INTEGER := 100; BEGIN v_age := 21; DBMS_OUTPUT.PUT_LINE(v_age); END; | := / CONSTANT:変数・定数(ローカル変数の既定値は通常NULL) |
| DECLARE v_amount NUMBER(12, 2) := 123.45; v_ok BOOLEAN := TRUE; BEGIN IF v_ok THEN DBMS_OUTPUT.PUT_LINE(v_amount); END IF; END; | NUMBER / VARCHAR2 / DATE / BOOLEAN:主な型(19cのBOOLEANはPL/SQL内。SQL列へのBOOLEAN対応は新しい版と区別) |
| DECLARE v_role VARCHAR2(20) := 'admin'; BEGIN CASE v_role WHEN 'admin' THEN DBMS_OUTPUT.PUT_LINE('管理者'); ELSE DBMS_OUTPUT.PUT_LINE('その他'); END CASE; END; | CASE:値による分岐(文と式のCASEを区別) |
| DECLARE v_name VARCHAR2(100); BEGIN SELECT name INTO v_name FROM users WHERE id = 1; DBMS_OUTPUT.PUT_LINE(v_name); END; | SELECT INTO:1行を変数へ取得(users表が必要。0行・複数行で例外) |
| DECLARE v_id NUMBER; BEGIN INSERT INTO users(name) VALUES('Pomo') RETURNING id INTO v_id; DBMS_OUTPUT.PUT_LINE(v_id); END; | INSERT / RETURNING INTO:追加値を受け取る(users.idの採番等を準備。自動COMMITしない) |
| DECLARE CURSOR c_users IS SELECT name FROM users; BEGIN FOR r IN c_users LOOP DBMS_OUTPUT.PUT_LINE(r.name); END LOOP; END; | 明示カーソル:カーソルを宣言 |
| DECLARE CURSOR c IS SELECT name FROM users; v_name users.name%TYPE; BEGIN OPEN c; LOOP FETCH c INTO v_name; EXIT WHEN c%NOTFOUND; DBMS_OUTPUT.PUT_LINE(v_name); END LOOP; CLOSE c; END; | OPEN FETCH CLOSE:明示的に行取得(実運用では例外時の解放も考慮) |
| DECLARE TYPE names_t IS TABLE OF VARCHAR2(100) INDEX BY PLS_INTEGER; names names_t; BEGIN names(1) := 'Pomo'; DBMS_OUTPUT.PUT_LINE(names.COUNT); END; | 連想配列:キー付き配列(添字が密に連続するとは限らない) |
| DECLARE TYPE ids_t IS TABLE OF users.id%TYPE; ids ids_t; BEGIN SELECT id BULK COLLECT INTO ids FROM users; DBMS_OUTPUT.PUT_LINE(ids.COUNT); END; | BULK COLLECT:複数行を一括取得(大量取得はメモリ消費。FETCH BULK COLLECT LIMIT等も検討) |
| DECLARE TYPE ids_t IS TABLE OF NUMBER; ids ids_t := ids_t(1, 2, 3); BEGIN FORALL i IN 1..ids.COUNT UPDATE users SET name = 'New' WHERE id = ids(i); END; | FORALL:DMLをまとめて送る(通常のFORループとは別。実データ変更) |
| DECLARE v_name users.name%TYPE; BEGIN SELECT name INTO v_name FROM users WHERE id = 1; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('なし'); WHEN TOO_MANY_ROWS THEN RAISE; END; | EXCEPTION / NO_DATA_FOUND:例外処理 |
| BEGIN RAISE NO_DATA_FOUND; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLCODE || ':' || SQLERRM); RAISE; END; | SQLCODE / SQLERRM:例外情報(WHEN OTHERSで無条件に握りつぶさない) |