PostgreSQL: più di una riga restituita da una sottoquery utilizzata come espressione
Ho una main.comments
tabella in cui memorizzo i commenti degli utenti. Sto cercando di aggiungere un commento al database e ottenere alcuni dati come ritorno. Ecco la mia domanda
INSERT INTO main.comments (text, post_id, user_id)
VALUES('sample', 11, 1)
RETURNING
comment_id,
text,
post_id,
(SELECT username FROM main.users WHERE main.users.user_id = user_id) AS username,
created_at,
updated_at
Quindi mi aspettavo di aggiungere un commento e ottenere i dati che volevo, ma non era così, invece ho ricevuto questo errore
ERRORE: più di una riga restituita da una sottoquery utilizzata come espressione Stato SQL: 21000
Pensavo di avere un problema con la sottoquery, quindi l'ho usata individualmente e ho ottenuto solo una riga in cambio. Quindi ho usato LIMIT 1
all'interno della sottoquery e ho ottenuto il risultato che mi aspettavo, ma non ha senso nella mia query. Qualcuno può spiegare questo comportamento? E anche la mia main.users
tabella non contiene alcun user_id
duplicato poiché sto usando il SERIAL
tipo.
- PostgreSQL 12.4
Risposte
Il vero colpevole è questa riga nel tuo codice
(SELECT username FROM main.users WHERE main.users.user_id = user_id)
Prova così:
INSERT INTO comments (text, post_id, user_id)
VALUES('sample', 11, 1)
RETURNING
comment_id,
text,
post_id,
(SELECT username FROM users t1 WHERE t1.user_id = comments.user_id) AS username,
created_at,
updated_at
DEMO:
I have removed the schema name for clarity
Il problema è che il user_id
nella tua sottoquery non si riferisce alla riga appena inserita in main.comments
, ma a main.users
, quindi la condizione diventa e vengono restituite TRUE
tutte le righe da .users
Userei un CTE in questo modo:
WITH ins AS (
INSERT INTO main.comments (text, post_id, user_id)
VALUES('sample', 11, 1)
RETURNING
comment_id,
text,
post_id,
user_id,
created_at,
updated_at
)
SELECT ins.comment_id,
ins.text,
ins.post_id,
u.username,
ins.created_at,
ins.updated_at
FROM ins
JOIN main.users AS u ON ins.user_id = u.user_id;
potresti prima inserire valori vuoti
INSERT INTO main.comments (text, post_id, user_id)
VALUES('sample', 11, 1)
RETURNING
comment_id,
text,
post_id,
NULL AS username,
created_at,
updated_at;
quindi aggiorna la tua tabella
UPDATE main.comment
SET username = (SELECT username )
FROM main.users
WHERE main.users.user_id = main.comment.user_id;
non ha testato ma dovrebbe funzionare