Đánh dấu tất cả các hàng hiện có của bạn là cũ:
ALTER TABLE integrations.billables
ADD COLUMN is_old BOOLEAN NOT NULL DEFAULT false;
UPDATE integrations.billables SET is_old = true;
Và thiết lập các ràng buộc để bỏ qua các hàng cũ:
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
);
(Vâng, IS NULL
kiểm tra đó hoạt động. Xem ở đây .)
Ưu điểm của cơ chế này:
- Ràng buộc vẫn còn hiệu lực
- Bạn có thể tiếp tục cập nhật các hàng cũ mà không cần điền giá trị này
Nhược điểm:
- Một tình huống tương tự xuống đường sẽ lộn xộn. Bạn sẽ phải thêm một
boolean
cột thứ hai hoặc một số bước nhảy khác cho cột mới thứ hai.
- Nếu bạn muốn buộc các hàng cập nhật được cung cấp một giá trị, điều này sẽ không làm điều đó.
- Điều này có khả năng lạm dụng, vì ai đó chỉ có thể lật
is_old
cờ đến true
. (Tuy nhiên, điều này có thể được giải quyết. Xem bên dưới.) Đây không phải là điều đáng quan tâm nếu người dùng cuối không thể truy cập trực tiếp vào cơ sở dữ liệu và bạn có thể tin tưởng các nhà phát triển không làm những điều kỳ quặc với dữ liệu.
Nếu bạn đang lo lắng về ai đó thay đổi lá cờ, bạn có thể thiết lập kích hoạt để ngăn chặn bất kỳ chèn hoặc cập nhật từ thiết is_old
để 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()
;
Bạn vẫn phải tin tưởng rằng không ai có thể sửa đổi lược đồ cơ sở dữ liệu sẽ xuất hiện và bỏ trình kích hoạt của bạn hoặc một cái gì đó, nhưng nếu họ sẽ làm điều đó, họ cũng có thể loại bỏ ràng buộc.
Đây là bản demo SQLFiddle . Lưu ý rằng hàng "nên bỏ qua" không nằm trong đầu ra (như chúng ta mong muốn).