私はRECORDデータ型を使用して複数のレコードを返そうとしていますが、RECORDに追加し、このRECORDに反復するたびに新しい値を追加/追加する方法があります。
つまり、rec
に追加して、ループが終了したときにrec
が行のセットになるようにします。これは、関数の最後で返すだけです。現在、私はこれをやっています-
_SELECT temp_table.col1, temp_table.col2, temp_table.col3
INTO rec
FROM temp_table
WHERE temp_table.col3 = false;
_
私の完全なコードはここにあります:
_CREATE OR REPLACE FUNCTION validation()
RETURNS RECORD AS $$
DECLARE
rec RECORD;
temp_row RECORD;
BEGIN
CREATE TEMPORARY TABLE temp_table (col1 TEXT, col2 INTEGER, col3 BOOLEAN) ON COMMIT DROP;
FOR temp_row IN SELECT * FROM staging.validation
LOOP
RAISE NOTICE 'sql: %', temp_row.sql;
EXECUTE format('INSERT INTO temp_table %s', temp_row.sql);
IF (SELECT DISTINCT temp_table.col3 FROM temp_table WHERE temp_table.col3 = false)=false THEN
RAISE NOTICE 'there is a false value';
SELECT temp_table.col1, temp_table.col2, temp_table.col3
INTO rec
FROM temp_table
WHERE temp_table.col3 = false;
END IF;
END LOOP;
RETURN rec;
END; $$
LANGUAGE plpgsql;
_
SELECT validation();
後の現在の出力
_validation
(crea_ddf,8095,f)
_
望ましい出力
_validation
(crea_ddf,8095,f)
(some_source_system,some_count,f)
(some_other_source_system,some_count,f)
(.....)
_
関数は、RECORD
ではなく_SETOF RECORD
_を返す必要があり、次のように単一のRETURN
ではなく、行ごとに1つの_RETURN NEXT
_が必要です。
_CREATE FUNCTION test() RETURNS SETOF RECORD AS $$
DECLARE
rec record;
BEGIN
select 1,2 into rec;
return next rec;
select 3,4 into rec;
return next rec;
END $$ language plpgsql;
_
発信者:
=> select * from test()as x(a int、b int); a | b --- + --- 1 | 2 3 | 4 (2行)
SQLは強く静的に型付けされているため、RECORD
疑似型は扱いにくいことに注意してください。
多くの場合、最初から、各列の名前と型の完全な定義を備えた複合型を、無名型のTABLE(...)
構文または_CREATE TYPE
_は、永続的な名前付きタイプです。
関数から複数のレコードを返す場合は、_setof record
_および_return next rec
_を使用します。例:
_create or replace function test_function()
returns setof record
language plpgsql as $$
declare
rec record;
begin
for rec in
select i, format('str%s', i), i/2*2 = i
from generate_series(1, 3) i
loop
return next rec;
end loop;
end $$;
_
このような関数は、列定義リストを使用してFROM句で呼び出す必要があります。
_select test_function(); -- NO
ERROR: set-valued function called in context that cannot accept a set
select * from test_function(); -- NO
ERROR: a column definition list is required for functions returning "record"
select * from test_function() as (id int, str text, is_even boolean);
id | str | is_even
----+------+---------
1 | str1 | f
2 | str2 | t
3 | str3 | f
(3 rows)
_
より良いオプションは、returns table(...)
および_return query
_を使用することです。
_drop function if exists test_function();
create or replace function test_function()
returns table (id int, str text, is_even boolean)
language plpgsql as $$
begin
return query
select i, format('str%s', i), i/2*2 = i
from generate_series(1, 3) i;
-- you can use return query multiple times
-- or assign values to columns
-- and return the row:
id = 100;
str = 'extra';
is_even = true;
return next; -- without a parameter
end $$;
_
使用法:
_select test_function(); -- possible but rather impractical
test_function
---------------
(1,str1,f)
(2,str2,t)
(3,str3,f)
(100,extra,t)
(4 rows)
select * from test_function();
id | str | is_even
-----+-------+---------
1 | str1 | f
2 | str2 | t
3 | str3 | f
100 | extra | t
(4 rows)
_
これは危険信号です。
validation
があります。staging
に移動します。temp_table.col3
IS FALSEを含む行はすべてユーザーに返されますこれをしてください.
WITH t AS ( SELECT true AS runthis FROM staging.validation WHERE col3 IS FALSE )
SELECT *
FROM staging.validation
WHERE t.runthis && col3 = 3
UNION ALL
SELECT *
FROM some_source_system
WHERE t.runthis && some_source_system.col3 = 3
UNION ALL
SELECT *
FROM some_other_source_system
WHERE t.runthis && some_other_source_system.col3 = 3;
必要に応じて、VIEW
に配置することもできます
付記として
SELECT DISTINCT temp_table.col3
FROM temp_table
WHERE temp_table.col3 = false
ここでDISTINCT
は何をしますか? LIMITを実行してください。実際、これはさらにクリーンだと主張します。
SELECT true
FROM temp_table
WHERE temp_table.col3 = false
LIMIT 1;
その後、奇妙な必要はありません= false ) = FALSE