how do I insert the std_id value and sub_id value in the student_subject table
insert into student_subjects(student_id,subject_id)
values(std_id,(select id from subjects
where guid in
(select * from
unnest(string_to_array(subjects_colls,',')::uuid[])))::int);
ERROR: more than one row returned by a subquery used as an expression
Get rid of the values clause and use the SELECT directly as the source for the INSERT statement:
You also don't need to unnest your array, using = any() will be a bit more efficient (although I would recommend you do not pass comma separated strings, but an array of uuid directly)
insert into student_subjects(student_id,subject_id)
select std_id, s.id
from subjects s
where guid = any(string_to_array(subjects_colls,',')::uuid[])
I assume this is part of a procedure or function and std_id and subjects_colls are parameters passed to it.
Related
I'm still having trouble understanding how CTE works.
I'm looking to make an insert. In case of conflict I use the on conflict do nothing but I want it to return the id to me (for the success of the insert or the conflict)
WITH inserted AS (
INSERT INTO fiche(label)
VALUES ('label')
ON CONFLICT (label) DO NOTHING
RETURNING *
)
SELECT * FROM inserted
WHERE NOT EXISTS (SELECT 1 FROM inserted);
Note that
SELECT * FROM some_relation
WHERE NOT EXISTS (SELECT 1 FROM some_relation);
will always give you an empty result. Either some_relation is empty itself or if it is not empty SELECT 1 FROM some_relation is not empty and therefore NOT EXISTS ... always returns false and so no record is matching the WHERE clause.
What you want is to have the VALUES as a CTE. You can then reference the values from your INSERT statement and in a SELECT to compare those values to the result of the RETURNING clause.
WITH
vals AS (
VALUES ('label')
),
inserted AS (
INSERT INTO fiche(label)
SELECT * FROM vals
ON CONFLICT (label) DO NOTHING
RETURNING label, id
)
SELECT
vals.column1,
inserted.id
FROM vals
LEFT JOIN inserted ON vals.column1 = inserted.label
This should give you a row for each row in your VALUES clause and the second column will be NULL if it was not inserted due to a conflict or the inserted ID otherwise.
I am new to PostgreSQL and trying to convert mssql scripts to Postgres.
For Merge statement, we can use insert on conflict update or do nothing but am using the below statement, not sure whether it is the correct way.
MSSQL code:
Declare #tab2(New_Id int not null, Old_Id int not null)
MERGE Tab1 as Target
USING (select * from Tab1
WHERE ColumnId = #ID) as Source on 0 = 1
when not matched by Target then
INSERT
(ColumnId
,Col1
,Col2
,Col3
)
VALUES (Source.ColumnId
,Source.Col1
,Source.Col2
,Source.Col3
)
OUTPUT INSERTED.Id, Source.Id into #tab2(New_Id, Old_Id);
Postgres Code:
Create temp table tab2(New_Id int not null, Old_Id int not null)
With source as( select * from Tab1
WHERE ColumnId = ID)
Insert into Tab1(ColumnId
,Col1
,Col2
,Col3
)
select Source.ColumnId
,Source.Col1
,Source.Col2
,Source.Col3
from source
My query is how to convert OUTPUT INSERTED.Id in postgres.I need this id to insert records in another table (lets say as child tables based on Inserted values in Tab1)
In PostgreSQL's INSERT statements you can choose what the query should return. From the docs on INSERT:
The optional RETURNING clause causes INSERT to compute and return value(s) based on each row actually inserted (or updated, if an ON CONFLICT DO UPDATE clause was used). This is primarily useful for obtaining values that were supplied by defaults, such as a serial sequence number. However, any expression using the table's columns is allowed. The syntax of the RETURNING list is identical to that of the output list of SELECT. Only rows that were successfully inserted or updated will be returned.
Example (shortened form of your query):
WITH [...] INSERT INTO Tab1 ([...]) SELECT [...] FROM [...] RETURNING Tab1.id
SELECT
Q."COLUMN1"
FROM
(SELECT
"COLUMN1",
CAST ((SELECT CAST (RTRIM (PARAM) AS VARCHAR(50)) FROM TABLE_VIEW WHERE PARAM_ID = :ID) AS VARCHAR(50)) AS "COLUMN2"
FROM ("TABLE1")Q
WHERE
RTRIM(CAST("COLUMN1" AS CHAR(10))) IN (SELECT VALUE_1 FROM TABLE (SPLIT_PARAMS(CAST(Q."COLUMN2" AS VARCHAR(50)),',',5)))
COLUMN2 gets its value from a separate table based on the input provided at run time.
The filter used in the query consists of a used defined table valued function that is used to split the comma separated valued to individual values.
The query throws the error message as:
"FUNCTION NOT SUPPORTED. SQLCODE=-270, SQLSTATE=42997"
Can anyone help me find the cause of the issue.
I am having difficulty using the results from a CTE in a function. Given the following Postgres table.
CREATE TABLE directory (
id SERIAL PRIMARY KEY
, name TEXT
, parent_id INTEGER REFERENCES directory(id)
);
INSERT INTO directory (name, parent_id)
VALUES ('Root', NULL), ('D1', 1), ('D2', 2), ('D3', 3);
I have this recursive CTE that returns the descendants of a directory.
WITH RECURSIVE tree AS (
SELECT id
FROM directory
WHERE parent_id = 2
UNION ALL
SELECT directory.id
FROM directory, tree
WHERE directory.parent_id = tree.id
)
The returned values are what I expect and can be made to equal an array
SELECT (SELECT array_agg(id) FROM tree) = ARRAY[3, 4];
I can use an array to select values from the table
SELECT * FROM directory WHERE id = ANY(ARRAY[3, 4]);
However, I cannot use the results of the CTE to accomplish the same thing.
SELECT * FROM directory WHERE id = ANY(SELECT array_agg(id) FROM tree);
The resulting error indicates that there is a type mismatch.
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
However, I am unsure how to correctly accomplish this.
Use:
SELECT *
FROM directory
WHERE id = ANY(SELECT unnest(array_agg(id)) FROM tree);
See detailed explanation in this answer.
Using unnest() in a subquery is a general method for dealing with arrays:
where id = any(select unnest(some_array))
Because array_agg() and unnest() are inverse operations, the query can be as simply as:
SELECT *
FROM directory
WHERE id = ANY(SELECT id FROM tree);
I have to update a VARCHAR column of a table by concatenating values from SELECT queries from another table. I have build a query like
UPDATE url SET VALUE = (SELECT id FROM ids WHERE identifier='site')':'(SELECT id FROM cids WHERE identifier='cid')
WHERE name='SToken:CToken'
AND tokenvalue LIKE (SELECT id FROM ids WHERE identifier='site');
Here value is VARCHAR.
How should I do this?