2016-05-26 14 views
2

Ich habe eine Einstellung wie dieseSQL UPDATE mit automatischer INSERT

CREATE TABLE Mother (
    id SERIAL PRIMARY KEY 
); 

CREATE TABLE Kitten (
    id SERIAL PRIMARY KEY AUTO_INCREMENT, 
    mother_id INTEGER NULL REFERENCES Mother 
); 

Die Kitten Tabelle gefüllt ist, und einige von ihnen auf eine Mutter einen Verweis haben aber einige haben nicht. Die Tabellen können wie folgt aussehen:

== Mother == 
| 1 | 
| 2 | 

== Kitten == 
| 1 | NULL | 
| 2 | 1 | 
| 3 | NULL | 
| 4 | 2 | 
| 5 | 1 | 
| 6 | NULL | 

Now (aufgrund einiger Anforderungsänderungen) jedes Kätzchen eine Mutter haben muss, die gerade erstellt werden soll. Ich habe folgendes versucht: funktioniert nicht.

UPDATE Kitten 
SET mother_id = (
    INSERT INTO Mother DEFAULT VALUES RETURNING id 
) 
WHERE mother_id IS NULL; 

Fehler ist

Fehler in der SQL-Abfrage: ERROR: syntax error at or near "INTO" 
LINE 3: INSERT INTO Mother DEFAULT VALUES RETURNING id 

Mit PosgreSQL 9.3.5

Auto-Erhöhungs-Kommentar: Die Kombination von "serial" und "Primärschlüssel" ermöglicht Autoinkrement standardmäßig

Hier ist die SQL-Snipped, um den beschriebenen Datenbankstatus zu erstellen:

drop table if exists Kitten; 
drop table if exists Mother; 

CREATE TABLE Mother (
    id SERIAL PRIMARY KEY 
); 

CREATE TABLE Kitten (
    id SERIAL PRIMARY KEY, 
    mother_id INTEGER NULL REFERENCES Mother 
); 

insert into Mother default values; 
insert into Mother default values; 

insert into Kitten (mother_id) values (NULL); 
insert into Kitten (mother_id) values (1); 
insert into Kitten (mother_id) values (NULL); 
insert into Kitten (mother_id) values (2); 
INSERT INTO Kitten (mother_id) VALUES (1); 
INSERT INTO Kitten (mother_id) VALUES (NULL); 
+0

Möchten Sie eine neue Mutter für ** jedes ** Kätzchen erstellen, das keine hat? (also 2 neue Mütter basierend auf Ihren Probendaten), oder ** nur eine Mutter, die für beide verwaisten Kätzchen verwendet wird (was die Syntax, die Sie versucht haben zu verwenden, vorschlagen würde) –

+0

ja für jedes Kätzchen eine neue Mutter – Marcel

Antwort

1

Wenn Sie eine Mutter pro Waise Kätzchen benötigen, können Sie folgendes tun:

with 
    orphans as (-- find the orphans and record their ids, ordered 
    select id, row_number() over() 
    from kitten 
    where mother_id is null 
    ), 
    newmothers as (-- insert as many new mothers as needed, return new ids 
    insert into mother 
    select nextval('mother_id_seq') 
    from orphans 
    returning id 
    ), 
    newmothers2 as (-- add row number for all new mother ids 
    select *, row_number() over() 
    from newmothers 
    ) 
update kitten k set 
    mother_id = m.id 
from orphans o 
join newmothers2 m using (row_number) -- join orphans with new mothers 
where o.id = k.id 
+0

Ich bekomme: FEHLER: Syntaxfehler bei oder in der Nähe von "" LINE 9: Wählen Sie aus Waisen ... Ich habe eine SQL-Snipped hinzugefügt, um meine Datenbank zu reproduzieren – Marcel

+0

@Marcel Ich habe das Skript ersetzt 'motherid' mit' mother_id'. Es funktioniert in meinem PostgreSQL 9.5, ich werde überprüfen, ob irgendein Teil des Codes mit 9.3 unvereinbar ist. –

+1

@ZiggyCrueltyfreeZeitgeister pg-9.3 scheint nicht die leeren Listen in "in Mutter einfügen von Waisen auszuwählen" – joop

0

ich eine reine SQL-Lösung gefunden, die für mich funktioniert. Es verwendet eine temporäre Spalte auf der Mutterseite.

-- prepare situation (same like in the question) 
DROP TABLE IF EXISTS Kitten; DROP TABLE IF EXISTS Mother; 
CREATE TABLE Mother (id SERIAL PRIMARY KEY); 
CREATE TABLE Kitten (id SERIAL PRIMARY KEY,mother_id INTEGER NULL REFERENCES Mother); 
INSERT INTO Mother DEFAULT VALUES;INSERT INTO Mother DEFAULT VALUES; 
INSERT INTO Kitten (mother_id) VALUES (NULL);INSERT INTO Kitten (mother_id) VALUES (1);INSERT INTO Kitten (mother_id) VALUES (NULL);INSERT INTO Kitten (mother_id) VALUES (2);INSERT INTO Kitten (mother_id) VALUES (1);INSERT INTO Kitten (mother_id) VALUES (NULL); 

-- create temporarily "bidirectionality" 
-- by creating a reference from mother to kitten 
ALTER TABLE mother ADD kitten_id INTEGER; 

-- create new Mothers for motherless kittens with reference to this kitten 
INSERT INTO mother (kitten_id) 
    (SELECT id FROM kitten WHERE mother_id IS NULL); 

-- update kittens 
UPDATE kitten SET mother_id = 
    (SELECT id FROM mother WHERE mother.kitten_id = kitten.id) 
WHERE mother_id IS NULL; 

-- remove temporary column 
ALTER TABLE mother DROP kitten_id; 

-- make sure this never happens again 
ALTER TABLE kitten ALTER mother_id SET NOT NULL; 

-- show results 
SELECT kitten.id AS Kitten_Id , mother.id AS Mother_Id FROM kitten, mother WHERE kitten.mother_id = mother.id ORDER BY Kitten_id