Cách tốt nhất để tạo ra ràng buộc không NULL trong MySQL sao cho fieldA và fieldB không thể là NULL. Tôi không quan tâm nếu một trong hai là NULL của chính nó, chỉ cần miễn là các lĩnh vực khác có một giá trị không NULL. Và nếu cả hai đều có giá trị NULL, thì nó thậm chí còn tốt hơn.Hoặc là các ràng buộc không rỗng trong MySQL
Trả lời
MySQL 5.5 giới thiệu SIGNAL, vì vậy chúng tôi không cần thêm cột trong câu trả lời của Bill Karwin nữa. Bill chỉ ra rằng bạn cũng cần một kích hoạt để cập nhật, vì vậy tôi đã bao gồm điều đó.
CREATE TABLE foo (
FieldA INT,
FieldB INT
);
DELIMITER //
CREATE TRIGGER InsertFieldABNotNull BEFORE INSERT ON foo
FOR EACH ROW BEGIN
IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null';
END IF;
END//
CREATE TRIGGER UpdateFieldABNotNull BEFORE UPDATE ON foo
FOR EACH ROW BEGIN
IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null';
END IF;
END//
DELIMITER ;
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error
UPDATE foo SET FieldA = NULL; -- gives error
tôi đã thực hiện một cái gì đó tương tự trong SQL Server, tôi không chắc chắn nếu nó sẽ làm việc trực tiếp trong MySQL, nhưng:
ALTER TABLE tableName ADD CONSTRAINT constraintName CHECK ((fieldA IS NOT NULL) OR (fieldB IS NOT NULL));
Ít nhất tôi tin rằng đó là cú pháp.
Tuy nhiên, hãy nhớ rằng bạn không thể tạo ràng buộc kiểm tra trên các bảng, bạn chỉ có thể kiểm tra các cột trong một bảng.
Đây là cú pháp tiêu chuẩn cho một hạn chế như vậy, nhưng MySQL blissfully bỏ qua các hạn chế sau
ALTER TABLE `generic`
ADD CONSTRAINT myConstraint
CHECK (
`FieldA` IS NOT NULL OR
`FieldB` IS NOT NULL
)
@Sklivvz: Kiểm tra với MySQL 5.0.51a, tôi thấy nó phân tích một hạn chế CHECK, nhưng không thi hành nó. Tôi có thể chèn (NULL, NULL) mà không có lỗi. Thử nghiệm cả MyISAM và InnoDB. Sau đó sử dụng SHOW CREATE TABLE cho thấy ràng buộc CHECK không có trong định nghĩa bảng, mặc dù không có lỗi nào được đưa ra khi tôi định nghĩa bảng.
Điều này khớp với số MySQL manual có nội dung: "Mệnh đề CHECK được phân tích cú pháp nhưng bị bỏ qua bởi tất cả các công cụ lưu trữ".
Vì vậy, đối với MySQL, bạn sẽ phải sử dụng trình kích hoạt để thực thi quy tắc này. Vấn đề duy nhất là các trình kích hoạt MySQL không có cách nào gây ra lỗi hoặc hủy bỏ một thao tác INSERT. Một điều bạn có thể làm trong trình kích hoạt gây ra lỗi là thiết lập cột NOT NULL thành NULL.
CREATE TABLE foo (
FieldA INT,
FieldB INT,
FieldA_or_FieldB TINYINT NOT NULL;
);
DELIMITER //
CREATE TRIGGER FieldABNotNull BEFORE INSERT ON foo
FOR EACH ROW BEGIN
IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
SET NEW.FieldA_or_FieldB = NULL;
ELSE
SET NEW.FieldA_or_FieldB = 1;
END IF;
END//
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error
Bạn cũng cần kích hoạt tương tự TRƯỚC KHI CẬP NHẬT.
Bill, cố định câu trả lời của tôi cho phù hợp, cảm ơn, – Sklivvz
Thay vì sử dụng cột 'NOT NULL' để buộc lỗi, bạn có thể làm một cái gì đó như' SET NEW.FieldA = 1/0' sẽ ném lỗi chia cho số không . Không phải là thông báo lỗi rất hữu ích *, nhưng ít nhất bạn không phải thêm các cột đặc biệt. Tôi thực sự muốn MySQL hỗ trợ các ràng buộc 'CHECK' thích hợp, hoặc ít nhất có cách tốt hơn để ném lỗi từ các trigger. :( – friedo
@friedo: Vì câu hỏi của OP là về việc thực thi một số điều kiện không có giá trị đặc biệt, tôi cho rằng một thông báo lỗi vi phạm sẽ là thích hợp. để gán một chuỗi cho nó, nó làm tăng thông báo lỗi bao gồm chuỗi bạn sử dụng. :) –
Đây không phải là câu trả lời trực tiếp cho câu hỏi của bạn, nhưng một số thông tin bổ sung.
Khi giao dịch với nhiều cột và kiểm tra nếu tất cả là null hoặc một không phải là null, tôi thường sử dụng COALESCE()
- đó là ngắn gọn, dễ đọc và dễ dàng duy trì nếu danh sách phát triển:
COALESCE(a, b, c, d) IS NULL -- True if all are NULL
COALESCE(a, b, c, d) IS NOT NULL -- True if any one is not null
này có thể được sử dụng trong kích hoạt của bạn.
- 1. ElementName Ràng buộc là không
- 2. Ràng buộc một biến rỗng trong một PreparedStatement
- 3. tạo ràng buộc bảng trong mysql
- 4. Từ ràng buộc vào đối tượng rỗng: RuntimeException: java.lang.reflect.InvocationTargetException
- 5. Tôi đang tìm một ràng buộc để ngăn việc chèn một chuỗi rỗng vào MySQL
- 6. MySQL và Kiểm tra ràng buộc
- 7. Chuỗi rỗng trong cột không rỗng trong MySQL?
- 8. MySQL - Conditional ràng buộc khoá ngoại
- 9. Xuân InitBinder: ràng buộc giá trị rỗng hoặc null của một trường phao như 0
- 10. Mẫu ràng buộc với ràng buộc là gì?
- 11. Mysql hiển thị tạo ra ràng buộc?
- 12. mysql unique index EXCEPT rỗng hoặc null
- 13. MySQL, tốt hơn để chèn NULL hoặc chuỗi rỗng?
- 14. Các khóa phức hợp MySql và các giá trị rỗng
- 15. "Ràng buộc lambda" trong Python là gì?
- 16. Ràng buộc các Procs
- 17. php là rỗng hoặc trống?
- 18. MySQL: Ràng buộc một tập hợp các cột sao cho ít nhất một không phải là NULL
- 19. Hoàn tác trong các ràng buộc WPF
- 20. MySQL: xóa một hàng bỏ qua ràng buộc khóa ngoài
- 21. Cách thêm ràng buộc không null vào cột chứa giá trị rỗng
- 22. Tại sao System.Array không thể là một ràng buộc kiểu?
- 23. Các chế độ ràng buộc WPF khác nhau là gì?
- 24. Tôi có ràng buộc ràng buộc các lớp bình thường bằng Autofac không?
- 25. Các ràng buộc duy nhất trong couchdb
- 26. Thêm các ràng buộc trong phpMyAdmin
- 27. std :: ràng buộc một hàm ràng buộc
- 28. Buộc ràng buộc duy nhất trong GAE
- 29. Ràng buộc với các lệnh trong WinForms
- 30. Phương pháp chung với các ràng buộc chung là
Vì đây là cú pháp SQL chuẩn, nên cũng nên làm việc với các cơ sở dữ liệu dựa trên SQL khác. (Nó chắc chắn hoạt động cho PostgreSQL.) – Neall
Hướng dẫn sử dụng MySQL cho biết: "Mệnh đề CHECK được phân tích cú pháp nhưng bị bỏ qua bởi tất cả các công cụ lưu trữ." Tôi đã thử nó và đó là sự thật. –
Nó thậm chí còn bị bỏ qua cho các bảng InnoDB? Điều đó thật tệ. – Neall