0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PostgreSQL 問い合わせ言語(SQL)で関数、プロシージャを作成する

Last updated at Posted at 2024-11-16

問い合わせ言語(SQL)で関数、プロシージャを作成するときについて、気にすることをまとめてみました

関数の定義

関数は CREATE [OR REPLACE] FUNCTION SQLコマンドで作成し、書式は以問い合わせ言語(SQL)下です

書式

CREATE [OR REPLACE] FUNCTION 関数名 ([引数][,引数, ...]) [RETURNS 戻り値型 | RETURNS TABLE ] AS '関数定義文字列' LANGUAGE 言語名

引数
[引数モード] [引数名] 引数型 [ { DEFAULT | = } デフォルト値]

言語名
関数を実装している言語の名前を指定します。 このパラメータには、sql、c、internal、もしくはユーザ定義手続き言語(例:plpgsql)の名前を指定可能です。

関数定義文字列
関数の本体の定義を記述した文字列定数です。言語名で指定した言語で記述します。<br>
定義を記述する際は、通常の単一引用符ではなく、ドル引用符 を使用するほうが便利に記載できます。

問い合わせ言語(SQL)で関数を作成する場合は、書式は以下です

問い合わせ言語(SQL)関数 書式

CREATE [OR REPLACE] FUNCTION 関数名 ([引数][,引数, ...]) [RETURNS 戻り値型 | RETURNS TABLE ] AS $$
関数定義文字列
$$ LANGUAGE SQL

問い合わせ言語(SQL)関数テンプレート

引数なし、戻り値が void 型

CREATE OR REPLACE FUNCTION func_name() RETURNS void AS $$

$$ LANGUAGE SQL;

関数本体の書き方

SQL関数は、任意のSQL文のリストを実行し、そのリストの最後の問い合わせの結果を返します。
単純な(集合ではない)場合、最後の問い合わせの結果の最初の行が返されます。 最後の問い合わせが何も行を返さない時はNULL値が返されます。
SQL関数の本体は、セミコロンで区切ったSQL文のリストで記述します。 最後の文の後のセミコロンは省略可能です。 関数がvoid型と宣言されていない限り、最後の文はSELECT、またはRETURNING句を持つINSERT、UPDATE、またはDELETEでなければなりません。

例1 Hello World を返すSQL関数。

最後のSELECT文の結果が戻り値になります

CREATE OR REPLACE FUNCTION HelloWorld() RETURNS text AS $$
 SELECT 'Hello World';
$$ LANGUAGE SQL;

戻り値は、’Hello' になります

CREATE OR REPLACE FUNCTION Hello() RETURNS text AS $$
 SELECT 'Hello World';
 SELECT 'Hello'
$$ LANGUAGE SQL;

例1の実施例

testdb5=# select HelloWorld();
 helloworld  
-------------
 Hello World
(1 row)

testdb5=# select Hello();
 hello 
-------
 Hello
(1 row)

例2-1 引数を返す SQL関数

CREATE OR REPLACE FUNCTION echo (message text) RETURNS text AS $$
  SELECT message;
$$ LANGUAGE SQL;

例2-1の実施

testdb5=# select echo('Hello');
 echo  
-------
 Hello
(1 row)

例2-2 引数を返す SQL関数

引数が型のみの記述の場合、$1, $2, ... で表現します

CREATE OR REPLACE FUNCTION echo2 (text) RETURNS text AS $$
  SELECT $1
$$ LANGUAGE SQL;

例2-2 の実施例

testdb5=# select echo2('Hello');
 echo2 
-------
 Hello
(1 row)

例3 prod テーブルの prod_name の最初の行を返すSQL関数

CREATE OR REPLACE FUNCTION prod_name() RETURNS text AS $$
 SELECT prod_name FROM prod;
$$ LANGUAGE SQL;

例3の実施例 テーブルの最初の行が戻り値として返します

testdb5=# testdb5=# select prod_name from prod;
 prod_name 
-----------
  みかん
  りんご
  メロン
(3 rows)

testdb5=# select prod_name();
 prod_name 
-----------
  みかん
(1 row)

例4 戻り値の型と SELECT文の返す型が一致しないと関数登録時にエラーになります

testdb=# CREATE OR REPLACE FUNCTION prod_name2() RETURNS text AS $$
 SELECT * FROM prod;
$$ LANGUAGE SQL;
ERROR:  return type mismatch in function declared to return text
DETAIL:  Final statement must return exactly one column.
CONTEXT:  SQL function "prod_name2"
testdb=# 

例5-1 戻り値が集合の場合の定義

戻り値にTABLEを使用した場合

CREATE OR REPLACE FUNCTION prod_name2() RETURNS TABLE(prod_name text) AS $$
 SELECT prod_name FROM prod;
$$ LANGUAGE SQL;

例5-1の実施例

testdb5=# select prod_name2();
 prod_name2 
------------
  みかん
  りんご
  メロン
(3 rows)

例5-2 戻り値が集合の場合の定義

戻り値に SETOF テーブル名 を 使用した場合

CREATE OR REPLACE FUNCTION prodlists() RETURNS SETOF prod AS $$
 SELECT * FROM prod;
$$ LANGUAGE SQL;

例5-2 の実施例

testdb5=# select prodlists();
     prodlists     
-------------------
 (1," みかん",50)
 (2," りんご",70)
 (3," メロン",100)
 (4,かき,100)
 (5,みかん,10)
 (5,みかん,10)
(6 rows)

testdb5=# select * from prodlists();
 prod_id | prod_name | price 
---------+-----------+-------
       1 |  みかん   |    50
       2 |  りんご   |    70
       3 |  メロン   |   100
       4 | かき      |   100
       5 | みかん    |    10
       5 | みかん    |    10
(6 rows)

例6 戻り値がvoid型のSQL関数

戻り値を返さなくていいので、結果を返さない、通常のよく使われるINSERT文等の構文が使えます

CREATE OR REPLACE FUNCTION testdataProd() RETURNS void AS $$
 INSERT INTO prod VALUES(4, 'かき', 100);
$$ LANGUAGE SQL;

例5の実施例

testdb5=# select * from prod;
 prod_id | prod_name | price 
---------+-----------+-------
       1 |  みかん   |    50
       2 |  りんご   |    70
       3 |  メロン   |   100
(3 rows)

testdb5=# select testdataprod();
 testdataprod 
--------------
 
(1 row)

testdb5=# select * from prod;
 prod_id | prod_name | price 
---------+-----------+-------
       1 |  みかん   |    50
       2 |  りんご   |    70
       3 |  メロン   |   100
       4 | かき      |   100
(4 rows)

例6 RETURNING句付きのInsert文でSQL関数を作成

CREATE OR REPLACE FUNCTION testdataProd3() RETURNS TABLE(prod_id integer, prod_name text, price numeric) AS $$
 INSERT INTO prod VALUES(5, 'みかん', 10) RETURNING prod_id, prod_name, price;
$$ LANGUAGE SQL;

例6の実施例

testdb=# select testdataprod3();
 testdataprod3 
---------------
 (1,みかん,10)
(1 row)

testdb5=# select * from testdataProd3();
 prod_id | prod_name | price 
---------+-----------+-------
       5 | みかん    |    10
(1 row)

問い合わせ言語(SQL)プロシージャの作成

書式

CREATE [OR REPLACE] PROCEDURE プロシージャ名 ([引数][,引数, ...]) LANGUAGE 言語名 AS '定義文字列' 

引数
[引数モード] [引数名] 引数型 [ { DEFAULT | = } デフォルト値]

言語名
プロシージャを実装している言語の名前を指定します。 このパラメータには、sql、c、internal、もしくはユーザ定義手続き言語(例:plpgsql)の名前を指定可能です。

定義文字列
プロシージャの本体の定義を記述した文字列定数です。言語名で指定した言語で記述します。
定義を記述する際は、通常の単一引用符ではなく、ドル引用符 を使用するほうが便利に記載できます。

問い合わせ言語(SQL)でプロシージャを作成する場合は、書式は以下になります

問い合わせ言語(SQL)プロシージャ 書式

CREATE [OR REPLACE] PROCEDURE プロシージャ名 ([引数][,引数, ...])  LANGUAGE SQL AS $$
定義文字列
$$ 

問い合わせ言語(SQL)プロシージャ テンプレート

引数なしのテンプレート

CREATE OR REPLACE PROCEDURE proc()
LANGUAGE SQL
AS $$

$$;

例1 問い合わせ言語(SQL)でプロシージャの作成

CREATE OR REPLACE PROCEDURE insertProd(prod_name text, price numeric)
LANGUAGE SQL
AS $$
INSERT INTO prod VALUES (nextval('seqno'), prod_name, price);
$$;

例1 の実施例

testdb5=# testdb5=# call insertProd('すもも', 500);
CALL
testdb5=# select * from prod;
 prod_id | prod_name | price 
---------+-----------+-------
       1 |  みかん   |    50
       2 |  りんご   |    70
       3 |  メロン   |   100
       4 | かき      |   100
       5 | みかん    |    10
       5 | みかん    |    10
       1 | すもも    |   500
(7 rows)

参照情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?