本文へスキップ
Typle
ログイン状態を確認中

プログラミング · 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で無条件に握りつぶさない)

ほかの公式パックを見る