Wie @lad2025 kommentiert , status
sollte eigentlich boolean
sein
. Billiger, sauberer.
In jedem Fall können Sie Ihre Regel mit einem teilweise eindeutigen Index
Um null oder eine Zeile mit status = 'Active'
zuzulassen in der ganzen Tabelle :
CREATE UNIQUE INDEX tbl_active_uni ON tbl (status)
WHERE status = 'Active';
Um null oder eine Zeile mit status = 'Active'
zuzulassen pro userid
, erstellen Sie userid
die indizierte Spalte:
CREATE UNIQUE INDEX tbl_userid_active_uni ON tbl (userid)
WHERE status = 'Active';
Beachten Sie, dass userid IS NULL
ist würde keine eindeutigen Verletzungen auslösen, da zwei NULL-Werte niemals als gleich angesehen werden. userid
muss gesetzt werden NOT NULL
in diesem Fall.
- So fügen Sie einen bedingten eindeutigen Index in PostgreSQL hinzu
- Eindeutige Einschränkung mit Nullspalten erstellen
Warum indexieren und nicht einschränken?
Umgang mit Ihrem Frage im Kommentar
:Dies ist ein Index, kein CONSTRAINT
.
Der Index für den ersten Fall ist winzig , die eine oder keine Zeile enthält.
Der Index für den zweiten Fall enthält eine Zeile pro vorhandener userid
, aber es ist der billigste und schnellste Weg , zusätzlich zu sauber und sicher. Sie würden auf jeden Fall einen Index benötigen, um andere Zeilen zu überprüfen, um dies schnell zu machen.
Sie können keinen CHECK
haben Einschränkungsprüfung für andere Zeilen - zumindest nicht auf saubere, zuverlässige Weise. Es gibt Möglichkeiten, die ich sicherlich nicht empfehlen würde für diesen Fall:
- Einschränkung auslösen vs. prüfen
- Wie vermeide ich eine zyklische Abhängigkeit (zirkuläre Referenz) zwischen 3 Tabellen?
- Deaktivieren Sie alle Beschränkungen und Tabellenprüfungen beim Wiederherstellen eines Dumps
Wenn Sie einen UNIQUE
verwenden Beschränkung auf (userid, status)
(der ebenfalls mit einem eindeutigen Index im Hintergrund implementiert ist!), können Sie ihn nicht teilweise machen , und alle Kombinationen werden als eindeutig erzwungen. Sie könnten Verwenden Sie dies trotzdem, wenn Sie mit status IS NULL
arbeiten für alle Fälle außer 'Active'
Fall. Aber das würde tatsächlich einen viel größeren Index einschließlich all erfordern Zeilen.