So, let me start with saying that I’m a complete Noob when it comes to SQL.
Ive Got two tables within a Schema: Attributes and Skills.
I wanted to automatically add the Skills for Each Attribute, since I already got all their Names in the "Modifies" column of the Attributes table, and well, also their Attribute.
The Code for The Function is the Following:
CREATE OR REPLACE FUNCTION AddSkFromList(p_Attr "Cyberpunk2020"."Attr", p_SkList text[]) RETURNS void AS $$
DECLARE
v_SkName text;
BEGIN
FOREACH v_SkName IN p_SkList LOOP
INSERT INTO "Cyberpunk2020"."Skills" ("Attribute", "Name")
VALUES (p_Attr, v_SkName);
END LOOP;
END;
$$ LANGUAGE plpgsql;
Which gives me the Syntax Error:
ERROR: syntax error at or near "p_SkList"
LINE 5: FOREACH v_SkName IN p_SkList LOOP
^
I sadly am unable to figure out why this function doesn’t work, according to the Postgres Docs the FOREACH statement requires a target and an Expression, in all Examples I’ve found the target got Declared in the Declare Block [Duh], and the Expression can be any kind of Array. I’ve tried setting the p_SkList parameter to just text, but the error is the same. Do I fundamentally misunderstand something about Postgres and the array to loop over has to be predefined? I also set the search_path to the corrosponding Shema, in which I Want to create the Function, which is the same one that houses the Tables, and as you can see below, I’m able to access the tables with a simple d+ $shema_name
The Attributes Table looks Like the Following:
Table "Cyberpunk2020.Attributes"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
----------+--------+-----------+----------+---------+----------+--------------+-------------
Attr | "Attr" | | not null | | plain | |
name | text | | | | extended | |
Modifies | text[] | | | | extended | |
Indexes:
"Attributes_pkey" PRIMARY KEY, btree ("Attr")
Child tables: public."Attributes"
Access method: heap
The Skills Table Like This:
d+ "Skills"
Table "Cyberpunk2020.Skills"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------------+--------+-----------+----------+---------+----------+--------------+-------------
Attribute | "Attr" | | not null | | plain | |
Name | text | | not null | | extended | |
Desciption | text | | | | extended | |
IPMultiplier | bigint | | | 1 | plain | |
Modifies | text[] | | | | extended | |
Indexes:
"Skills_pkey" PRIMARY KEY, btree ("Attribute", "Name")
Child tables: public."Skills"
Access method: heap
Postgres version
version
---------------------------------------------------------------------------------------------------------------------------
PostgreSQL 13.9 (Debian 13.9-0+deb11u1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
(1 row)
Thanks in Advance for all pointers in the right direction, as I am thoroughly confused.
I am expecting the Function to loop over the given text array p_SkList
and insert the found names with the corrosponding Attribute as a new Row into "Skills"
2
Answers
That's all that was wrong, thank you very much, i feel pretty blind now ^^
This Code works:
Something like this should work, using UNNEST() to get all items from the array. This avoids the loop and you don’t need plpgsql either: