没有额外的桌子的多对多

You*_*sef 3 mysql sql

我有两个表operation,并sourcemysql数据库中.

operation我有10行(可能性)和source只有3行(可能性)和它们之间有一种many-to-many关系.
问题:是否需要添加此额外表或只添加sourcein 的外键operation.

operation 可以订阅请求,订阅启用,订阅禁用,订阅取消,付款确定,订阅交易确定,订阅开始.

source 可以来自互联网,来自代理商

来源有共同的操作和独立的操作.

操作subscribe enabled可以通过互联网订阅或代理订阅和操作来完成:subscribe deal ok可以只是来自代理商,subscribe request也可以来自互联网.

Osc*_*car 7

在关系数据库中,您需要3个表来建立多对多关系.两个包含主键和连接表.别无他法.

  • 从技术上讲,当数据库处于非规范化状态(即大量冗余数据)时,您可以在单个表中建立多对多关系. (7认同)

lp_*_*lp_ 6

对于简短而简短的回答,通常,对于像mysql这样的rdbms,只支持一对多关系,你需要第三个(交叉或交叉引用)表来实现两者之间的多对多关系.实体.

但....

既然你没有太多记录,你可以映射之间的许多一对多的关系source,并operation只有一个附加列source,并没有多余的数据存储.但是,您可能会失去一些性能(例如:不那么强大的索引),并且肯定会让您的生活更难以使用这些表...

诀窍是使用特定的二进制值作为operation表中的主键值,并将一个整数列添加到source表中,在该表中使用其位来映射关系.因此,本专栏的一部分描述了实际源记录与相应操作记录之间的一种关系.

对于样本operation表,您可以使用bit类型的pri键创建一个表,其大小等于您的估计行数.你说你将有~10行,所以bit(10)用作数据类型.因为,mysql会将int存储在4个字节上,所以你不会在这里放松存储大小(相反,与int相比,你可能实际上赢了一些,但实际上这是dbe如何能够压缩记录的问题.实际上,如果你愿意的话,你也可以简单地使用int.)

create table operation (id bit(10) primary key, title varchar(50));

insert into operation values (b'0', 'none');
insert into operation values (b'1', 'subscribe request');
insert into operation values (b'10', 'subscribe enabled');
insert into operation values (b'100', 'subscribe disabled');
insert into operation values (b'1000', 'subscribe canceled');
insert into operation values (b'10000', 'payment ok');
insert into operation values (b'100000', 'subscribe deal ok');
insert into operation values (b'1000000', 'subscribe start');
Run Code Online (Sandbox Code Playgroud)

现在,假设您的源表中包含以下内容:

create table source (id int primary key, value int, operations bit(10));

insert into source values (1, 1, b'0');
insert into source values (2, 2, b'1'); -- refers to subscribe request
insert into source values (3, 3, b'10'); -- refers to subscribe enabled
insert into source values (4, 4, b'10011'); -- refers to payment ok, subscribe request, subscribe enabled
insert into source values (5, 5, b'1110011'); -- refers to subscribe deal ok, subscribe start, payment ok, subscribe request, subscribe enabled
Run Code Online (Sandbox Code Playgroud)

现在,如果要选择所有关系,请按以下方式连接这两个表:

select source.id, operation.title
from source
join operation
  on (source.operations & operation.id);

id  operation.title
2   subscribe request
4   subscribe request
5   subscribe request
3   subscribe enabled
4   subscribe enabled
5   subscribe enabled
4   payment ok
5   payment ok
5   subscribe deal ok
5   subscribe start
Run Code Online (Sandbox Code Playgroud)

如果要添加新关系,可以利用insert 的on duplicate key update子句,因此您不必担心现有关系:

insert into source (id,value,operations)
   values (2,2,(select id from operation where title = 'subscribe start'))
on duplicate key update operations = operations
   | (select id from operation where title = 'subscribe start');
Run Code Online (Sandbox Code Playgroud)

如果要删除关系:

update source set operations = operations
   & ~(select id from operation where title = 'subscribe start') where source.id=2;
Run Code Online (Sandbox Code Playgroud)

总而言之,它不是一个好的,但可能是将多对多关系映射到两个表的可能方式.