PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Fügen Sie eine Einschränkung hinzu, um die Spalte pro Zeilengruppe eindeutig zu machen

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.

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:

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.