2017-02-21 6 views
0

ich sicherstellen wollen, dass ein Arbeiter genau ein ManagerWelche geeignete Verriegelungstechnik verhindert das Einfügen von Daten? [PostgreSQL]

CREATE TABLE IF NOT EXISTS user_relationships (
    object_id SERIAL PRIMARY KEY    NOT NULL UNIQUE, 
    manager_id INT REFERENCES users (object_id) NOT NULL, 
    worker_id INT REFERENCES users (object_id) NOT NULL, 
    CHECK (manager_id != worker_id), 
    UNIQUE (manager_id, worker_id) 
); 

Ich habe Reihe von SQL-Anweisungen hat mit Read Committed Höhe der Transaktions Isolation,

BEGIN 
SELECT * FROM users WHERE id=manager_id AND acc_type="manager" FOR UPDATE; 
SELECT * FROM users WHERE id=worker_id AND acc_type="worker" FOR UPDATE; 
SELECT * FROM relationships WHERE id=worker; 
INSERT INTO relationships (m, w) VALUES (manager_id, worker_id) 
COMMIT 
  • Ich habe herausgefunden, die ersten beiden FOR UPDATE zu anderen gleichzeitige Transaktion zu verhindern s von der Änderung des Benutzerkontentyps Mitte Transaktion
  • Ich konnte nicht herausfinden, welche Art von "Trick" für dritte Abfrage verwenden. Die dritte Abfrage sollte eine leere Liste zurückgeben, um sicherzustellen, dass der Mitarbeiter noch keinem Manager gehört hat.
  • Dritte Abfrage FOR UPDATE funktioniert nicht, weil ich eine leere Zeile erwarte.
  • Aufgrund der dritten Abfrage laufe ich das Risiko der gleichzeitigen Transaktion doppelte Arbeiter zu verschiedenen Managern hinzufügen.

Was kann ich tun, um einen Mitarbeiter für einen Manager zu erzwingen?

+0

@VaoTsun '(1,2)' und '(2,2)' würde als nicht eindeutig, aber die Worker 2 würde zwei Manager haben, was Zanko versucht zu verhindern, dass es jetzt –

+0

IC ist. Wenn diese object_id nicht da wäre, würden unique (manager_id) und unique (worker_id) den Trick machen? –

Antwort

2

Wahrscheinlich müssen Sie UNIQUE hinzufügen, um worker_id Constraint:

CREATE TABLE IF NOT EXISTS user_relationships (
    object_id SERIAL PRIMARY KEY    NOT NULL UNIQUE, 
    manager_id INT REFERENCES users (object_id) NOT NULL, 
    worker_id INT REFERENCES users (object_id) UNIQUE NOT NULL, 
    CHECK (manager_id != worker_id) 
); 

Aber besser ist Feld hinzuzufügen manager_id INT REFERENCES users (object_id) NOT NULL Tabelle users und nicht user_relationships zu verwenden.

+0

Danke! Ich habe keine so einfache Lösung gesehen! – Zanko

Verwandte Themen