Mối quan hệ một-nhiều mysql

Mối quan hệ xác định là mối quan hệ mà bảng con không thể được xác định duy nhất nếu không có cha của nó. Thông thường, điều này xảy ra khi một bảng trung gian được tạo để giải quyết mối quan hệ nhiều-nhiều. Trong những trường hợp như vậy, khóa chính thường là khóa tổng hợp được tạo thành từ các khóa chính từ hai bảng gốc

  • A mối quan hệ không xác định . được xác định bởi một đường đứt đoạn (nét đứt) giữa các bảng

  • Tạo hoặc kéo và thả các bảng mà bạn muốn kết nối. Đảm bảo rằng có một khóa chính trong bảng nằm trên một side of the relationship. Click on the appropriate tool for the type of relationship you wish to create. If you are creating a one-to-many relationship, first click the table that is on the “many” side of the relationship, then on the table containing the referenced key

    Quan hệ 1-m là loại quan hệ rất phổ biến khi chúng ta thiết kế bảng. Trong quan hệ này, một bản ghi trong bảng thứ nhất có thể có nhiều bản ghi phù hợp trong bảng thứ 2, nhưng một bản ghi trong bảng thứ hai chỉ có một bản ghi phù hợp trong bảng thứ nhất

    Mối quan hệ một-nhiều mysql

    Trong bài viết này, chúng ta cùng tìm hiểu về mối quan hệ 1-M giữa các đối tượng bằng việc sử dụng Golang connect với cơ sở dữ liệu Mysql thông qua GORM

    Constructor directory

    .
    ├── ddl -> chứa các câu lệnh DDL để tạo bảng
    ├── go.mod
    ├── go.sum
    ├── model -> định nghĩa model - entity
    ├── repo -> Chứa hàm thao tác với cơ sở dữ liệu
    └── test -> Viết các hàm unit test để kiểm tra repo

    Tạo bảng và chèn mẫu dữ liệu

    Để tạo bảng chúng ta sử dụng DBeaver và kết nối với container chạy cơ sở dữ liệu mysql (nếu chưa làm được phần này, hãy xem lại bài viết Tìm hiểu về GORM trong Golang (phần 1) và làm theo hướng dẫn)

    Câu lệnh tạo bảng DDL

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')

    Ở đây chúng ta sẽ tạo 2 bảng

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    5 và
    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    6 và thêm 1 số dữ liệu cho 2 bảng này. Mỗi quan hệ giữa
    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    5 và
    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    6 là 1-M, tức là một bản ghi
    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    5 có thể có 0 hoặc nhiều bản ghi
    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    6

    Định nghĩa mô hình

    ________số 8

    Chúng ta định nghĩa 2 struct model is

    // file model/model.go
    
    package model
    
    type Foo struct {
        Id   string `gorm:"primaryKey"`
        Name string
        Bars []Bar `gorm:"foreignKey:FooId"`
    }
    
    type Bar struct {
        Id    string `gorm:"primaryKey"`
        Name  string
        FooId string `gorm:"column:foo_id"`
        Foo   Foo
    }
    1 and
    // file model/model.go
    
    package model
    
    type Foo struct {
        Id   string `gorm:"primaryKey"`
        Name string
        Bars []Bar `gorm:"foreignKey:FooId"`
    }
    
    type Bar struct {
        Id    string `gorm:"primaryKey"`
        Name  string
        FooId string `gorm:"column:foo_id"`
        Foo   Foo
    }
    2. Mặc định thì Id của struct sẽ tham chiếu đến khóa chính trong bảng (vì vậy có thể bỏ qua thẻ gorm cho thuộc tính trong struct)

    Mặc định tên bảng sẽ được tham chiếu từ tên của cấu trúc. Ví dụ struct

    // file model/model.go
    
    package model
    
    type Foo struct {
        Id   string `gorm:"primaryKey"`
        Name string
        Bars []Bar `gorm:"foreignKey:FooId"`
    }
    
    type Bar struct {
        Id    string `gorm:"primaryKey"`
        Name  string
        FooId string `gorm:"column:foo_id"`
        Foo   Foo
    }
    1 -> tên bảng
    // file model/model.go
    
    package model
    
    type Foo struct {
        Id   string `gorm:"primaryKey"`
        Name string
        Bars []Bar `gorm:"foreignKey:FooId"`
    }
    
    type Bar struct {
        Id    string `gorm:"primaryKey"`
        Name  string
        FooId string `gorm:"column:foo_id"`
        Foo   Foo
    }
    4,
    // file model/model.go
    
    package model
    
    type Foo struct {
        Id   string `gorm:"primaryKey"`
        Name string
        Bars []Bar `gorm:"foreignKey:FooId"`
    }
    
    type Bar struct {
        Id    string `gorm:"primaryKey"`
        Name  string
        FooId string `gorm:"column:foo_id"`
        Foo   Foo
    }
    2 ->
    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    6, nhưng ở phần tạo bảng bên chúng ta tạo lại 2 bảng là
    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    5 và
    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    6. Nên cấu trúc tham chiếu đúng đến bảng, lúc này chúng ta cần ghi đè tên bảng

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    7

    Chúng ta có thể thay đổi tên bảng mặc định bằng cách triển khai giao diện Tabler

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    8

    Connected to the database

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    9

    Chúng ta kết nối tới cơ sở dữ liệu thông qua chuỗi kết nối với các thông số khi chúng ta khởi động cơ sở dữ liệu bằng vùng chứa

    Viết repo thao tác với CSDL + Viết unit test

    1. Get list Foo - Bar

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    0

    Viết bài kiểm tra đơn vị

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    1

    Kết quả khi chạy thử nghiệm

    Mối quan hệ một-nhiều mysql

    2. Get information of Foo theo ID

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    2

    Viết bài kiểm tra đơn vị

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    3

    Kết quả khi chạy thử nghiệm

    Mối quan hệ một-nhiều mysql

    3. Get information of Bar by ID

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    0

    Viết bài kiểm tra đơn vị

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    1

    Kết quả khi chạy thử nghiệm

    Mối quan hệ một-nhiều mysql

    4. Dữ liệu mô phỏng

    Ở bước đầu tiên chúng ta tạo bảng và chèn bằng tay 1 vài bản ghi vào cơ sở dữ liệu

    Trong ví dụ này, chúng tôi sẽ thực hiện viết 1 hàm để chèn tự động các bản ghi vào CSDL

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    2

    Để ID ngẫu nhiên cho các đối tượng foo, thanh chúng tôi định nghĩa thêm chức năng NewID()

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    3

    Viết bài kiểm tra đơn vị

    // file DDL/ddl.sql
    
    CREATE TABLE db.foo (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT NULL
    );
    
    CREATE TABLE db.bar (
      id varchar(10) PRIMARY KEY,
      name varchar(50) NOT null,
      foo_id varchar(10) REFERENCES db.foo(id) ON DELETE CASCADE
    );
    
    INSERT INTO db.foo (id, name) VALUES
    ('ox-01', 'foo1'),
    ('ox-02', 'foo2')
    
    INSERT INTO db.bar (id, name, foo_id) VALUES
    ('bar1', 'this is bar 1', 'ox-01'),
    ('bar2', 'this is bar 2', 'ox-02'),
    ('bar3', 'this is bar 3', 'ox-01'),
    ('bar4', 'this is bar 4', 'ox-01')
    4

    Kết quả khi kiểm tra

    Mối quan hệ một-nhiều mysql

    Để kiểm tra lại xem dữ liệu đã được chèn hay chưa, chúng ta có thể kiểm tra trực tiếp trong cơ sở dữ liệu hoặc chạy chức năng kiểm tra Test_GetFooBar