2010-03-02 37 views
138

Ví dụ, tôi có một bảng có một số cột ID cho các bảng khác. Tôi muốn có một chìa khóa nước ngoài để buộc toàn vẹn chỉ khi tôi đặt dữ liệu vào đó. Nếu tôi làm một bản cập nhật tại một thời gian sau đó để cư cột đó sau đó nó vẫn sẽ kiểm tra các ràng buộc (điều này có khả năng phụ thuộc vào máy chủ cơ sở dữ liệu, tôi đang sử dụng MySQL & loại bảng InnoDB). Tôi tin rằng đây là một kỳ vọng hợp lý, nhưng đúng với tôi nếu tôi sai.Các cột trong bảng có khóa ngoại là null không?

+6

Tôi không biết về MySQL, nhưng MS SQL Server cho phép khóa ngoại được vô hiệu hóa với ngữ nghĩa mà bạn muốn. Tôi hy vọng đó là hành vi tiêu chuẩn. –

+0

khóa ngoài, không thể rỗng theo mặc định trong mySQL, lý do rất đơn giản, nếu bạn tham khảo cái gì đó và bạn để nó rỗng, bạn sẽ mất toàn vẹn dữ liệu. khi bạn tạo bộ bảng cho phép null thành NOT và sau đó áp dụng ràng buộc khóa ngoài. Bạn không thể đặt null khi cập nhật, nó sẽ gửi cho bạn một lỗi, nhưng bạn có thể (bạn phải) không cập nhật cột này và chỉ cập nhật các trường bạn cần thay đổi. – JoelBonetR

Trả lời

137

Có, bạn có thể thực thi ràng buộc chỉ khi giá trị không phải là NULL. Điều này có thể dễ dàng được kiểm tra bằng ví dụ sau:

CREATE DATABASE t; 
USE t; 

CREATE TABLE parent (id INT NOT NULL, 
        PRIMARY KEY (id) 
) ENGINE=INNODB; 

CREATE TABLE child (id INT NULL, 
        parent_id INT NULL, 
        FOREIGN KEY (parent_id) REFERENCES parent(id) 
) ENGINE=INNODB; 


INSERT INTO child (id, parent_id) VALUES (1, NULL); 
-- Query OK, 1 row affected (0.01 sec) 


INSERT INTO child (id, parent_id) VALUES (2, 1); 

-- ERROR 1452 (23000): Cannot add or update a child row: a foreign key 
-- constraint fails (`t/child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY 
-- (`parent_id`) REFERENCES `parent` (`id`)) 

Chèn đầu tiên sẽ vượt qua vì chúng tôi chèn NULL vào parent_id. Chèn thứ hai không thành công do ràng buộc khóa ngoài, vì chúng tôi đã cố gắng chèn một giá trị không tồn tại trong bảng parent.

+14

Bảng cha cũng có thể được khai báo với id INT NOT NULL. – Will

+0

@CJDennis Nếu bạn làm cho nó để chỉ có một hàng có thể có một ID null, nó có thể được sử dụng như là giá trị dự phòng cho các hàng khác. (Mặc dù nó có thể làm việc tốt hơn cho DB nếu bạn chỉ sử dụng nhiều cột hơn.) Ràng buộc mặc định có vẻ như là một vấn đề nếu bạn muốn biết sau liệu giá trị ban đầu được đặt là "mặc định" (bằng cách sử dụng null) hay được đặt thành giá trị xảy ra giống với "mặc định". Bằng cách có một hàng có id rỗng, bạn có thể chỉ rõ rằng hàng này không được sử dụng như một hàng bình thường và có thể sử dụng hàng như một cách cung cấp một loại giá trị mặc định động cho các hàng khác. – Ouroborus

+0

tôi nghĩ rằng phần 'parent_id INT NULL' là (verbosely) bằng' parent_id int default null' – Chinggis6

2

Có, điều đó sẽ hoạt động như bạn mong đợi. Thật không may, tôi dường như gặp khó khăn khi tìm một tuyên bố rõ ràng về điều này trong số MySQL manual.

Khóa ngoại nghĩa là giá trị phải tồn tại trong bảng khác. NULL đề cập đến sự vắng mặt của giá trị, vì vậy khi bạn thiết lập một cột để NULL, nó sẽ không có ý nghĩa để cố gắng thực thi các ràng buộc về điều đó.

+0

Bằng cách thiết kế Khóa ngoài phải tham chiếu đến một số khóa (Chính) không phải là NULL, nhưng trong giai đoạn phát triển khi chúng ta cần có nhiều dữ liệu đầu tiên được chèn vào bảng con, chúng ta không biết nó sẽ tham chiếu đến ai (bảng cha)). Đó là lý do tại sao chúng tôi có giá trị NULL được cho phép. Trong sản xuất có NULL sẽ là một luồng thiết kế, có thể được nói gần như. –

15

Tôi thấy rằng khi chèn, các giá trị cột rỗng phải được khai báo cụ thể là NULL, nếu không tôi sẽ nhận được một lỗi vi phạm ràng buộc (trái ngược với một chuỗi rỗng).

+5

Bạn không thể đặt giá trị mặc định của NULL trên cột để cho phép điều này? –

+0

Có, trong hầu hết các ngôn ngữ NULL khác với một chuỗi rỗng. Có lẽ tinh tế khi bắt đầu, nhưng rất quan trọng để nhớ. – Gary

+0

Hey Backslider, bạn nói "(trái ngược với một chuỗi rỗng)", nhưng tôi không nghĩ rằng bạn có nghĩa là bạn sẽ INSERT một giá trị của chuỗi rỗng, mà là, bạn không chỉ định một giá trị tại cho Giá trị ở tất cả? tức là bạn thậm chí không đề cập đến cột trong 'INSERT INTO {table} {list_of_columns}' của bạn? Bởi vì đó là sự thật đối với tôi; bỏ qua đề cập đến cột gây ra lỗi, nhưng bao gồm và thiết lập rõ ràng để sửa lỗi NULL.Nếu tôi đúng, tôi nghĩ rằng bình luận của Gary không áp dụng (bởi vì bạn không có nghĩa là một chuỗi rỗng), nhưng @Kevin Coulombe có thể hữu ích ... –

Các vấn đề liên quan