Cách mô hình kế thừa hai bảng MySQL


14

Tôi có một số bảng nơi tôi lưu trữ dữ liệu và tùy thuộc vào loại người (công nhân, dân sự) đã làm một công việc mà tôi muốn lưu trữ trong một eventbảng, bây giờ những người này giải cứu một con vật (có một animalbảng).

Cuối cùng, tôi muốn có một cái bàn để lưu trữ sự kiện mà một anh chàng (công nhân, dân sự), đã cứu một con vật, nhưng tôi nên thêm một cái chìa khóa nước ngoài hoặc làm thế nào để biết idgiá trị của dân sự hoặc công nhân đã làm công việc đó?

Bây giờ, trong thiết kế này, tôi không biết làm thế nào để liên hệ người nào đã làm công việc đó, nếu tôi chỉ có một loại người (còn gọi là dân sự), tôi sẽ chỉ lưu trữ civil_idvale trong một personcột trong bảng cuối cùng này ... nhưng làm thế nào để biết nếu đó là dân sự hay công nhân, tôi có cần bảng "trung gian" khác không?

Làm thế nào để phản ánh thiết kế của sơ đồ sau trong MySQL?

nhập mô tả hình ảnh ở đây

Chi tiết bổ sung

Tôi đã mô hình hóa nó theo cách sau:

DROP    TABLE IF EXISTS `tbl_animal`; 
CREATE TABLE `tbl_animal` (
    id_animal       INTEGER     NOT NULL PRIMARY KEY AUTO_INCREMENT,
    name            VARCHAR(25) NOT NULL DEFAULT "no name",
    specie          VARCHAR(10) NOT NULL DEFAULT "Other",
    sex             CHAR(1)     NOT NULL DEFAULT "M",
    size            VARCHAR(10) NOT NULL DEFAULT "Mini",
    edad            VARCHAR(10) NOT NULL DEFAULT "Lact",
    pelo            VARCHAR(5 ) NOT NULL DEFAULT "short",
    color           VARCHAR(25) NOT NULL DEFAULT "not defined",
    ra              VARCHAR(25) NOT NULL DEFAULT "not defined",
    CONSTRAINT `uc_Info_Animal` UNIQUE (`id_animal`)           
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;


INSERT INTO `tbl_animal` VALUES (1,'no name', 'dog', 'M','Mini','Lact','Long','black','Bobtail');
INSERT INTO `tbl_animal` VALUES (2,'peluchin', 'cat', 'M','Mini','Lact','Long','white','not defined');
INSERT INTO `tbl_animal` VALUES (3,'asechin', 'cat', 'M','Mini','Lact','Corto','orange','not defined');

DROP    TABLE IF EXISTS `tbl_person`;  
CREATE TABLE `tbl_person` (
    type_person  VARCHAR(50) NOT NULL primary key        
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
INSERT INTO `tbl_person` (type_person) VALUES ('Worker');
INSERT INTO `tbl_person` (type_person) VALUES ('Civil');



DROP    TABLE IF EXISTS `tbl_worker`;  
CREATE TABLE `tbl_worker`(
    id_worker           INTEGER  NOT NULL PRIMARY KEY,
    type_person         VARCHAR(50) NOT NULL , 
    name_worker         VARCHAR(50) NOT NULL ,    
    address_worker      VARCHAR(40) NOT NULL DEFAULT "not defined",     
    delegation          VARCHAR(40) NOT NULL DEFAULT "not defined",
    FOREIGN KEY (type_person)               REFERENCES `tbl_person` (type_person),
    CONSTRAINT `uc_Info_worker` UNIQUE (`id_worker`)           
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

INSERT INTO `tbl_worker` VALUES (1,'Worker','N_CEDENTE1', 'DIR Worker 1', 'DEL');
INSERT INTO `tbl_worker` VALUES (2,'Worker','N_worker1', 'DIR Worker 2', 'DEL');
INSERT INTO `tbl_worker` VALUES (3,'Worker','N_worker2', 'address worker','delegation worker'); 


DROP    TABLE IF EXISTS `tbl_civil`; 
CREATE TABLE `tbl_civil`(
    id_civil                        INTEGER  NOT NULL PRIMARY KEY,
    type_person         VARCHAR(50) NOT NULL ,
    name_civil                      VARCHAR(50)  ,
    procedence_civil                VARCHAR(40)  NOT NULL DEFAULT "Socorrism",    
  FOREIGN KEY (type_person)             REFERENCES `tbl_person` (type_person),
    CONSTRAINT `uc_Info_civil` UNIQUE (`id_civil`)           
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;


INSERT INTO `tbl_civil`  VALUES (1,'Civil','N_civil1' , 'Socorrism');


CREATE TABLE `tbl_event` (
    id_event     INTEGER NOT NULL,
    id_animal    INTEGER NOT NULL,
    type_person  VARCHAR(50) NOT NULL , 
    date_reception DATE DEFAULT '2000-01-01 01:01:01',
    FOREIGN KEY (id_animal)   REFERENCES `tbl_animal`    (id_animal),
    FOREIGN KEY (type_person )  REFERENCES `tbl_person`   (type_person ),
    CONSTRAINT `uc_Info_ficha_primer_ingreso` UNIQUE (`id_animal`,`id_event`)     
)ENGINE=InnoDB  DEFAULT CHARSET=utf8;

INSERT INTO `tbl_event` VALUES (1,1, 'Worker','2013-01-01 01:01:01' );
INSERT INTO `tbl_event` VALUES (2,2, 'Civil','2013-01-01 01:01:01' );

Tuy nhiên, có cách nào để loại bỏ null?

Các truy vấn tôi có là:

SELECT  a.*,b.*,z.*
FROM    tbl_event a
        left JOIN tbl_worker b
            ON a.type_person = b.type_person
        left JOIN tbl_animal z
            ON   z.id_animal = a.id_animal ;

SELECT  a.*,b.*,z.*
FROM    tbl_event a
        left JOIN tbl_civil b
            ON a.type_person = b.type_person
        left JOIN tbl_animal z
            ON   z.id_animal = a.id_animal ;

Đây là một sqlfiddle cập nhật .


mục đích của bảng TYPE_PERSONkhi nó chỉ chứa một cột là gì?
JW


@cMinor - Bạn đang hỏi "làm thế nào để biết id của dân sự hoặc công nhân đã làm công việc đó?" Bạn có thực sự biết ai đã làm công việc này trong cuộc sống thực (hoặc tưởng tượng, nếu đây là một bài tập về nhà)? Bạn có đủ dữ liệu nguồn?

Tôi đã quen với việc thừa kế, vì vậy tôi đã tạo ra một người trong bảng có thể chứa các loại người (công nhân, dân sự), sau đó trong bảng sự kiện, Làm thế nào để tham chiếu một người tùy thuộc vào công việc (dân sự hoặc công nhân) như thế nào?
cMinor

1
Tôi tin rằng bạn sẽ nhận được lời khuyên tốt hơn trong Quản trị viên Cơ sở dữ liệu
Pieter Geerkens

Câu trả lời:


13

Vì tôi đã lập sơ đồ, tôi trả lời tốt hơn;)

Rất tiếc, các cơ sở dữ liệu quan hệ hiện tại không hỗ trợ trực tiếp kế thừa, do đó bạn cần chuyển đổi nó thành các bảng "đơn giản". Nhìn chung có 3 chiến lược để làm như vậy:

  1. Tất cả các lớp 1 trong một bảng với các trường không phổ biến có thể NULL.
  2. Lớp bê tông 2 trong các bảng riêng biệt. Các lớp trừu tượng không có bảng của riêng họ.
  3. Tất cả các lớp trong các bảng riêng biệt.

Để biết thêm về ý nghĩa thực sự của nó và một số ưu và nhược điểm, vui lòng xem các liên kết được cung cấp trong bài viết gốc của tôi , nhưng tóm lại, (3) có lẽ nên là mặc định của bạn trừ khi bạn có lý do cụ thể cho một trong hai lý do khác. Bạn có thể biểu diễn (3) trong cơ sở dữ liệu đơn giản như thế này:

CREATE TABLE person (
    person_id int PRIMARY KEY
    -- Other fields...
);

CREATE TABLE civil (
    civil_id int PRIMARY KEY REFERENCES person (person_id)
    -- Other fields...
);

CREATE TABLE worker (
    worker_id int PRIMARY KEY REFERENCES person (person_id)
    -- Other fields...
);

CREATE TABLE event (
    event_id int PRIMARY KEY,
    person_id int REFERENCES person (person_id)
    -- Other fields...
);

Thật không may, cấu trúc này sẽ cho phép bạn có một personcái không civilphải worker(tức là bạn có thể khởi tạo lớp trừu tượng), và cũng sẽ cho phép bạn tạo một personcái có cả hai civilworker. Có nhiều cách để thực thi cái trước ở cấp cơ sở dữ liệu và trong DBMS hỗ trợ các ràng buộc hoãn lại 3 thậm chí cái sau có thể được thi hành trong cơ sở dữ liệu, nhưng đây là một trong số ít trường hợp sử dụng tính toàn vẹn ở cấp ứng dụng .


1 person , civilworkertrong trường hợp này.

2 civilworkertrong trường hợp này ( personlà "trừu tượng").

3 MySQL nào không.


Làm thế nào cái sau có thể được thi hành trong DBMS hỗ trợ các ràng buộc hoãn lại? (không cho phép một người trở thành cả hai civilworker)
Gima

@Gima Hãy theo liên kết tôi đã cung cấp trong câu trả lời.
Branko Dimitrijevic

Bạn yêu cầu cơ sở dữ liệu quan hệ hiện tại không hỗ trợ kế thừa. Điều gì về postgresql? postgresql.org/docs/9.6/static/ddl-inherit.html
Climax

@Climax Tôi biết về PostgreSQL, nhưng việc triển khai nó chỉ là một phần. Từ liên kết của bạn: "Các loại ràng buộc khác (duy nhất, khóa chính và ràng buộc khóa ngoài) không được kế thừa."
Branko Dimitrijevic

1
@naaz Khóa ngoại tồn tại trong cả hai civilworker. Có lẽ bạn đã bỏ lỡ cú pháp tay ngắn (chỉ cần REFERENCESkhông có FOREIGN KEY)?
Branko Dimitrijevic

5

Không cần có Civil_ID và Worker_ID riêng biệt; chỉ cần tiếp tục sử dụng Person-ID làm khóa cho cả ba bảng: Person, Civil và Worker. Thêm một cột PersonType vào Person với hai giá trị "Civil" và "Worker".

Bây giờ, nó đại diện cho hai lớp con CivilClass và WorkerClass của lớp cơ sở trừu tượng PersonClass là các thực thể con Civil và Worker của thực thể cơ sở Person. Bạn nhận được một sự tương ứng tốt giữa mô hình dữ liệu trong DB với mô hình đối tượng trong ứng dụng.


Tôi đã thực hiện một sqlfiddle sqlfiddle.com/#!2/1f6a4/1 nhưng tôi không biết làm thế nào để tham gia vào bảng khác, bạn có thể vui lòng chỉ câu trả lời của bạn ở đây trong sqlfiddle không?
cMinor

Không có "khác biệt" civil_idworker_id- chúng giống nhau person_id, chỉ được đặt tên khác - nhìn vào FK1điểm đánh dấu (khóa ngoại) trước mặt chúng.
Branko Dimitrijevic

4

Trường hợp của bạn là một ví dụ của mô hình lớp / lớp con. Hoặc, như bạn đã lập sơ đồ trong ER, khái quát hóa / chuyên môn hóa.

Có ba kỹ thuật sẽ giúp bạn thiết kế các bảng mysql để bao quát trường hợp này. Chúng được gọi là Kế thừa bảng đơn, Kế thừa bảng lớp và Khóa chính được chia sẻ. Bạn có thể đọc chúng trên tab thông tin từ thẻ tương ứng trong SO.

/programming//tags/single-table-inherribution/info

/programming//tags/group-table-inherribution/info

/programming//tags/spl-primary-key/info

Kế thừa bảng đơn rất hữu ích cho các trường hợp đơn giản trong đó sự hiện diện của NULL không gây ra vấn đề. Kế thừa bảng lớp là tốt hơn cho các trường hợp phức tạp hơn. Khóa chính được chia sẻ là một cách tốt để thực thi các mối quan hệ một-một và tăng tốc độ tham gia.


1

Bạn có thể tạo bảng kiểu người và thêm trường vào tất cả các bảng cần thực thi kiểu. Sau đó tạo khóa ngoại. Đây là một ví dụ xuất phát từ ...

    CREATE TABLE person_type (
        person_type_id int PRIMARY KEY
        -- data: 1=civil, 2=worker
        -- Other fields (such as a label)...
    );

    CREATE TABLE person (
        person_id int PRIMARY KEY
        person_type_id int FOREIGN KEY REFERENCES person_type (person_type_id)
        -- Other fields...
    );

    CREATE TABLE civil (
        civil_id int PRIMARY KEY REFERENCES person (person_id)
        person_type_id int FOREIGN KEY REFERENCES person (person_type_id)
        -- Other fields...
    );

    CREATE TABLE worker (
        worker_id int PRIMARY KEY REFERENCES person (person_id)
        person_type_id int FOREIGN KEY REFERENCES person (person_type_id)
        -- Other fields...
    );

    CREATE TABLE event (
        event_id int PRIMARY KEY,
        person_id int REFERENCES person (person_id)
        -- Type is optional here, but you could enforce event for a particular type
        person_type_id int FOREIGN KEY REFERENCES person (person_type_id)
        -- Other fields...
    );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.