初投稿がpostgresql!
書き方慣れないので、見にくいかもしれません。。。
今ユーザー定義の入力帳票をjsonb型でデータを格納しています。
入力チェックを基本していません。
jsonは日付フォーマットに沿っていないと、普通に日付キャストして検索をかけようとするとエラーになります。
たとえば、すでに2020-3-99と日付型ではないデータが入っていた場合に下記のようにエラーがでます。(betweenで取得を試みる)
"errorInfo": "22008",
7,
"ERROR: date/time field value out of range: \"2020-3-99\"\nHINT: Perhaps you need a different \"datestyle\" setting."
なので、日付形式に沿っているものだけ抽出するできるものが欲しいと考えて
調べたりした結果サブクエリ化しても大変なので、ファンクション化しようとおもいました。
ファンクション関数は作ったことがなかったんで、いろいろ突っ込みどころはあるかとおもいますが、下記で動きました
こちらを参考にしてカスタマイズさせていただきました。
https://postgresweb.com/post-166
betweenで検索用
CREATE OR REPLACE FUNCTION "public"."jsondatebetween"(text, date, date)
RETURNS "pg_catalog"."bool" AS $BODY$
declare
c_date alias for $1; --引数1:日付チェックする文字列
s_date alias for $2;
e_date alias for $3;
c_execute character varying; --動的SQLの格納用
d_temp bool; --一時変数
BEGIN
c_execute := 'SELECT date(''' || c_date || ''') BETWEEN date(''' || s_date || ''') and date(''' || e_date || ''')';
EXECUTE c_execute INTO d_temp;
return d_temp;
EXCEPTION
WHEN OTHERS THEN
return FALSE;
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
比較演算子で検索用
CREATE OR REPLACE FUNCTION "public"."jsondatecomparison"(text, varchar, date)
RETURNS "pg_catalog"."bool" AS $BODY$
declare
c_date alias for $1; --日付チェックする文字列
comparison alias for $2; --比較文字列
s_date alias for $3; --
c_execute character varying; --SQL格納用
d_temp bool; --一時変数
BEGIN
c_execute := 'SELECT date(''' || c_date || ''') ' || comparison || ' date(''' || s_date || ''')';
EXECUTE c_execute INTO d_temp;
return d_temp;
EXCEPTION
WHEN OTHERS THEN
return FALSE;
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ネーミングセンスないです(;^ω^)
大文字は使えないとか見ました。
使う時は、ちゃんとキャストするなどしてつかわないとエラーがでてきますので気を付けてください(ちょっとハマった)