在 PostgreSQL 数据库中,我有2个表。
问题
| question_id | question_text | widget | required | position |
|-------------|---------------|--------|----------|----------|
| int | text | int | boolean | int |
FACTORS_QUESTIONS_RELATIONSHIP
| factor_id | question_id |
|-------------|---------------|
| int | text |
您可以在此函数中看到2条插入语句。第一个返回新问题ID的列表。我想在第二个插入语句中使用该ID。如何正确制作?同时,我想从第一条语句返回id作为函数的结果。
CREATE OR REPLACE FUNCTION factorio(
FACTOR_IDENTIFIER INT,
TEXT_ARR VARCHAR[],
WIDGET_ARR INT[],
REQUIRED_ARR BOOLEAN[],
POSITION_ARR INT[]
) RETURNS SETOF INT AS $$
BEGIN
RETURN QUERY
WITH RESULT_SET AS (
INSERT INTO QUESTIONS (TEXT, WIDGET, REQUIRED, POSITION)
SELECT
UNNEST(ARRAY[TEXT_ARR]) AS TEXT,
UNNEST(ARRAY[WIDGET_ARR]) AS WIDGET,
UNNEST(ARRAY[REQUIRED_ARR]) AS REQUIRED,
UNNEST(ARRAY[POSITION_ARR]) AS POSITION
RETURNING ID
)
--
INSERT INTO factors_questions_relationship (FACTOR_ID, QUESTION_ID)
SELECT FACTOR_IDENTIFIER FACTOR_ID, QUESTION_ID FROM UNNEST(ARRAY[array_agg(SELECT ID FROM RESULT_SET)]) QUESTION_ID
--
SELECT ID FROM RESULT_SET;
END;
$$ LANGUAGE plpgsql;
答案 0 :(得分:1)
我只会先将ID放在ID的临时表中。然后发出另一个插入。然后返回ID的临时表。
这是一个例子:
create table z
(
id int generated by default as identity primary key,
question_text text not null
);
create table q_factory
(
id int generated by default as identity primary key,
q_id int not null references z(id),
some_text text not null
);
create or replace function insert_multiple_test()
returns setof int
as
$$
begin
create temporary table x_t on commit drop
as
with resulting_rows as
(
insert into z(question_text) values
('hello'),
('你好'),
('hola')
returning id
)
select id from resulting_rows;
insert into q_factory(q_id, some_text)
select id, q.another
from x_t
cross join unnest(array[
'answer to life and everything',
'are great and awesome'
]) as q(another);
return query select id from x_t;
end;
$$ language 'plpgsql'
测试:
select * from insert_multiple_test();
输出:
测试:
select * from q_factory;
输出:
答案 1 :(得分:1)
嗯..好像不需要创建temporary table。即使您的第二条插入语句依赖于第一条语句的返回ID,也可以直接从返回查询中返回if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) {
// Bug in AnimatorSet for API 23
animation1.start()
animation2.start()
} else {
val animation = AnimatorSet()
animation.playTogether(animation1, animation2)
animation.start()
}
的结果。这是安全的,因为即使在查询中两次引用了result_rows,它也不会运行两次。
无论如何,如果后续的语句/查询是复杂的语句/查询,例如使用循环,您可能仍要使用临时表方法。无法在CTE中嵌入循环。
returning id
测试:
create or replace function insert_multiple_test()
returns setof int
as
$$
begin
return query
with resulting_rows as
(
insert into z(question_text) values
('hello'),
('你好'),
('hola')
returning id
),
generate_question as
(
insert into q_factory(q_id, some_text)
select id, q.another
from resulting_rows
cross join unnest(array[
'answer to life and everything',
'are multiple and awesome'
]) as q(another)
)
select id from resulting_rows;
end;
$$ language 'plpgsql';
即使在查询中两次引用了result_rows,也不会运行两次。仍然是3行:
测试:
select * from insert_multiple_test() as x(the_id);
输出: