美文网首页
关系表、外键、什么情况创建外键?

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

作者: royluck | 来源:发表于2020-01-17 15:18 被阅读0次
  • 主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性

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

  • 这里将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

模型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
  SET
    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 };

image.png
  • 写法二:
'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,
      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 };
新创建的数据尚未跟目标源表关联,如果后续修改数据,这里的category_id必须与目标源表的主键id一致(即目标源关联表存在该id),否则会报错

相关文章

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

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

  • ORM 关联关系

    参看手册文档 关联关系 可以 创建外键或不创建外键 假设存在 users 表 id(主键) -> phones 表...

  • MySQL学习:外键约束foreign key

    1、在创建表时,可添加外键 语法: CREATE TABLE 表名( .... 外键列 CONSTRAINT 外键...

  • MySQL的简单学习(二)-多表查询

    外键 设置外键 如果是创建表添加外键约束,我们需要在创建表的()最后添加如下语句 FOREIGN KEY (bra...

  • SQL数据库的、外键和查询

    外键 增加外键 创建表的时候增加外键:在所有的表字段之后,使用foreign key(外键字段) referenc...

  • 外键、联合查询、子查询

    1、外键: 增加外键 创建表的时候增加外键:在所有的表字段之后,使用foreign key(外键字段) refer...

  • mysql-删除关联表

    1.删除表的外键约束 外键是一个特殊字段,其将某一个表与其父表建立关联关系。在创建表的时候,外键约束就已经设定好了...

  • Mysql外键

    只有InnoDB存储引擎才支持外键 有两张表: 创建外键 方式1: 如上面创建表的语句: 方式2: 删除外键

  • Zabbix数据库优化(Oracle表分区)

    1. 删除zabbix表,重建分区表 a) 保存即将删除表的ddl,外键 b) 根据ddl创建test表,将外键,...

  • python-Flask_SQLAlchemy(3)

    外键约束 [TOC] 创建外键约束表结构 有两个表,用户表(users)与文章表(article)。其中文章表中的...

网友评论

      本文标题:关系表、外键、什么情况创建外键?

      本文链接:https://www.haomeiwen.com/subject/czdfzctx.html