-
主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性
-
外键:是另一表的主键, 外键可以有重复的, 可以是空值,用来和其他表建立联系用的。所以说,如果谈到了外键,一定是至少涉及到两张表。
-
这里将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
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),否则会报错
网友评论