Markieren Sie alle vorhandenen Zeilen als alt:
ALTER TABLE integrations.billables
ADD COLUMN is_old BOOLEAN NOT NULL DEFAULT false;
UPDATE integrations.billables SET is_old = true;
Und richten Sie die Einschränkung so ein, dass alte Zeilen ignoriert werden:
ALTER TABLE integrations.billables
ADD CONSTRAINT cc_at_least_one_mapping_needed_billables
CHECK (
NOT(("qb_id", "xero_id", "freshbooks_id", "unleashed_id", "csv_data", "myob_id") IS NULL)
OR is_old
);
(Ja, diese IS NULL
Prüfung funktioniert. Siehe hier .)
Vorteile dieses Mechanismus:
- Die Einschränkung bleibt gültig
- Sie können alte Zeilen weiterhin aktualisieren, ohne diesen Wert einzugeben
Nachteile:
- Eine ähnliche Situation auf der Straße wird chaotisch sein. Sie müssten eine zweite
boolean
Spalte oder einen anderen Reifensprung für die zweite neue Spalte hinzufügen .
- Wenn Sie erzwingen möchten , dass aktualisierten Zeilen ein Wert zugewiesen wird, ist dies nicht der Fall.
- Dies kann zu Missbrauch führen, da jemand einfach die
is_old
Flagge umdrehen könnte true
. (Dies kann jedoch behoben werden. Siehe unten.) Dies ist kein Grund zur Sorge, wenn Endbenutzer nicht direkt auf die Datenbank zugreifen können und Sie darauf vertrauen können, dass die Entwickler keine verrückten Dinge mit den Daten tun.
Wenn Sie sich über jemanden Änderung der Flagge besorgt, könnten Sie einen Trigger einrichten, um alle Einsätze oder Updates zu verhindern Einstellung is_old
zu true
:
CREATE FUNCTION throw_error_on_illegal_old()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW.is_old THEN
-- Need to make sure we don't try to access
-- OLD in an INSERT
IF TG_OP = 'INSERT' THEN
RAISE 'Cannot create new with is_old = true';
ELSE
IF NOT OLD.is_old THEN
RAISE 'Cannot change is_old from false to true';
END IF;
END IF;
END IF;
-- If we get here, all tests passed
RETURN NEW;
END
$$
;
CREATE TRIGGER billables_prohibit_marking_row_old
BEFORE INSERT OR UPDATE ON integrations.billables
FOR EACH ROW EXECUTE PROCEDURE throw_error_on_illegal_old()
;
Sie müssen immer noch darauf vertrauen, dass niemand, der das Datenbankschema ändern kann, Ihren Trigger oder etwas anderes fallen lässt, aber wenn er das tut, kann er auch die Einschränkung fallen lassen.
Hier ist eine SQLFiddle-Demo . Beachten Sie, dass die Zeile "sollte überspringen" nicht in der Ausgabe enthalten ist (wie gewünscht).