Một biến thể trong câu trả lời của @ a_horse_with_no_name sẽ là trước tiên tạo bảng với ràng buộc và sau đó chèn vào bảng, vẫn sử dụng giao dịch, vì vậy mọi thứ sẽ quay trở lại trong trường hợp vi phạm ràng buộc. Đây là điều bạn nên cân nhắc nếu các hàng được chèn rất nhiều (tức là trong hàng trăm nghìn hoặc hàng triệu).
Nếu khó tạo create table
động câu lệnh, bạn có thể tách phần đó thành 2 câu, với nội dung như sau:
begin transaction ;
create table new_table -- create the table
as
select v.*
from (select ....) as v -- as before
where false ; -- but insert 0 rows
alter table new_table add constraint ... ; -- add the constraint
insert into new_table -- and then attempt
select ... ; -- the insert
end ;
Sự khác biệt với cách khác là ràng buộc sẽ ở đó trước khi bất kỳ hàng nào được chèn vào bảng. Và vì NOT NULL
và các CHECK
ràng buộc không thể bảo vệ được nhưng luôn được kiểm tra ngay lập tức khi một hàng được chèn hoặc sửa đổi (và không ở cuối câu lệnh), câu lệnh chèn của bạn sẽ thất bại (và khôi phục) với hàng đầu tiên vi phạm (các) ràng buộc của bạn có một địa điểm.
Nếu bạn đang chèn nhiều triệu hàng, nó sẽ nhanh hơn, bởi vì nó có thể tìm thấy lỗi nhanh hơn nhưng cũng vì nó sẽ phải khôi phục lại ít phần chèn thêm.