Function inserting multiple rows in a table
So I have the following tables.
G
__________________________
id_musician | id_album
--------------------------
1 | 51
3 | 52
2 | 53
3 | 54
1 | 55
3 | 56
C
__________________________
id_album | year
--------------------------
51 | 1990
52 | 2001
53 | 1990
54 | 2001
55 | 1945
56 | 1945
I've created the following function:
CREATE OR REPLACE FUNCTION test2 (year1 INTEGER, p_type VARCHAR(1))
RETURNS SETOF test2 AS $$
DECLARE
output test2;
BEGIN
IF p_type='S' THEN
FOR output IN SELECT g.id_artist, c.year, COUNT(c.id_album) AS albums
FROM G g, C c
WHERE g.id_album = c.id_album AND
c.year = year1
GROUP BY c.year, g.id_musician
LOOP
RETURN NEXT output;
END LOOP;
END IF
RETURN;
END;
$$LANGUAGE plpgsql;
test2 is a type of output I created:
CREATE TYPE test2 AS(
id smallint,
year smallint,
total_albums integer)
The function accepts a year and type of perfomer. It returns, for every year and performer (in this case Guitarist, 'G'), the amount of records a performer has participated in every year.
What I would like is for the function to insert that output into a table I've created, instead of just showing the output:
CREATE TABLE TEST2_TABLE (
id smallint,
year smallint,
total_albums integer );
postgresql postgresql-9.1 postgresql-9.2 postgresql-9.5
add a comment |
So I have the following tables.
G
__________________________
id_musician | id_album
--------------------------
1 | 51
3 | 52
2 | 53
3 | 54
1 | 55
3 | 56
C
__________________________
id_album | year
--------------------------
51 | 1990
52 | 2001
53 | 1990
54 | 2001
55 | 1945
56 | 1945
I've created the following function:
CREATE OR REPLACE FUNCTION test2 (year1 INTEGER, p_type VARCHAR(1))
RETURNS SETOF test2 AS $$
DECLARE
output test2;
BEGIN
IF p_type='S' THEN
FOR output IN SELECT g.id_artist, c.year, COUNT(c.id_album) AS albums
FROM G g, C c
WHERE g.id_album = c.id_album AND
c.year = year1
GROUP BY c.year, g.id_musician
LOOP
RETURN NEXT output;
END LOOP;
END IF
RETURN;
END;
$$LANGUAGE plpgsql;
test2 is a type of output I created:
CREATE TYPE test2 AS(
id smallint,
year smallint,
total_albums integer)
The function accepts a year and type of perfomer. It returns, for every year and performer (in this case Guitarist, 'G'), the amount of records a performer has participated in every year.
What I would like is for the function to insert that output into a table I've created, instead of just showing the output:
CREATE TABLE TEST2_TABLE (
id smallint,
year smallint,
total_albums integer );
postgresql postgresql-9.1 postgresql-9.2 postgresql-9.5
"insert that output into a table I've created", you haven't shown us the table, instead you reposted the type definition. Then do you want it to to both write that output to the table and return it, or just write it?
– 404
Nov 24 '18 at 14:15
Sorry, that was a mistake, I've corrected it now. The table is empty, ideally it would return the type and insert it in the table TEST2_TABLE. However, if that's not possible I'd settle for just the function filling the table
– Sergio
Nov 24 '18 at 15:03
add a comment |
So I have the following tables.
G
__________________________
id_musician | id_album
--------------------------
1 | 51
3 | 52
2 | 53
3 | 54
1 | 55
3 | 56
C
__________________________
id_album | year
--------------------------
51 | 1990
52 | 2001
53 | 1990
54 | 2001
55 | 1945
56 | 1945
I've created the following function:
CREATE OR REPLACE FUNCTION test2 (year1 INTEGER, p_type VARCHAR(1))
RETURNS SETOF test2 AS $$
DECLARE
output test2;
BEGIN
IF p_type='S' THEN
FOR output IN SELECT g.id_artist, c.year, COUNT(c.id_album) AS albums
FROM G g, C c
WHERE g.id_album = c.id_album AND
c.year = year1
GROUP BY c.year, g.id_musician
LOOP
RETURN NEXT output;
END LOOP;
END IF
RETURN;
END;
$$LANGUAGE plpgsql;
test2 is a type of output I created:
CREATE TYPE test2 AS(
id smallint,
year smallint,
total_albums integer)
The function accepts a year and type of perfomer. It returns, for every year and performer (in this case Guitarist, 'G'), the amount of records a performer has participated in every year.
What I would like is for the function to insert that output into a table I've created, instead of just showing the output:
CREATE TABLE TEST2_TABLE (
id smallint,
year smallint,
total_albums integer );
postgresql postgresql-9.1 postgresql-9.2 postgresql-9.5
So I have the following tables.
G
__________________________
id_musician | id_album
--------------------------
1 | 51
3 | 52
2 | 53
3 | 54
1 | 55
3 | 56
C
__________________________
id_album | year
--------------------------
51 | 1990
52 | 2001
53 | 1990
54 | 2001
55 | 1945
56 | 1945
I've created the following function:
CREATE OR REPLACE FUNCTION test2 (year1 INTEGER, p_type VARCHAR(1))
RETURNS SETOF test2 AS $$
DECLARE
output test2;
BEGIN
IF p_type='S' THEN
FOR output IN SELECT g.id_artist, c.year, COUNT(c.id_album) AS albums
FROM G g, C c
WHERE g.id_album = c.id_album AND
c.year = year1
GROUP BY c.year, g.id_musician
LOOP
RETURN NEXT output;
END LOOP;
END IF
RETURN;
END;
$$LANGUAGE plpgsql;
test2 is a type of output I created:
CREATE TYPE test2 AS(
id smallint,
year smallint,
total_albums integer)
The function accepts a year and type of perfomer. It returns, for every year and performer (in this case Guitarist, 'G'), the amount of records a performer has participated in every year.
What I would like is for the function to insert that output into a table I've created, instead of just showing the output:
CREATE TABLE TEST2_TABLE (
id smallint,
year smallint,
total_albums integer );
postgresql postgresql-9.1 postgresql-9.2 postgresql-9.5
postgresql postgresql-9.1 postgresql-9.2 postgresql-9.5
edited Nov 24 '18 at 15:02
Sergio
asked Nov 24 '18 at 13:13
SergioSergio
214
214
"insert that output into a table I've created", you haven't shown us the table, instead you reposted the type definition. Then do you want it to to both write that output to the table and return it, or just write it?
– 404
Nov 24 '18 at 14:15
Sorry, that was a mistake, I've corrected it now. The table is empty, ideally it would return the type and insert it in the table TEST2_TABLE. However, if that's not possible I'd settle for just the function filling the table
– Sergio
Nov 24 '18 at 15:03
add a comment |
"insert that output into a table I've created", you haven't shown us the table, instead you reposted the type definition. Then do you want it to to both write that output to the table and return it, or just write it?
– 404
Nov 24 '18 at 14:15
Sorry, that was a mistake, I've corrected it now. The table is empty, ideally it would return the type and insert it in the table TEST2_TABLE. However, if that's not possible I'd settle for just the function filling the table
– Sergio
Nov 24 '18 at 15:03
"insert that output into a table I've created", you haven't shown us the table, instead you reposted the type definition. Then do you want it to to both write that output to the table and return it, or just write it?
– 404
Nov 24 '18 at 14:15
"insert that output into a table I've created", you haven't shown us the table, instead you reposted the type definition. Then do you want it to to both write that output to the table and return it, or just write it?
– 404
Nov 24 '18 at 14:15
Sorry, that was a mistake, I've corrected it now. The table is empty, ideally it would return the type and insert it in the table TEST2_TABLE. However, if that's not possible I'd settle for just the function filling the table
– Sergio
Nov 24 '18 at 15:03
Sorry, that was a mistake, I've corrected it now. The table is empty, ideally it would return the type and insert it in the table TEST2_TABLE. However, if that's not possible I'd settle for just the function filling the table
– Sergio
Nov 24 '18 at 15:03
add a comment |
1 Answer
1
active
oldest
votes
Here's the function:
CREATE OR REPLACE FUNCTION test2 (year1 INTEGER, p_type VARCHAR(1))
RETURNS SETOF test2 AS
$BODY$
BEGIN
IF p_type='S' THEN
RETURN QUERY (
WITH inserted AS (
INSERT INTO test2_table
SELECT g.id_musician, c.year, COUNT(c.id_album)::INTEGER AS albums
FROM g, c
WHERE g.id_album = c.id_album
AND c.year = year1
GROUP BY c.year, g.id_musician
RETURNING *
)
SELECT *
FROM inserted
);
ELSE
RETURN;
END IF;
END
$BODY$
LANGUAGE plpgsql;
So the signature and output is the same as your original function. Main differences are:
- No need to use a loop and read/return one row at a time. You can return the result of your query directly. Much faster like that.
- To accomplish both inserting into a table and returning the same results, it uses a CTE which inserts the data in the table and returns everything that was inserted, then selects from that CTE as the return output.
I've also removed the aliases. Any identifier in postgres is lowercase, unless in double quotes. Since G
and C
were not in quotes, the table names are actually g
and c
, respectively. So I just used the actual lowercase table names.
thanks for your help, it works great!
– Sergio
Nov 24 '18 at 15:42
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53458510%2ffunction-inserting-multiple-rows-in-a-table%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Here's the function:
CREATE OR REPLACE FUNCTION test2 (year1 INTEGER, p_type VARCHAR(1))
RETURNS SETOF test2 AS
$BODY$
BEGIN
IF p_type='S' THEN
RETURN QUERY (
WITH inserted AS (
INSERT INTO test2_table
SELECT g.id_musician, c.year, COUNT(c.id_album)::INTEGER AS albums
FROM g, c
WHERE g.id_album = c.id_album
AND c.year = year1
GROUP BY c.year, g.id_musician
RETURNING *
)
SELECT *
FROM inserted
);
ELSE
RETURN;
END IF;
END
$BODY$
LANGUAGE plpgsql;
So the signature and output is the same as your original function. Main differences are:
- No need to use a loop and read/return one row at a time. You can return the result of your query directly. Much faster like that.
- To accomplish both inserting into a table and returning the same results, it uses a CTE which inserts the data in the table and returns everything that was inserted, then selects from that CTE as the return output.
I've also removed the aliases. Any identifier in postgres is lowercase, unless in double quotes. Since G
and C
were not in quotes, the table names are actually g
and c
, respectively. So I just used the actual lowercase table names.
thanks for your help, it works great!
– Sergio
Nov 24 '18 at 15:42
add a comment |
Here's the function:
CREATE OR REPLACE FUNCTION test2 (year1 INTEGER, p_type VARCHAR(1))
RETURNS SETOF test2 AS
$BODY$
BEGIN
IF p_type='S' THEN
RETURN QUERY (
WITH inserted AS (
INSERT INTO test2_table
SELECT g.id_musician, c.year, COUNT(c.id_album)::INTEGER AS albums
FROM g, c
WHERE g.id_album = c.id_album
AND c.year = year1
GROUP BY c.year, g.id_musician
RETURNING *
)
SELECT *
FROM inserted
);
ELSE
RETURN;
END IF;
END
$BODY$
LANGUAGE plpgsql;
So the signature and output is the same as your original function. Main differences are:
- No need to use a loop and read/return one row at a time. You can return the result of your query directly. Much faster like that.
- To accomplish both inserting into a table and returning the same results, it uses a CTE which inserts the data in the table and returns everything that was inserted, then selects from that CTE as the return output.
I've also removed the aliases. Any identifier in postgres is lowercase, unless in double quotes. Since G
and C
were not in quotes, the table names are actually g
and c
, respectively. So I just used the actual lowercase table names.
thanks for your help, it works great!
– Sergio
Nov 24 '18 at 15:42
add a comment |
Here's the function:
CREATE OR REPLACE FUNCTION test2 (year1 INTEGER, p_type VARCHAR(1))
RETURNS SETOF test2 AS
$BODY$
BEGIN
IF p_type='S' THEN
RETURN QUERY (
WITH inserted AS (
INSERT INTO test2_table
SELECT g.id_musician, c.year, COUNT(c.id_album)::INTEGER AS albums
FROM g, c
WHERE g.id_album = c.id_album
AND c.year = year1
GROUP BY c.year, g.id_musician
RETURNING *
)
SELECT *
FROM inserted
);
ELSE
RETURN;
END IF;
END
$BODY$
LANGUAGE plpgsql;
So the signature and output is the same as your original function. Main differences are:
- No need to use a loop and read/return one row at a time. You can return the result of your query directly. Much faster like that.
- To accomplish both inserting into a table and returning the same results, it uses a CTE which inserts the data in the table and returns everything that was inserted, then selects from that CTE as the return output.
I've also removed the aliases. Any identifier in postgres is lowercase, unless in double quotes. Since G
and C
were not in quotes, the table names are actually g
and c
, respectively. So I just used the actual lowercase table names.
Here's the function:
CREATE OR REPLACE FUNCTION test2 (year1 INTEGER, p_type VARCHAR(1))
RETURNS SETOF test2 AS
$BODY$
BEGIN
IF p_type='S' THEN
RETURN QUERY (
WITH inserted AS (
INSERT INTO test2_table
SELECT g.id_musician, c.year, COUNT(c.id_album)::INTEGER AS albums
FROM g, c
WHERE g.id_album = c.id_album
AND c.year = year1
GROUP BY c.year, g.id_musician
RETURNING *
)
SELECT *
FROM inserted
);
ELSE
RETURN;
END IF;
END
$BODY$
LANGUAGE plpgsql;
So the signature and output is the same as your original function. Main differences are:
- No need to use a loop and read/return one row at a time. You can return the result of your query directly. Much faster like that.
- To accomplish both inserting into a table and returning the same results, it uses a CTE which inserts the data in the table and returns everything that was inserted, then selects from that CTE as the return output.
I've also removed the aliases. Any identifier in postgres is lowercase, unless in double quotes. Since G
and C
were not in quotes, the table names are actually g
and c
, respectively. So I just used the actual lowercase table names.
answered Nov 24 '18 at 15:21
404404
3,1401726
3,1401726
thanks for your help, it works great!
– Sergio
Nov 24 '18 at 15:42
add a comment |
thanks for your help, it works great!
– Sergio
Nov 24 '18 at 15:42
thanks for your help, it works great!
– Sergio
Nov 24 '18 at 15:42
thanks for your help, it works great!
– Sergio
Nov 24 '18 at 15:42
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53458510%2ffunction-inserting-multiple-rows-in-a-table%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
"insert that output into a table I've created", you haven't shown us the table, instead you reposted the type definition. Then do you want it to to both write that output to the table and return it, or just write it?
– 404
Nov 24 '18 at 14:15
Sorry, that was a mistake, I've corrected it now. The table is empty, ideally it would return the type and insert it in the table TEST2_TABLE. However, if that's not possible I'd settle for just the function filling the table
– Sergio
Nov 24 '18 at 15:03