数据库设计 联合主键设为外键的问题

  很多时候我们在数据库设计中都会遇到这样的问题:

有两个表 ,例如(红色的是主键)

学生(学号,姓名,性别,专业号,班级号)

student(sno,sname,sex,spno,class_no);

专业(专业号,专业名称,上课学时);

department(spno,sname,semester);

班级:(专业号,班级号,班主任);

class(spno,class_no,header);

这个时候,我们想把student表里面的class_no设为外键,references  class表,这个时候应该怎么做呢?

我一开始的做法是:

alter  table student

add constraint  fr_student foreign key(class_no)   references  class(class_no);

会出现什么问题呢?

消息 1776,级别 16,状态 0,第 1 行
在被引用表 'class' 中没有与外键 'fr_student' 中的引用列列表匹配的主键或候选键。
消息 1750,级别 16,状态 0,第 1 行
无法创建约束。请参阅前面的错误消息。

会报错!

为什么呢?

这个时候我们就好好好理解一下定义了!

什么是外码,外码设置有什么条件?

其中有一点很重要的就是:外码必须是另外一个表的主码!

这里,我们的student表中的class_no如果想要设计成为一个外码,我们首先要找一下,它是哪一个表的主码?

class表?

class表中的主码是(spno,class_no);这个才是class的主码,是联合主键!

所以,果你设置联合主键,那么外键必须同时引用两个主键属性,否则只能用check约束来实现参照关系。

所以,一般这个时候你可以回去看看语意有没有理解错误,我的一开始就是因为语意理解错误了,才会出这种情况,我的student表中的(spno,class_no)应该设置成为外键才对。

写的不好的可以告诉我一下,让我修改一下

 

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle数据库设计规范建议 1 目的 本规范的主要目的是希望规范数据库设计,尽量提前避免由于数据库设计不当而产生 的麻烦;同时好的规范,在执行的时候可以培养出好的习惯,好的习惯是软件质量的很 好的保证。 数据库设计是指对于一个给定的应用环境,构造最优的数据库模式,建立数据库及其 应用系统,有效存储数据,满足用户信息要求和处理要求。 2 适用范围 本规范的适用人员范围包括我司的所有应用开发人员以及在我司承接数据库应用开 发的软件人员。 本规范的适用IT范围包括数据库对象的命名规范、设计原则、SQL语句的设计和使用 、SQL语句的性能优化建议、其他与性能有关的设计原则以及设计工具的选择。 3 数据对象的命名规范 3.1 通用规范 3.1.1 使用英文:要用简单明了的英文单词,不要用拼音,特别是拼音缩写。主要目的很明确 ,让人容易明白这个对象是什么用的; 3.1.2 一律大写,特别是表名:有些数据库,表的命名乃至其他数据对象的命名是大小写敏感 的,为了避免不必要的麻烦,并且尊重通常的习惯,最好一律用大写; 3.2 数据库对象命名规范 3.2.1 表的命名 3.2.1.1 表名的前缀:前缀_表名_T。为表的名称增加一个或者多个前缀,前缀名不要太长,可以 用缩写,最好用下划线与后面的单词分开;其目的有这样几个: 3.2.1.1.1 为了不与其他项目或者其他系统、子系统的表重名; 3.2.1.1.2 表示某种从属关系,比如表明是属于某个子系统、某个模块或者某个项目等等。表示这 种从属关系的一个主要目的是,从表名能够大概知道如何去找相关的人员。比如以子系 统为前缀的,当看到这个表的时候,就知道有问题可以去找该子系统的开发和使用人员 ; 3.2.2 视图命名:相关表名_V(或者根据需要另取名字); 3.2.3 程序包命名:程序包名_PKG(用英文表达程序包意义); 3.2.4 存储过程命名:存储过程名_PRO(用英文表达存储过程意义); 3.2.5 函数命名:函数名称_FUN(用英文表达函数作用); 3.2.6 触发器命名:触发器名称_TRI(用英文表达触发器作用); 3.2.7 索引命名:表名_字段名_IDX(如果存在多字段索引,取每字段前三个字符加下划线组合 ,如在 custom, cutting, curtail 上建立联合索引,命名为 表名_cus_cut_cur_IDX,如果前三个截取字符相同,就从字段名称中不同的字符开始取三 个字符加下划线组合,如在 custid, custom,custname上建立联合索引,就命名为表_tid_tom_tna_IDX; 3.2.8 唯一索引命名:表名_字段名_UNI(如果存在多字段唯一索引,取每字段前三个字符加下 划线组合,如在 custom, cutting, curtail上建立唯一索引,命名为 表名_ cus_cut_cur_UNI,如果前三个截取字符相同,就从字段名称中不同的字符开始取三个字 符加下划线组合,如:在 custid, custom,custname上建立唯一索引,命名:表_tid_tom_tna_UNI; 3.2.9 主键命名:表名_字段名_PK(如果存在多字段主键,取每字段前三个字符加下划线组合, 如在 custom, cutting, curtail上建立主键,命名为 表名_cus_cut_cur_PK,如果前三个截取字符相同,就从字段名称中不同的字符开始取三 个字符加下划线组合,如在 custid, custom,custname上建立主键,命名:表_tid_tom_tna_PK; 3.2.10 外键命名:表名_主表名_字段名_FK; 3.2.11 Sequence 命名:表名_列名_SEQ(或者根据需要另取名字); 3.2.12 Synonym 命名:与对应的数据库对象同名; 3.2.12 JAVA 命名:遵守公司相应的JAVA命名规范; 4 数据库对象设计原则 4.1 表的设计 4.1.1 主、外键 4.1.1.1 每个表,都必须要有主键。主键是每行数据的唯一标识,保证主键不可随意更新修改, 在不知道是否需要主键的时候,请加上主键,它会为你的程序以及将来查找数据中的错 误等等,提供一定的帮助; 4.1.1.2 一个表的某列与另一表有关联关系的时候,如果加得上的话,请加上外键约束外键是 很重要的,所以要特别强调: 4.1.1.2.1 适量建外键。为了保证外键的一致性,数据库会增加一些开销,如果有确凿的并且是对 性能影响到无法满足用户需求的证据,可以考虑不建外键。否则,还是应该建外键; 4.1.1.2.2 不要以数据操作不方便为理由而不建外键。是的,加上外键以后,一些数据操作变得有 些麻烦,但是这正是对数据一致性的保护。正是因为这种保护很有效,所以最好不要拒
数据库设计规范 数据库的重要性不⾔⽽喻。对程序员来说跟数据库打交道更是家常便饭。数据库给开发带来了巨⼤的便利。我们或多或少的知道⼀些数据库 设计规范,但并不全⾯。今天我就简单整理⼀下,帮⾃⼰个总结梳理,也希望可以帮到⼩伙伴们。 数据库设计规范包括命名规范、库表基础规范、字段规范、索引规范和SQL设计规范。 1. 命名规范 1.1 库名、表名、字段名禁⽌使⽤MySQL保留字。 1.2 库名、表名、字段名使⽤常⽤英语⽽不要使⽤编码,需见名知意,命名与业务、产品线等相关联。 中⽂词汇的英语翻译可以参考常⽤术语来选择相应的英⽂词汇。 1.3 库名、表名、字段名必须是名词的复数形式,并且使⽤⼩写字母,多个名词采⽤下划线分割单词。 MySQL有配置参数lower_case_table_names=1,即库表名以⼩写存储,⼤⼩写不敏感。如果是0,则库表名以实际情况存储,⼤⼩写敏 感;如果是2,以实际情况存储,但以⼩写⽐较。 如果⼤⼩写混合使⽤,可能存在abc、Abc、ABC等多个表共存,容易导致混乱。 字段名显⽰区分⼤⼩写,但实际使⽤时不区分,即不可以建⽴两个名字⼀样但⼤⼩写不⼀样的字段。 为了统⼀规范, 库名、表名、字段名使⽤⼩写字母,不允许-号。 1.4 库名、表名、字段名禁⽌超过32个字符。 库名、表名、字段名⽀持最多64个字符,但为了统⼀规范、易于辨识以及减少传输量,禁⽌超过32个字符 1.5 索引命名规则 索引按照idx_table_column1_column2。其中table是建⽴索引的表名,column1和column2是建⽴索引的字段名。 索引名限制在32个字符内。当索引名超过32字符时,可⽤缩写来减少索引名的长度,如description --> desc;information --> info; address --> addr等。 1.6 主键、外键命名规则 主键按照PK_table的规则命名,其中table为数据库表名。 唯⼀键按照UK_table_column的规则命名。其中table为数据块表名,column为字段名。 外键按照FK_parent_child_nn的规则命名。其中parent为⽗表名,child为⼦表名,nn为序列号。 2. 库表基础规范 2.1 使⽤InnoDB存储引擎。 MySQL 5.5版本开始默认存储引擎就是InnoDB,5.7版本开始,系统表都放弃MyISAM了。 2.2 表字符集使⽤UTF8MB4字符集,校验字符集使⽤utf8mb4_general_ci。 UTF8字符集存储汉字占⽤3个字节,存储英⽂字符占⽤⼀个字节 校对字符集使⽤默认的utf8mb4_general_ci。特别对于使⽤GUI⼯具设计表结构时,要检查它⽣成的SQL定义 连接的客户端也使⽤utf8,建⽴连接时指定charset或SET NAMES UTF8;。 如果遇到EMOJ等表情符号的存储需求,可申请使⽤UTF8MB4字符集 2.3 所有表都要添加注释,除主键外的字段都需要添加注释 类status型需指明主要值的含义,如'0-离线,1-在线' 2.4 控制单表字段数量 单表字段数上限30左右,再多的话考虑垂直分表,⼀是冷热数据分离,⼆是⼤字段分离,三是常在⼀起条件和返回列的不分离。 表字段控制少⽽精,可以提⾼I/O效率,内存缓存更多有效数据,从⽽提⾼响应速度和并发能⼒,后续ALTER TABLE也更快。 2.5 所有表都必须显式指定主键 主键尽量采⽤⾃增⽅式,InnoDB表实际是⼀棵索引组织表,顺序存储可以提⾼存取效率,充分利⽤磁盘空间。还有对⼀些复杂查询可能需 要⾃连接来优化时需要⽤到。 只有需要全局唯⼀主键时,使⽤外部⾃增id服务 如果没有主键或唯⼀索引,UPDATE/DELETE是通过所有字段来定位操作的⾏,相当于每⾏就是⼀次全表扫描 少数情况可以使⽤联合唯⼀主键,需与DBA协商 对于主键字段值是从其它地⽅插⼊(⾮⾃⼰使⽤AUTO_INCREMENT⽣产),去掉AUTO_INCREMENT定义。⽐如⼀些31天表、历史⽉ 份表上,不要AUTO_INCREMENT属性;还有,必须通过全局id服务获取的主键,也要去掉AUTO_INCREMENT定义。 2.6 不强制使⽤外键参考 即使2个表的字段有明确的外键参考关系,也不使⽤FOREIGN KEY,因为新纪录会去主键表校验,影响性能。 2.7 适度使⽤视图,禁⽌使⽤存储过程、触发器和事件 使⽤视图⼀定程度上也是为了降低代码⾥SQL的复杂度,但有时候为了视图的通⽤性会损失性能(⽐如返回不必要的字段)。 存储过程(PROCEDURE)虽然可以简化业务端代码,在传统企业写复杂逻辑时可能会⽤到,⽽在互联⽹企业变更是很频繁的,在分库分 表的情况下要升级⼀个存储过程相当
主键是在数据库表中用来唯一标识每一行数据的字段。主键具有以下特点:一张表中主键是唯一的,主键不能为空。如果一个表中的字段不能作为唯一标识每一行数据时,可以选择多个字段作为联合主键联合主键的特点是,如果去掉联合主键中的某个字段,剩下的字段仍然可以构成联合主键,否则说明之前的联合主键是错误的。\[1\] 外键是子表中对应于主表的列,用来建立表与表之间的关系。外键的值要求与主表的主键或唯一键相对应,用来强制引用完整性。一个表可以有多个外键。例如,在成绩表中,学号可以作为外键,与学生表中的学号关联外键可以有重复的值,也可以是空值。\[2\]\[3\] 在数据库中,主键和外键的声明可以通过在表的字段声明中指定相应的约束来实现。主键约束用于声明主键字段,外键约束用于声明外键字段。通过这样的声明,数据库系统可以确保主键的唯一性和外键的引用完整性。 #### 引用[.reference_title] - *1* *2* [数据库的完整性:主键和外键](https://blog.csdn.net/Peakednes/article/details/106501136)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [数据库的主键与外键](https://blog.csdn.net/YangYanDong666/article/details/89070881)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值