【PL/SQL】基本構文完全ガイド|4セクション・ブロック7種類・セミコロンとスラッシュ・DBMS_OUTPUT設定・学習ロードマップ

【PL/SQL】初心者でもわかる基本構文とブロック構造の書き方 PL/SQL

PL/SQLはProcedural Language/SQLの略で、OracleがSQLに手続き型プログラミング(変数・制御文・例外処理・サブルーチン)を加えたOracle専用のプログラミング言語です。学習の最初に必ず出会うのが「DECLARE/BEGIN/EXCEPTION/END」の4セクション構造ですが、入門書の多くはこの基本形を示して「詳しくは次章」で終わってしまいます。

実務でPL/SQLを書き始めると、セミコロン(;)とスラッシュ(/)の使い分け、DBMS_OUTPUTが表示されない原因、無名ブロックとストアドプロシージャの違い、ブロックの7種類(匿名/プロシージャ/ファンクション/パッケージ/トリガー/型メソッド等)、USER_ERRORSでコンパイル失敗を追跡する方法など、入門書では扱われない実用知識が次々必要になります。

この記事では、PL/SQLの基本構文を初心者向けの丁寧さと実務レベルの深さで両立させます。4セクション詳解、7種類のブロック形態、セミコロン/スラッシュ使い分け、DBMS_OUTPUTの設定、コメント2種類、コンパイルエラー(PLS-00103等)の読み方、ラベル・ネストブロック、変数・代入、学習ロードマップまで、ゼロから始めてPL/SQL開発の現場に立てるレベルに引き上げる2026年版の決定版です。関連は【PL/SQL】IF文完全ガイド【PL/SQL】例外処理完全ガイド【PL/SQL】ループ処理完全ガイド【PL/SQL】変数・定数完全ガイドも順次ご参照ください。

この記事で学べること

  • PL/SQLと通常SQLの決定的な違い
  • PL/SQLブロックの4セクション(DECLARE/BEGIN/EXCEPTION/END)完全解説
  • ブロック7種類:匿名/プロシージャ/ファンクション/パッケージ/トリガー/型メソッド等
  • セミコロン(;)とスラッシュ(/の使い分け
  • DBMS_OUTPUT.PUT_LINEが表示されない時のSERVEROUTPUT設定
  • コメント2種類(--/* */)とドキュメントコメント
  • コンパイルエラー(PLS-00103/PLS-00201等)の読み方とUSER_ERRORSビュー
  • 無名ブロック vs 名前付きブロック(ストアドプロシージャ/ファンクション)の比較
  • ラベル付きブロック(<<label>>)とネストの基本
  • 変数・代入(:=)・NULL 初期値の基礎
  • 実行環境別の使い方(SQL*Plus/SQLcl/SQL Developer/VS Code Database Client
  • PL/SQL学習ロードマップ(16ステップ
スポンサーリンク

30秒で分かるPL/SQLブロックの基本

最小構成とフル構成
-- ① 最小:BEGIN ~ END;だけでも動く
BEGIN
  DBMS_OUTPUT.PUT_LINE('Hello PL/SQL');
END;
/

-- ② フル構成:4セクション
DECLARE
  v_name  VARCHAR2(50);    -- 変数宣言
  v_count NUMBER := 0;      -- 初期値付き
BEGIN
  v_name := 'PL/SQL';
  v_count := v_count + 1;
  DBMS_OUTPUT.PUT_LINE('Hello ' || v_name);
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('エラー: ' || SQLERRM);
    RAISE;
END;
/

3つの暗記ポイント:DECLAREとEXCEPTIONは省略可、BEGIN~END;が最小構成、②代入は:==ではない、=は比較演算子)、③ブロック末尾はEND;+スラッシュ/(ツール実行用)。

PL/SQLと通常SQLの違い

項目 通常SQL PL/SQL
基本性質 宣言型(何を) 手続き型(何を+どのように)
変数 無し(バインド変数のみ) ◎ 型付き変数
制御構文 CASE式のみ IF/CASE文/LOOP/WHILE/FOR
例外処理 なし(エラーは呼出側) ◎ EXCEPTION句
関数/手続き定義 不可 プロシージャ/ファンクション/パッケージ
コンパイル 実行時解析 事前コンパイル+データベース内に保存
実行場所 クライアント発行→サーバー実行 サーバー内でブロック単位実行(ラウンドトリップ削減)

PL/SQLの最大のメリット

ネットワークラウンドトリップ削減が最大の強み。「100件取得→判定→更新」を通常SQLで書くと3往復、PL/SQLなら1往復で完結。大量データ処理が劇的に高速化します。さらにSQLインジェクション耐性、トリガー/パッケージ化によるロジック一元管理、業務ルール集約などのメリットもあります。

4セクション構造の詳解

PL/SQLブロックの構造
[&lt;&lt;ラベル名&gt;&gt;]
DECLARE              ← 省略可
  -- 変数/定数/例外/カーソル/ネスト型の宣言
BEGIN                ← 必須
  -- 実行本体(SQL実行・PL/SQL制御文)
EXCEPTION            ← 省略可
  WHEN 例外名 THEN
    -- 例外処理
END [ラベル名];       ← 必須(セミコロン含む)
/                    ← ツール実行の合図(スクリプト内必須)

①DECLARE:宣言セクション(省略可)

DECLAREの中身
DECLARE
  -- 変数
  v_name   VARCHAR2(50);
  v_count  NUMBER := 0;            -- 初期値
  v_flag   BOOLEAN DEFAULT FALSE;  -- := でも DEFAULT でも同じ

  -- 定数
  c_tax_rate CONSTANT NUMBER := 0.10;

  -- 型継承
  v_email  users.email%TYPE;       -- users.emailと同じ型
  v_user   users%ROWTYPE;          -- users全列のレコード

  -- カスタム型
  TYPE t_ids IS TABLE OF NUMBER;
  v_ids t_ids := t_ids();

  -- 例外
  e_custom EXCEPTION;
  PRAGMA EXCEPTION_INIT(e_custom, -20001);

  -- カーソル
  CURSOR cur_users IS SELECT id FROM users WHERE status = 'A';
BEGIN
  NULL;
END;

DECLAREで宣言できるもの

  • 変数(VARCHAR2NUMBERDATEBOOLEAN等)
  • 定数(CONSTANTキーワード)
  • ユーザー定義型(TYPE ... IS RECORDTABLEVARRAY
  • サブタイプ(SUBTYPE
  • 例外(EXCEPTIONPRAGMA EXCEPTION_INIT
  • カーソル(CURSOR ... IS SELECT ...
  • 入れ子ブロック内ローカルプロシージャ/ファンクション

詳細は【PL/SQL】変数・定数完全ガイド参照。

②BEGIN:実行セクション(必須)

BEGINで書ける処理
BEGIN
  -- SQL文
  SELECT email INTO v_email FROM users WHERE id = 1;
  INSERT INTO orders VALUES (...);
  UPDATE users SET status = 'active' WHERE id = 1;
  DELETE FROM logs WHERE created_at &lt; SYSDATE - 365;

  -- 代入
  v_name := 'Taro';
  v_count := v_count + 1;

  -- 制御文
  IF v_count &gt; 10 THEN ...
  FOR i IN 1..10 LOOP ...
  WHILE v_flag LOOP ...
  CASE v_type WHEN 'A' THEN ...

  -- サブプログラム呼び出し
  my_procedure(p_id =&gt; 1);
  v_result := my_function(p_x =&gt; 10);

  -- 例外を手動発生
  RAISE e_custom;
  RAISE_APPLICATION_ERROR(-20001, 'エラー');

  -- トランザクション制御
  COMMIT;
  ROLLBACK;
  SAVEPOINT sp_1;
END;

③EXCEPTION:例外処理セクション(省略可)

EXCEPTION基本
BEGIN
  SELECT email INTO v_email FROM users WHERE id = 999;  -- 0件ならNO_DATA_FOUND
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    DBMS_OUTPUT.PUT_LINE('該当なし');

  WHEN TOO_MANY_ROWS THEN
    DBMS_OUTPUT.PUT_LINE('複数件検出');

  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('予期せぬエラー: ' || SQLCODE || ' / ' || SQLERRM);
    RAISE;   -- 呼出し元に再送出
END;

EXCEPTIONの3つの鉄則:①具体例外(NO_DATA_FOUND等)を先に書く、②WHEN OTHERSは最後の網、③WHEN OTHERS THEN NULL;は例外窒息のアンチパターン——必ずRAISEで再送出。詳細は【PL/SQL】例外処理完全ガイド参照。

④END:終了(必須)

ENDパターン
-- 基本
END;

-- ラベル付きブロックの終了時はラベル名で対応を明示
&lt;&lt;main_block&gt;&gt;
BEGIN
  ...
END main_block;

-- ネストされたPROCEDUREの終了
CREATE OR REPLACE PROCEDURE calc_tax(p_amount IN NUMBER) IS
BEGIN
  ...
END calc_tax;   -- プロシージャ名を書いて対応を明示

PL/SQLブロックの7種類

「4セクション」は共通ですが、ブロック全体を「何として定義するか」で7種類に分かれます。

種類 保存先 主な用途
①匿名ブロック 保存されず一時実行 試行錯誤/バッチ/スクリプト
②ストアドプロシージャ DB内に保存 再利用可能な処理(値を返さない)
③ストアドファンクション DB内に保存 値を返す関数(SELECT内でも使用可)
④パッケージ(仕様+本体) DB内に保存 関連手続き・関数・定数をまとめる
⑤トリガー DB内に保存 DML/DDL/ログオン等に自動応答
⑥オブジェクト型メソッド DB内に保存 オブジェクト型の振る舞い定義
⑦WITH FUNCTION SQL文内限定 SQL文内に関数定義(12c+)

①匿名ブロック(Anonymous Block)

最も基本的な形
-- 保存されない。実行即解放
BEGIN
  DBMS_OUTPUT.PUT_LINE('匿名ブロック');
END;
/

-- ツール(SQLcl/SQL Developer)から直接実行
-- 試行錯誤やバッチ実行に使う

②ストアドプロシージャ

再利用可能な処理
CREATE OR REPLACE PROCEDURE update_user_status(
  p_id      IN NUMBER,
  p_status  IN VARCHAR2
) IS
BEGIN
  UPDATE users SET status = p_status, updated_at = SYSDATE
  WHERE id = p_id;

  IF SQL%ROWCOUNT = 0 THEN
    RAISE_APPLICATION_ERROR(-20001, 'ユーザーが見つかりません');
  END IF;
END update_user_status;
/

-- 呼び出し
BEGIN
  update_user_status(p_id =&gt; 1, p_status =&gt; 'active');
END;
/

③ストアドファンクション

値を返す関数
CREATE OR REPLACE FUNCTION get_user_count(
  p_status IN VARCHAR2
) RETURN NUMBER IS
  v_count NUMBER;
BEGIN
  SELECT COUNT(*) INTO v_count FROM users WHERE status = p_status;
  RETURN v_count;
END get_user_count;
/

-- PL/SQL内でも
DECLARE
  v_n NUMBER;
BEGIN
  v_n := get_user_count('active');
  DBMS_OUTPUT.PUT_LINE('active: ' || v_n);
END;

-- SQL文内でも使える
SELECT get_user_count('active') AS active_count FROM dual;

プロシージャとファンクションの詳細

両者の違い・引数モード(IN/OUT/IN OUT)・戻り値型の設計は【PL/SQL】ストアドプロシージャとファンクションの違いと作り方【PL/SQL】IN・OUT・IN OUTパラメータの完全ガイドで詳解。

④パッケージ(PACKAGE + PACKAGE BODY)

仕様と本体の分離
-- 仕様(インタフェース公開)
CREATE OR REPLACE PACKAGE pkg_user IS
  PROCEDURE activate(p_id IN NUMBER);
  FUNCTION  count_active RETURN NUMBER;
END pkg_user;
/

-- 本体(実装)
CREATE OR REPLACE PACKAGE BODY pkg_user IS
  PROCEDURE activate(p_id IN NUMBER) IS
  BEGIN
    UPDATE users SET status = 'active' WHERE id = p_id;
  END activate;

  FUNCTION count_active RETURN NUMBER IS
    v_n NUMBER;
  BEGIN
    SELECT COUNT(*) INTO v_n FROM users WHERE status = 'active';
    RETURN v_n;
  END count_active;
END pkg_user;
/

-- 呼び出し
BEGIN
  pkg_user.activate(1);
  DBMS_OUTPUT.PUT_LINE(pkg_user.count_active);
END;

⑤トリガー/⑥オブジェクト型メソッド/⑦WITH FUNCTION

セミコロン(;)とスラッシュ(/)の使い分け

PL/SQL初心者が必ず混乱するのが;/の使い分けです。役割がまったく違います。

記号 役割 置く場所
;(セミコロン) 文の終了マーカー 各SQL文/PL/SQL文/ENDの直後
/(スラッシュ) ブロック/ストアドをツールに送信実行する合図 END;次の行(行頭、単独)
正しい書き方
BEGIN
  DBMS_OUTPUT.PUT_LINE('A');    -- ここで1文終了 → ;
  DBMS_OUTPUT.PUT_LINE('B');    -- こっちも文終了 → ;
END;                            -- ブロック終了 → ;
/                               -- ツールへ「実行しろ」の合図(行頭単独)

よくある間違い:ENDの後にセミコロンが無い→コンパイルエラー、②END;の同じ行に/を書く→/が識別子扱いされエラー、③/をブロック内に書く→SQL*Plusが早期実行してエラー。/は必ずブロック終了後の次の行頭に単独で書きます。

スラッシュは”ツール向けコマンド”

/SQL*Plus/SQLcl/SQL Developerが「ここまでをサーバーに送って実行」と解釈するコマンドで、PL/SQL言語そのものの一部ではありません。アプリケーション(JavaやPython)からPL/SQLを呼ぶ時には不要。一方でスクリプトファイル(.sql)で複数のブロックを並べて実行する時は必須です。

コメント2種類とドキュメント

コメント記法
-- 単一行コメント(行末まで)
DECLARE
  v_count NUMBER := 0;   -- 初期化
BEGIN
  /*
     複数行コメント
     ブロック全体を囲む
  */
  v_count := v_count + 1;

  /* インラインの /* ネスト */ は許可されない */
  -- ↑ネストはサポート無し、上記はコメント途中で終了する
END;

プロシージャのドキュメントコメント

README風コメント
CREATE OR REPLACE PROCEDURE calc_shipping_fee(
  p_order_id  IN  NUMBER,
  p_country   IN  VARCHAR2,
  p_fee       OUT NUMBER
) IS
/*
------------------------------------------------------------------------
Procedure  : calc_shipping_fee
Purpose    : 注文IDと配送国から送料を計算してOUTに返す
Parameters :
  p_order_id : 注文ID(必須)
  p_country  : 配送国(ISO 3166-1 alpha-2)
  p_fee      : 送料(OUT)
Errors     :
  -20001 : 注文が見つからない
  -20002 : 配送先が対応外
Author     : team-order / 2026-04-23
------------------------------------------------------------------------
*/
BEGIN
  -- 実装
  NULL;
END calc_shipping_fee;

ドキュメントコメントはパラメータ/戻り値/例外/改訂履歴をパッケージ/プロシージャ冒頭に書くのが業界慣習。USER_SOURCEビューで全ソースをgrepすれば、プロジェクト全体のドキュメントとして機能します。

DBMS_OUTPUTの使い方と”表示されない”問題の解決

基本+表示有効化
-- SQL*Plus / SQLcl / SQL Developer で実行前に必須
SET SERVEROUTPUT ON;
SET SERVEROUTPUT ON SIZE UNLIMITED;
SET SERVEROUTPUT ON FORMAT WRAPPED;

-- これ無しだとPUT_LINEの内容は表示されない

-- 基本の出力
BEGIN
  DBMS_OUTPUT.PUT_LINE('Hello');
  DBMS_OUTPUT.PUT_LINE('Count = ' || 10);
  DBMS_OUTPUT.PUT_LINE(SYSTIMESTAMP);
END;
/

-- 改行せず追記(PUT+NEW_LINE)
BEGIN
  DBMS_OUTPUT.PUT('A');
  DBMS_OUTPUT.PUT('B');
  DBMS_OUTPUT.NEW_LINE;     -- ここで改行
  -- 出力: AB
END;

DBMS_OUTPUT.PUT_LINEは本番ロギングに使わない。バッファに溜まって終了時に吐かれるだけで、途中取得困難。本番ではPRAGMA AUTONOMOUS_TRANSACTION付きのログプロシージャでテーブルに記録する方式が定石。詳細は【PL/SQL】例外処理完全ガイド参照。

コンパイルとエラーメッセージの読み方

エラー確認の3コマンド
-- ①コンパイル後すぐに SHOW ERRORS
CREATE OR REPLACE PROCEDURE my_proc IS
BEGIN
  invalid_statement_here;     -- 意図的にエラー
END;
/
SHOW ERRORS;
-- Errors for PROCEDURE MY_PROC:
-- LINE/COL ERROR
-- -------- -------------------------------------------------
-- 3/3      PLS-00201: identifier 'INVALID_STATEMENT_HERE' must be declared

-- ② USER_ERRORS ビューで確認
SELECT line, position, text FROM user_errors
WHERE name = 'MY_PROC' AND type = 'PROCEDURE'
ORDER BY sequence;

-- ③ DBMS_UTILITY.FORMAT_ERROR_STACK(実行時用)
BEGIN
  my_proc;
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_STACK);
    DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
END;

よくあるコンパイルエラーTOP5

エラーコード 意味 よくある原因
PLS-00103 予期しないシンボル セミコロン忘れ/キーワード誤用/予約語
PLS-00201 識別子を宣言してください 未宣言変数/typo/権限なし
PLS-00302 コンポーネントが宣言されていない レコード/カーソル列名ミス
PLS-00306 引数の数/型が一致しない プロシージャ呼び出しの引数不一致
PLS-00363 定数式に代入不可 CONSTANT変数に代入しようとした

実行環境別の使い方

SQLcl(無料・CLI)
# インストール(Javaが必要)
# https://www.oracle.com/database/sqldeveloper/ からダウンロード

# 接続
sql user/password@host:port/service

# スクリプト実行
SQL&gt; @my_script.sql

# PL/SQLブロック直接入力
SQL&gt; SET SERVEROUTPUT ON;
SQL&gt; BEGIN
  2    DBMS_OUTPUT.PUT_LINE('Hello');
  3  END;
  4  /
SQL Developer(GUI・無料)
-- Oracle社公式GUI(Javaベース)
-- SQLワークシートにPL/SQLを貼って F5(Run Script)または Ctrl+Enter(Run)
-- SET SERVEROUTPUT ON; を実行する必要あり
-- View → Dbms Output ウィンドウで出力確認
VS Code Database Client
-- 拡張: Database Client (cweijan.vscode-mysql-client2) で Oracle接続
-- .sql ファイルを開いて Ctrl+Alt+E で PL/SQL ブロック実行
-- DBMS_OUTPUTの受信は拡張によって異なる

2026年のおすすめ

CLI好きはSQLcl(標準同梱のオラクルCLI)、GUI好きはSQL Developer(Oracle公式無料)、VS Code好きはDatabase Client拡張。本番のPL/SQL開発者はSQLcl+Gitでのソース管理が主流。SQL Developerのコード補完はOracle専用構文の強みがあり、初学者にはSQL Developer推奨です。

ラベル付きブロックとネスト

ラベル付きの例
&lt;&lt;outer&gt;&gt;
DECLARE
  v_x NUMBER := 1;
BEGIN
  &lt;&lt;inner&gt;&gt;
  DECLARE
    v_x NUMBER := 2;  -- 外のv_xと同名(内側で隠蔽)
  BEGIN
    DBMS_OUTPUT.PUT_LINE(v_x);         -- 2(内側)
    DBMS_OUTPUT.PUT_LINE(outer.v_x);   -- 1(外側をラベルで参照)
  END inner;

  FOR i IN 1..3 LOOP
    FOR j IN 1..3 LOOP
      EXIT outer WHEN i * j &gt; 5;    -- 外ループまで一気に脱出
    END LOOP;
  END LOOP;
END outer;

ラベルの効用

変数・代入・NULLの基礎

代入と比較
DECLARE
  v_a NUMBER := 10;
  v_b NUMBER;
  v_c NUMBER;
BEGIN
  -- 代入は := (コロンイコール)
  v_b := v_a;
  v_c := v_a + v_b;

  -- 比較は = (イコール)
  IF v_a = v_b THEN
    DBMS_OUTPUT.PUT_LINE('等しい');
  END IF;

  -- NULL比較は IS NULL
  IF v_b IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('NULLです');
  END IF;

  -- NULLとの = 比較は常にNULL(FALSEでもTRUEでもない!)
  IF v_b = NULL THEN    -- この条件は常にFALSE扱いになる
    DBMS_OUTPUT.PUT_LINE('到達不能');
  END IF;
END;

3値論理の罠:PL/SQLはTRUE/FALSE/NULLの3値論理です。NULL = NULLNULL != 10はどちらもNULL(TRUEでもFALSEでもない)で、IF文ではELSEに落ちます。NULLを明示的に扱うにはIS NULLIS NOT NULLを使用。詳細は【PL/SQL】IF文完全ガイド参照。

変数宣言・データ型・定数(CONSTANT)・%TYPE%ROWTYPEなどの深掘りは【PL/SQL】変数・定数完全ガイドを参照。

PL/SQL学習ロードマップ(16ステップ)

初級→中級→上級
【初級(1〜2週間)】
 1. 4セクション構造(本記事)
 2. 変数・定数・データ型
 3. IF文とCASE文
 4. LOOPとFORループ
 5. SELECT INTO と例外処理基礎

【中級(2〜4週間)】
 6. カーソル(Cursor FOR Loop)
 7. %TYPE / %ROWTYPE
 8. ストアドプロシージャとファンクション
 9. IN/OUT/IN OUTパラメータ
10. 例外処理の完全理解(RAISE_APPLICATION_ERROR)

【上級(1〜3ヶ月)】
11. パッケージ(仕様と本体)
12. トリガー(BEFORE/AFTER/Compound)
13. コレクション(TABLE/VARRAY/RECORD)
14. バルク処理(BULK COLLECT/FORALL)
15. 動的SQL(EXECUTE IMMEDIATE)
16. 自律トランザクション/SAVEPOINT

初学者のつまずきポイント10選

DBMS_OUTPUT.PUT_LINEが表示されないSET SERVEROUTPUT ON;を忘れているか、ツールの出力ウィンドウが開いていない。

/の位置で混乱END;の次の行・行頭・単独でないとエラー。END; /同じ行はNG。

③代入は:=、比較は=:PL/SQL初心者が必ず踏む罠。多くの言語とは逆。

SELECT INTOで0件エラーNO_DATA_FOUND例外が発生。必ずEXCEPTIONでハンドリング。

ELSIFの綴りELSE IFではなくELSIF(スペース無し)

CONSTANT変数への代入エラーPLS-00363。定数は再代入不可。

⑦NULL比較で= NULL:常にNULL評価されTHENに入らない。IS NULLを使用。

⑧予約語を変数名に使ってしまうdatecountlevel等。v_プレフィックスで回避。予約語完全ガイド参照。

⑨変数を宣言する場所がわからない:必ずDECLAREセクションBEGINの前)。BEGIN内で新規変数は定義不可。

⑩コメントアウトの入れ子/* ... /* */ ... */ネスト不可で最初の*/でコメント終了。--(単一行)を多用する方が安全。

よくある質問

QDECLAREは書かないといけない?
Aいいえ、省略可能です。変数・定数・カーソル等を宣言しない場合はDECLAREを書かずBEGINから始められます。ただしストアドプロシージャ/ファンクション/パッケージ本体ではDECLAREキーワード自体は書かずISASの後に変数宣言が続きます。
Q/(スラッシュ)はいつ必要?
ASQL*Plus/SQLcl/SQL Developerのスクリプト実行時のみ必要。ツールが「ここまでをサーバーに送信して実行」と解釈します。アプリケーション(Java/Python等)からPL/SQLを呼ぶ時や、トリガー/ストアドの中身としてネストする時は不要。スクリプトで複数ブロックを並べる時は必須
QDBMS_OUTPUTが表示されない
Aツール側の設定が必要:①SET SERVEROUTPUT ON;を実行(SQL*Plus/SQLcl)、②SQL Developerなら View → Dbms Outputウィンドウを開き接続を追加、③SET SERVEROUTPUT ON SIZE UNLIMITED;でバッファ拡大。なお本番ロギングには使わない(バッファ制限+終了時一括出力)。
Q無名ブロックとストアドプロシージャの違いは?
A無名ブロックDECLARE BEGIN ... END;の1回限り実行型、データベースに保存されない。ストアドプロシージャCREATE OR REPLACE PROCEDURE ...でDBにコンパイル済み状態で保存、何度でも再利用できる。繰り返し実行するロジックはストアド化、試行錯誤は無名ブロック、と使い分けます。
QISASはどちらを使う?
A完全に同義CREATE PROCEDURE ... IS BEGIN ... END;でもCREATE PROCEDURE ... AS BEGIN ... END;でも動きます。Oracleの慣習はIS(プロシージャ/ファンクション)、ASはビュー定義(CREATE VIEW ... AS SELECT)でよく見ます。
QPL/SQLはどのDBで動く?
AOracle Database専用(Oracle XE/Standard/Enterprise)です。MySQL/PostgreSQL/SQL Serverには独自のプロシージャ言語があります:MySQL はBEGIN...ENDストアドプロシージャ構文、PostgreSQL はPL/pgSQL、SQL ServerはT-SQL。基本構造は似ていますが構文は独立しています。
Qセミコロン(;)を書き忘れるとどうなる?
APLS-00103: Encountered the symbol “END”など、次の行のキーワードが予期しない場所にあると解釈されてコンパイルエラー。「各文の終わり」「ブロックの終わり(END;)」の2箇所必須。特にENDの後の;忘れが多発します。
Qコメントで#は使える?
A使えません。PL/SQLのコメントは--(単一行)//* */(複数行)の2種類のみ。#はエラーになります(PLS-00103)。シェルスクリプトやPythonの癖で#を書くとコンパイルエラーに。
Qインデントやスペースはどうすべき?
APL/SQLは空白に寛容でどう書いても動きますが、業界標準は①キーワード大文字BEGINIF)、②識別子小文字+スネークケースv_user_id)、③2スペースインデント、④THENLOOPの前で改行、⑤END IF;END LOOP;END;を左寄せ、の5点を守ると読みやすい。
QPL/SQLの関数をSQLのSELECT内で使える?
A使えます(ストアドファンクションのみ)。SELECT get_user_count('active') FROM dual;のように呼び出せます。ただしDETERMINISTIC指定がないとSQL最適化が制限され、関数内でDMLをするとSELECT失敗するなど制約があります。12c+のWITH FUNCTION句でインラインファンクション定義も可能。
QPL/SQLはパフォーマンス面で不利?
A適切に書けば超高速。ラウンドトリップ削減・BULK COLLECT+FORALLで1万件UPDATEが秒単位で完了。逆にCursor FOR Loop内で1行ずつDMLなどアンチパターンを書くと遅い。ループ内DMLはバルク化、SELECT は結合/集計をSQLに寄せる、PL/SQLは制御フロー中心に、というメンタルモデルが重要です。

関連記事

まとめ

  • PL/SQLはOracle専用の手続き型拡張SQL、ラウンドトリップ削減が最大のメリット
  • ブロックの4セクション:DECLARE(省略可)/BEGIN(必須)/EXCEPTION(省略可)/END;(必須)
  • ブロック7種類:匿名/プロシージャ/ファンクション/パッケージ/トリガー/型メソッド/WITH FUNCTION
  • セミコロン(;)は文の終了、スラッシュ(/)はツールへの実行合図
  • 代入は:=、比較は=、NULL比較はIS NULL(3値論理)
  • コメントは--(単一行)//* */(複数行、ネスト不可)
  • DBMS_OUTPUTSET SERVEROUTPUT ON;必須、本番ロギングには使わない
  • コンパイルエラーはSHOW ERRORSUSER_ERRORSビューで確認
  • 主要エラー:PLS-00103(構文)/PLS-00201(未宣言)/PLS-00306(引数)
  • 実行環境:SQLcl(CLI)/SQL Developer(GUI)/VS Code拡張
  • ラベル付き(<<name>>)で変数衝突解決・ネストループ一括脱出
  • 学習順:4セクション→変数→IF→LOOP→例外→カーソル→プロシージャ→パッケージ→トリガー→バルク処理
  • 初学者の罠:SERVEROUTPUT忘れ//の位置/:==NULL比較/ELSIFの綴り

PL/SQLはSQLに手続き型構文を加えたOracle最強のサーバーサイド言語。本記事の4セクション構造・7種類のブロック・セミコロン/スラッシュ使い分け・エラーメッセージの読み方・学習ロードマップを押さえれば、ゼロから始めて実務のPL/SQL開発に立てるレベルへ着実に進めます。次のステップとして変数・定数IF文ループ例外処理カーソルプロシージャ/ファンクションの順で学習を進めましょう。