0

In PostgreSQL database I have table which looks like this:

| question_id | question_text | widget | required | position |
|-------------|---------------|--------|----------|----------|
| int         | text          | int    | boolean  | int      |

Second table which called factors_questions_relationship looks like this:

| factor_id   | question_id   |
|-------------|---------------|
| int         | text          |

I am trying to create function which would create multiple rows and return array of ids of new created entries. How correctly to make such function?

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;

1 Answer 1

2

You can simply unnest them in columns

select 
     unnest(array['quick','brown','fox']) as question_text, 
     unnest(array[1,2,3]) as widget_id

enter image description here

Whereas putting them in FROM clause, would result to cartesian product:

select question_text, widget_id
from 
unnest(array['quick','brown','fox']) as question_text, 
unnest(array[1,2,3]) as widget_id

Output:

enter image description here

To obtain the Ids generated from newly-inserted records, use return query + returning id combo. Sample test:

create table z
(
    id int generated by default as identity primary key, 
    question_text text
);

create or replace function insert_multiple_test()
returns table (someid int) as
$$
begin
    return query
    with resulting_rows as
    (
        insert into z(question_text) values
        ('hello'),
        ('你好'),
        ('hola')
        returning id
    )
    select id from resulting_rows;
end;
$$ language 'plpgsql';


select * from insert_multiple_test();

Output:

enter image description here

Here's for SETOF:

create table z(id int generated by default as identity primary key, question_text text);

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
    )
    select id from resulting_rows;
end;
$$ language 'plpgsql';


select x.the_id from insert_multiple_test() as x(the_id);

Output:

enter image description here

If you don't need to run multiple queries, you can just use LANGUAGE 'sql', it's simpler:

create table z
(
    id int generated by default as identity primary key, 
    question_text text
);

create or replace function insert_multiple_test()
returns setof int as
$$
    insert into z(question_text) values
    ('hello'),
    ('你好'),
    ('hola')
    returning id;
$$ language 'sql';


select x.id_here from insert_multiple_test() as x(id_here);

Output:

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

Hello! Thank you for detailed answer. Can I ask you one more question?! Inside function I am trying to use array of questions ids in insert statement to second table. Can you check my post again please?! What can you recommend to do?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.