次の現場でPL/SQLが必要そうなので勉強中。
とりあえずいろいろ種類があるっぽい。
・無名ブロック
・ストアドプロシージャ – PROCEDURE
・ストアドファンクション – FUNCTION
・ストアドパッケージ – PACKAGE
テーブルとか
PL/SQL標準出力
とりあえず標準出力を許可。
-- DBMS_OUTPUT 出力ON
SET SERVEROUTPUT ON;
参考
SET SERVEROUTPUTオラクル・Oracle SQL*Plus リファレンス
無名ブロック その1
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello World');
END;
/
実行結果
PL/SQLプロシージャが正常に完了しました。 Hello World
無名ブロック その2
DECLARE
-- 変数設定
hoge VARCHAR2(10) := 'test';
BEGIN
DBMS_OUTPUT.PUT_LINE('hello world:' || hoge);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error!!');
END;
/
実行結果
PL/SQLプロシージャが正常に完了しました。 Hello World:test
ストアドプロシージャ
get_name.sql
CREATE OR REPLACE PROCEDURE GET_NAME (
v_id IN NUMBER,
v_name OUT VARCHAR2
) AS
BEGIN
SELECT NAME INTO v_name FROM TRANSACTION1 WHERE ID = v_id;
END GET_NAME;
/
無名ブロック から呼び出し
DECLARE
v_name varchar2(40);
BEGIN
GET_NAME(v_id => 2, v_name => v_name);
DBMS_OUTPUT.PUT_LINE(v_name);
END;
/
PL/SQLプロシージャが正常に完了しました。 BBB
ストアドファンクション
get_name2.sql
CREATE OR REPLACE FUNCTION GET_NAME2(v_id IN NUMBER)
RETURN VARCHAR2 AS
v_name VARCHAR2(40);
BEGIN
SELECT NAME INTO v_name FROM TRANSACTION1 WHERE ID = v_id;
RETURN v_name;
END GET_NAME2;
/
SQL から呼び出し
SELECT GET_NAME2(3) FROM DUAL;
GET_NAME2(3) -------------------------------------------------------------------------------- CCC
無名ブロック から呼び出し
DECLARE
v_name VARCHAR2(40);
BEGIN
v_name := GET_NAME2(v_id => 3);
DBMS_OUTPUT.PUT_LINE(v_name);
END;
/
PL/SQLプロシージャが正常に完了しました。 CCC
IF文
DECLARE
v_id NUMBER;
BEGIN
v_id := 10;
IF v_id BETWEEN 1 AND 5 THEN
DBMS_OUTPUT.PUT_LINE('1~5');
ELSIF v_id BETWEEN 6 AND 9 THEN
DBMS_OUTPUT.PUT_LINE('6~9');
ELSE
DBMS_OUTPUT.PUT_LINE('ELSE:' || TO_CHAR(v_id));
END IF;
END;
/
実行結果
PL/SQLプロシージャが正常に完了しました。 ELSE:10
%TYPE と %ROWTYPE
DECLARE
v_name TRANSACTION1.NAME%TYPE;
v_transaction1 TRANSACTION1%ROWTYPE;
BEGIN
SELECT NAME INTO v_name FROM TRANSACTION1 WHERE ID = 1;
SELECT * INTO v_transaction1 FROM TRANSACTION1 WHERE ID = 2;
DBMS_OUTPUT.PUT_LINE(v_name);
DBMS_OUTPUT.PUT_LINE(v_transaction1.KBN);
END;
/
実行結果
PL/SQLプロシージャが正常に完了しました。 AAA KBN001
LOOP
BEGIN
FOR v_count IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(v_count);
END LOOP;
END;
/
実行結果
PL/SQLプロシージャが正常に完了しました。 1 2 3 4 5 6 7 8 9 10
ストアドパッケージ
パッケージはパッケージ仕様とパッケージ本体に分けるのが定石のようです。
PKG_TEST.sql
CREATE OR REPLACE PACKAGE PKG_TEST
AS
FUNCTION TEST(p_number NUMBER)
RETURN NUMBER;
FUNCTION TEST(p_char NVARCHAR2)
RETURN NVARCHAR2;
FUNCTION TEST(p_date DATE)
RETURN DATE;
END;
/
PKG_TEST_BODY.sql
CREATE OR REPLACE PACKAGE BODY PKG_TEST
AS
FUNCTION TEST(p_number in NUMBER)
RETURN NUMBER
AS
BEGIN
RETURN p_number + 1; -- 加算
END;
FUNCTION TEST(p_char in NVARCHAR2)
RETURN NVARCHAR2
AS
BEGIN
RETURN p_char || ' - TEST'; -- 結合
END;
FUNCTION TEST(p_date in DATE)
RETURN DATE
AS
BEGIN
RETURN p_date + 1; -- 加算
END;
END;
/
実行結果
-- SQLから実行
SELECT PKG_TEST.TEST(100) FROM DUAL;
SELECT PKG_TEST.TEST('oqiita') FROM DUAL;
SELECT PKG_TEST.TEST(SYSDATE) FROM DUAL;
PKG_TEST.TEST(100) --------------------------------------- 101 PKG_TEST.TEST('OQIITA') -------------------------------------------------------------------------------- oqiita - TEST PKG_TEST.TEST(SYSDATE) ---------------------- 2018-09-06 14:26:32
まとめ
いろいろ種類があってムズいな!!