精彩文章免费看

关系表、外键、什么情况创建外键?

  • 主键: 是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性

  • 外键: 是另一表的主键, 外键可以有重复的, 可以是空值,用来和其他表建立联系用的。所以说,如果谈到了外键,一定是至少涉及到两张表。

  • 这里将hasOne、hasMany、belongsTo进行一个详细举例说明:

  • 首先,这3个的大致中文意思:
    hasOne:有一个,加上主谓语应该是 ,A 有一个 B
    hasMany:有很多,A 有很多 B
    belongsTo:属于, A 属于 B
    这里我们准备3张表来理解他们的关系:
    user_group 用户分组表:id、title
    user 用户表:id、user_group_id、username、password
    profile 用户信息表:id、user_id、nickname、sex
    1、user表需要关联user_group表,表示每一个 用户 需要知道该用户是 哪个用户分组的;
    2、profile表 需要关联 用户表,表示该用户信息数据 是哪个用户的信息;
    我们知道一个用户组下面可以有很多用户,所以:user_group hasMany user;
    一个用户 属于 一个用户组,所以:user belongsTo user_group;
    同样是user_group和user表,但我们出发点不同,关系也就不一样了。
    每个用户都应该有唯一一条用户信息数据,所以:user hasOne profile;
    一条用户信息 属于 一个用户,所以:profile belongsTo user

    belongsTo与hasOne区别 : 外键属性存在位置不同,foreignKey 指定源不同,targetKey 指定源不同

    模型hasOne、hasMany、belongsTo详解
    使用sequelize实现关联(include)查询
    Mysql外键约束,一对多、多对多、一对一:
    1、 一对多: 外键(department_id)一定要放在多的一方,员工表就是多的一方,多个员工是一个部门。创建一对多外键约束
    没有外键的一方是主表,有外键的一方是子表.;
    2、 一对一: 外键(author_detail_id)是两个表之间的绑定关系,创建外键(author_detail_id)的时候要加唯一(unique)约束,不加唯一(unique)约束会变成一对多的关系;
    3、 多对多: 多对多的关系需要借助第三张表 (xx_xx_relation 关系表) 来实现。在第三张表中创建两个外键,把员工和部门表的book_id字段绑定到书表的id字段,author_id字段绑定到作者表的id字段.

    问了两个后端的朋友,他们现在几乎都不用外键了。

  • 现在基本不用外键啦
  • 即使是一对多 多对多的关系 也不用外键
  • 外键好处正在削弱,因为现在集群,分布式概念比较火,一有个什么项目idea,都想着平台化,做大
  • 对开发来说,维护外键使用程序和数据库工作量一样
  • MYSQL外键的使用以及优缺点
    关于数据库设计是否需要加入(建立)外键

    Associations - 关联

    外键:当你在模型中创建关联时,会自动创建带约束的外键引用. 下面是设置;

    Task.init({ title: Sequelize.STRING }, { sequelize, modelName: 'task' });
    class User extends Model {}
    User.init({ username: Sequelize.STRING }, { sequelize, modelName: 'user' });
    User.hasMany(Task); // 将userId添加到Task模型
    Task.belongsTo(User); // 同样会将userId添加到Task模型中
    

    将生成以下SQL:

      "id" SERIAL,
      "username" VARCHAR(255),
      "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
      "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL,
      PRIMARY KEY ("id")
    CREATE TABLE IF NOT EXISTS "tasks" (
      "id" SERIAL,
      "title" VARCHAR(255),
      "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
      "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL,
      "userId" INTEGER REFERENCES "users" ("id") ON DELETE
        NULL ON UPDATE CASCADE,
        PRIMARY KEY ("id")
    

    MySQL中serial关键字的作用
    百度百科:外键
    ==>备注:
    上述SQL语法,起初我看别人创建外键的SQL语法,都应该有FOREIGN KEY这两个关键字,但是上述的SQL语法却没有看到,通过比对代码发现,上述之所以没加FOREIGN KEY,是因为上面的字段userId没有在前面进行声明,如果前面声明了,就需要加FOREIGN KEY关键字,如下:

    create table dep(
        id int primary key auto_increment,
        dep_name char(10),
        dep_comment char(60)
    create table emp(
        id int primary key auto_increment,
        name char(16),
        gender enum('male','female') not null default 'male',
        dep_id int,
        foreign key(dep_id) references dep(id)  // 这里的dep_id,在上面已经声明过了,dep_id int
    
    'use strict';
    const { InfoCrudMixin } = require('lin-mizar/lin/interface');
    const { merge } = require('lodash');
    const { Sequelize, Model } = require('sequelize');
    const { db } = require('lin-mizar/lin/db');
    const {Category} = require('./category')
    class Attr extends Model {
      toJSON () {
        let origin = {
          id: this.id,
          name: this.name,
          cate_id: this.cate_id,
          pid: this.pid,
          create_time: this.createTime
        return origin;
    Attr.init(
        id: {
          type: Sequelize.INTEGER,
          primaryKey: true,
          autoIncrement: true
        name: {
          type: Sequelize.STRING(50),
          allowNull: false,
          comment: '规格名称'
        cate_id: {
          type: Sequelize.INTEGER,  // 这里声明的外键类型必须跟Category的主键类型一致,否则会报错
          allowNull: false,
          comment: '所属分类'
        pid: {
          type: Sequelize.INTEGER,
          defaultValue: 0,
          comment: '所属规格父类id(保留字段,暂时没用)'
      merge(
          tableName: 'attr',
          modelName: 'attr',
          sequelize: db
        InfoCrudMixin.options
    Attr.belongsTo(Category, {
      foreignKey: 'cate_id', targetKey: 'id', as: 'category'
    module.exports = { Attr };
    const { InfoCrudMixin } = require('lin-mizar/lin/interface');
    const { merge } = require('lodash');
    const { Sequelize, Model } = require('sequelize');
    const { db } = require('lin-mizar/lin/db');
    const {Category} = require('./category')
    class Attr extends Model {
      toJSON () {
        let origin = {
          id: this.id,
          name: this.name,
          cate_id: this.cate_id,
          pid: this.pid,
          create_time: this.createTime
        return origin;
    Attr.init(
        id: {
          type: Sequelize.INTEGER,
          primaryKey: true,
          autoIncrement: true
        name: {
          type: Sequelize.STRING(50),
          allowNull: false,
          comment: '规格名称'
        cate_id: {
          type: Sequelize.INTEGER,
          allowNull: false,
          comment: '所属分类'
        pid: {
          type: Sequelize.INTEGER,
          defaultValue: 0,
          comment: '所属规格父类id(保留字段,暂时没用)'
      merge(
          tableName: 'attr',
          modelName: 'attr',
          sequelize: db
        InfoCrudMixin.options
    Attr.belongsTo(Category, {
      foreignKey: 'category_id', targetKey: 'id', as: 'category'
    module.exports = { Attr };