当前位置: 首页 > news >正文

MySQL:设计数据库与操作

设计数据库

  • 1. 数据建模
    • 1.1 概念模型
    • 1.2 逻辑模型
    • 1.3 实体模型
      • 主键
      • 外键
      • 外键约束
  • 2. 标准化
    • 2.1 第一范式
    • 2.2 链接表
    • 2.3 第二范式
    • 2.4 第三范式
  • 3. 数据库模型修改
    • 3.1 模型的正向工程
    • 3.2 同步数据库模型
    • 3.3 模型的逆向工程
    • 3.4 实际应用建议
  • 4. 数据库实体模型
    • 4.1 创建和删除数据库
    • 4.2 创建表
    • 4.3 更改表
    • 4.4 创建关系
    • 4.5 更改主键和外键约束
    • 4.6 字符集和排序规则
    • 4.7 存储引擎

1. 数据建模

数据建模的4个步骤:

  1. 理解需求
    理解和分析商业/业务需求,遗憾是很多程序员跳过了这一步就急着去设计数据库里的表和列了,实际上,这一步是最关键的一步,你对问题理解的越透彻,你才越容易找到最合适的解决方案,设计数据库也一样。所以,在动手创建表和列之前,要先完整了解你的业务需求,包括和产品经理、行业专家、从业人员甚至终端用户深入交流以及收集查阅已有的领域相关的表、文件、应用程序、数据库,以及其他与问题领域相关的任何信息或资料。
  2. 概念建模
    当收集并理解了所有相关信息后,下一步就是为业务创建一个概念性的模型。这一步包括找出/识别/确认(identify)业务中的实体/事务/概念(entities/things/concepts)以及它们之间的关系。概念模型只是这些概念的一个图形化表达,用来与利益相关方交流和达成共识。
  3. 逻辑建模
    创建好概念模型后,转而创建数据模型(data model)或数据结构(data structure for storing data),即逻辑建模。这一步创建的是不依赖于具体数据库技术的抽象的数据模型,主要是确认所需要的表和列以及大体的数据类型。
  4. 实体建模
    实体建模指的是将逻辑模型在具体某种DBMS上加以实现的过程,相比于逻辑模型,实体模型会确定更多细节,包括各表主键的设定,各列在某一DBMS下特定的具体的数据类型,默认值,是否可为空,还包括储存过程和触发器等对象的创建。总之,实体模型是在某一特定DBMS下对数据模型非常具体的实现。

1.1 概念模型

在这里插入图片描述
案例:建立学生实体并确定相关属性;建立课程实体并确定相关属性;建立两个实体之间的关系。如上图所示。

将实体及其关系可视化的方法,一种是实体关系图(Entity Relationship, ER),一种是统一建模语言(Unified Modeling Language,UML),这里我们用实体关系图(ER),这里采用工具为VISIO。

NOTE: 建模是个迭代过程,不可能第一次就建立完美模型,需要在理解需求和模型设计之间不断反复,多次调整。比如这里的学生属性,可以先确定个大概,之后可以根据需要再进行增删修改。
概念模型主要是从很高的视角来总览业务需求,识别业务中的实体/事务/概念以及他们彼此间的关系,通常这些实体包括人、事件、地点等。只是从概念上总揽全局,目的是和业务人员交流,保持理解一致。

1.2 逻辑模型

逻辑模型是在概念模型的基础上,在不依赖特定数据库系统的前提下确定数据结构,包括细化实体间的关系(常常要为关系创造新的实体),调整字段设置,确定大体的数据类型。总之,逻辑模型会基本确立数据库中的表、列以及表间关系。

对概念模型逻辑化的过程如下:

  1. 细化实体间关系
    考虑学生和课程的关系,首先这是一种多对多关系(通常意味着需要进一步细化);这些属性相对于学生和课程而言都是一对多关系,不管放在学生还是课程身上都不合适,所以应该为学生和课程之间的关系,即注册课程的事件另外设立一个实体 enrollmemt,上面的注册日期和注册价格都应该是这个enrollment 注册事件的属性。
  2. 调整字段并大体确定字段的数据类型
    姓名(name)最好拆分为姓和名 (first_name 和 last_name),同理,地址应该拆分为省、市、街道等等小的部分,这样方便查询。注意课程里的 tags 标签字段不是一个好的设计,之后讲归一化时再来处理。
    这里的数据类型只需确定个大概即可,如:是 string,float 而非 VARCHAR, DECIMAL。等到下一步实体模型里再来确定某个DBMS下的具体数据类型。
    在这里插入图片描述

1.3 实体模型

实体模型(实际模型)就是逻辑模型在具体DBMS的实现,这里我们用MySQL实现的逻辑模型。实体模型是逻辑模型在特定DBMS上的实现,主要是一些技术上的细化,包括确定字段具体数据类型和性质(能否为空等),设置主键等。

  • 操作方法:Workbench-file-【new model】新建数据库,上方用 add diagram 作 EER 图,这里EER表示Enhanced Entity Relationship增强型实体关系图。为三个实体创建三张表,设定表名、字段、具体的数据类型、是否可为空(即是否为必须字段),也可以选择设定默认值(主键设定之后再讲)。

NOTE:

  1. 表名:之前逻辑模型里表名用单数,但这里表名用复数。这只是一种惯例,单复数都行,关键是要保持一致。
  2. 字段名:以enrollments表为例,注册事件的属性应该是dat日期和pric价格而非enrollment_date注册日期和enrollement_price注册价格,不要将表名前缀加上字段上造成不必要的麻烦,保持精简(keep thingssimple)。
  3. 数据类型:数据类型要根据业务需要来,例如,和业务人员确认后发现课程价格最高是999美元,所以price价格就可以设定为DECIMAL(5,2),之后如果需求变了了也可以随时更改,不要一上来就设定DECIMAL(9,2),浪费磁盘,注意保持精简(keep things small)

主键

主键就是能唯一标识表中每条记录的字段。(一般用数字ID来确定)

主键要短,可唯一标识记录,且永不改变。我们增加一个 student_id 作为主键,类型设为 INT(最大可表示2亿,一般足够了,但记得总是根据具体的需求决定),设为主键后自动变为不可为空,另外还要设定 AI(AutoIncremental)自动递增,这样会方便许多,不用担心主键唯一性的问题,最后我们把主键拖到表的第一列让表的结构看起来更清晰。
在这里插入图片描述

外键

实体模型需要更多得实现细节。
在这里插入图片描述

Note: 连线时记不得先连主表还是子表可以看状态栏的提示; MySQL自动添加的外键会带父表前缀,没必要,建议去掉.

注意 enrollments 表的特殊性,它可以说是 students 和 courses 的衍生表,先要有学生和课程,才能有学生注册课程这一事件,后者表述的是前两者的关系,学生和课程是因,注册课程这一事件是果。

MySQL里可以通过一对一或一对多两种连线表达这种先后关系/因果关系并自动建立外键,其中学生和课程被称作父表或主键表,注册事件被称作子表或外键表,外键是子表里对父表主键的引用。

根据表间关系给enrollments表添加了student_id和course_id两个外键,enrollments 的主键设置有两个选择:

  1. 将这两个外键作为联合主键;
  2. 另外设置一个单独的主键 enrollment_id。
  • 联合主键可以防止同一个学生重复注册同一门课程,因为主键(这里是联合主键)是唯一不可重复的,这可以防止一些不合理的数据输入。坏处是如果 enrollments 未来有新的子表,就需要复制两个字段(而不是 enrollment_id 这样的一个字段)作为外键,这也不一定是很大的麻烦,要根据数据量以及子表是否还有子表等情况来考虑,在一定情况下可能会造成不必要冗余和麻烦(相对于将 enrollment_id 一个字段作为主键来说)。
    创建表之间关系和设置ID时,先考虑当下的情况。

外键约束

有外键时,需要设置约束以防止数据损坏/污染(不一致)。
右边 Foreign KeyOptions 可分别选择当父表里的主键被修改或删除(Update / Delete)时,子表里的外键如何反应,有三种选项:

  1. CASCADE: 瀑布/串联/级联,表示随着主键改变而改变,如主键某学生的student_id从1变成2,则改学生的所有注册课程记录的 student_id也会全部变为2(注意主键一般也最好是永远不要变的,这里讨论的是特殊情况)
  2. RESTRICT/NO ACTION: 等效,作用都是禁止更改或删除主键。如:对于有过注册记录的课程,除非先删除该课程的注册购买记录,不然不能在 courses表里删除该课程的信息。(另外注意:MySQL 里外键默认的 On Update 和 On Delete 的反应都是 NO ACTION)
  3. SET NULL: 就是当主键更改或删除时,使得相应的外键变为空,这样的子表记录就没有对应的主键和对应的父表记录了(no parent),被称为孤儿记录(orphan record),这是垃圾数据,让我们不知道是谁注册的课程或不知道注册的是什么课程,一般不用,只在极其特殊的情况可能有用.
  • 通常对于 UPDATE, 设置为 CASCADE 级联,随之改变.
    对于 DELETE,看情况而定,可能设置为 CASCADE 随之删除 也可能设置为 RESTRICT / NO ACTION 禁止删除。不要死板,永远按照业务/商业需求来选择,这也正是为什么之前强调“理解业务需求”是最重要的一步。比如我们课程注册记录里包含购买价格信息,则应该禁止删除,否则之后想查询某课或某时间段的收入情况就不能实现,相反如果只是个用户登录并设定一系列提醒的软件,可能用户允许用户注销并删除所有提醒就没什么大不了的,但万一,我们需要这些提醒记录来进行统计,则又该设置为禁止删除,总之一定要根据具体业务需求来(always check with the business)。

2. 标准化

正式建立数据库前我们先要检查并确定现在的设计是最优化的(optimal),关键是没有任何冗余或重复,简洁且便于修改和保持一致性。重复数据会占用更多空间并且使得增删查改的操作复杂化,比如,如果用户名在多处出现的话,一旦更改用户名就要到多处更改否则就会使得数据不一致,出现无效数据。

为了防止重复冗余,需要遵循数据库设计的7大规则或者说7大范式,每一条都是建立在你已经遵循了前一条的基础上。实际上,99%的数据库之需要遵循前3大范式就够了。

2.1 第一范式

第一范式要求一行中的每一个单元格都应该有单一值,且不能出现重复列。Each cell should have a single value and we cannot have repeated columns。

案例:courses 里的 tags 标签列就不符合第一范式。tags 列用逗号隔开多个标签,不是单一值。若将 tags 分割成多列,每个标签一列,问题是我们不知道到底有多少标签,每次出现新标签就要改动表结构,这样的设计很糟糕。这也正是范式1要求没有重复列的原因。因此将tags列单独拉出生成表。
在这里插入图片描述

2.2 链接表

在这里插入图片描述
建立courses和tags之间的联系,发现两者是多对多关系(MySQL里只有一对一和一对多,没有多对多),这说明两者的关系需要进一步细化,我们添加一个course_tags表来专门描述两者间的关系,记录每一对课程和标签的组合,这个中间表或者说链表(link table)同时是 courses 和 tags 的子表,与这两个父表均为一对多的关系,建立两条一对多连线后MySql自动给 course_tags表增加了两个外键course_id和tage_id(注意去掉自动添加的表前缀),两者构成 course_tags表的联合主键。

建立链表细化多对多关系,这是很常用的一种方法,有时链表只包含引用的两个外键,如course_tags 表,有时链表还包含其它信息,如 enrollments 表。

链表也可以直接用多对多来生成。当表中存在不确定数值的属性列时需要在实体模型中进一步细分。

2.3 第二范式

每个表都应该是单一功能的/应该表示一个实体类型,这个表的所有字段都是用来描述这个实体的。Every table should describe one entity, and every column in that table should describe that entity。

以 courses 表为例,course_id、title、price 都完全是属于课程的属性,放在courses 表里没问题,但注册时间enrollment_date放在courses表里就不合适,因为一个课程可以被多个学生注册所以有多个注册时间,同样的注册时间也不应该是students表的属性,因为一个学生可以注册多门课所以可以有多个注册时间,注册时间应该是属于“注册事件”的属性,所以应该另外建个enrollments表,放在该表里。

总之,第一范式是要求单一值和无重复列,这里第二范式是要求表中所有列都只能是完全描述该表所代表的实体的属性,不属于该实体(如订单表)的、在记录中可重复的属性,应该另外放在描述相应实体的表里(如顾客表)。

案例:courses里的instructors虽然是单一值符合第一范式却不符合第二范式,因为老师不是完全属于课程的属性,老师在不同课程中可能重复。所以,另外建立instructrors表作为父表,包含instructor_id和name字段,其中instructor_id为主键,一对多连接courses表后自动引进courses表作为外键,删除原先的instructor列。还有注意设置外键约束,UPDATE 设置为CASCADE,DELETE设置为NO ACTION,也就是instructor_id会随着instructors表更改,但不允许在某教师有课程的情况下删除该教师的信息。
在这里插入图片描述

2.4 第三范式

一个表中的字段不应该是由表中其他字段推导而来。A column in a table should not be derived from other columns.

案例:

  1. invoices 发票表里假设有三个字段:发票额、支付额 和 余额,第三个可以由前两个相减得到所以不符合3NF,每次前两者更新第三个就要随之更新,假设没有这样做,让三者出现了 100,40,80 这样不一致的数据,就不知道到底该相信哪个了,余额到底是 80 还是 100-40=60?
  2. 如果表里已经有 first_name 和 last_name 就不该有 full_name,因为第三者总是可以由前两者合并得到不管是上面的 余额balance 还是 全名fullname,都是一种冗余,应该删除。

这些范式目的:减少数据重复和冗余,增强数据的一致性和完整性。

3. 数据库模型修改

3.1 模型的正向工程

通过模型正向搭建数据库:workbench 菜单的 Database 选项 → Forward Engineer 正向搭建数据库。依据向导保持默认不断点下一步就好了,不要更改,除非你知道你在做什么。

最后一步会展示对应的SQL代码,里面有创建 school 数据库(schema 架构;模式;纲目;结构方案)以及各表的SQL代码,之后会详细讲。可以选择保存代码为文件(以保存到仓库中)或者复制到剪贴板然后到workbench查询窗口里以脚本方式运行,这里我们直接运行,返回local instance连接刷新界面就可以看到新的school数据库和里面的6张表了。

3.2 同步数据库模型

之后可能会修改数据库结构,比如更改某些表中字段的数据类型或增加字段之类,如果只是自己一个人用的一个本地数据库,可以直接打开对应表的设计模式并点击更改即可,但如果是在团队中工作通常不是这样。在中大型团队中,我们通常有多个服务器来模拟各种环境,其中有:

  1. 生产环境production environment:用户真正访问应用和数据库的地方;
  2. 模拟环境staging environment:与生产环境十分接近;
  3. 测试环境testing environment:存粹用来做测试的
  4. 开发环境development environment

每次需要对数据库做修改时我们需要复制相同的修改到不同的环境以保持数据的一致性。
***操作:***所以不能是在设计模式中直接点击修改,相反,是在之前模型标签(注意模型可以保存为一个 MySQL 模型文件,下次可以直接打开使用)里的实体模型图(EER Diagram)中修改表或字段,并使用菜单中的 Database →Synchronize Model ( 用 模 型 创 建 数 据 库 时 用 Forward Engineer , 对 已 有 数 据 库 进 行 同 步 修 改 时 用Synchronize Model ) 。 注 意 点 开 Synchronize Model 后 可 以 选 择 连 接 。

3.3 模型的逆向工程

为数据库创建模型,之后可以在模型上更改,便于同步各个环境下的数据库数据。
模型图中实线和虚线表示强联系和弱联系,实线表示must be,虚线表示may be。
Note:

  1. 关闭当前 Model,不然之后的逆向工程结果会添加到当前模型上,最好是每个数据库都有一个单独的模型,除非数据库间相互关联否者不要在一个模型中处理多个数据库.
  2. Database → Reverse Engineer,可以选择目标数据库,如上说所,除非数据库相互关联,否者最好一次只逆向工程一个数据库,让每个数据库都有一个单独的模型.
  3. 可以对逆向的表格进行筛选。

在反向搭建出的模型中,可以更好的看到和理解数据库的结构设计,可以修改表结构(并将相关修改脚本保存并用于其它环境的数据库),还可以发现问题。尽量消除没有关联的表格。

3.4 实际应用建议

  1. 不要死记范式规则,重点在于消除冗余,减轻数据库复杂度
    比如发现一个name字段下出现的是一些重复的名字而不是重复的外键(如某种id),那就说明设计还不够归一化,具体违反哪条范式并不重要,关键是专注于避免重复性。
  2. 不要对什么都建模
    简单才是最高境界。Simplicity is the Ultimate Sophistication.
  3. 第六范式:不要在关系型数据库中再建关系型数据结构。

设计数据库时总是考虑当前的业务需求,不要试图包罗万象,总有开发人员会考虑各种未来可能出现的需求,实际上大部分那些需求都从未发生,反而使得数据库增加了很多没必要的复杂性,复杂化了查询并拖慢了执行效率.

建立复杂模型不是本事,让模型尽可能优美简单易懂又能满足目前的需求这才是本事,如果还能有不错的拓展性以满足未来可能的新特性就更好了.

尽可能保持简洁,简洁才是终极哲学,无论你对未来的预测有多好,总会有意料之外的需求出现,总有一天你会写脚本改数据库甚至进行数据迁移,这是避免不了的,当前只需考虑如何最好地满足目前的需求就好了,不要企图对全宇宙建模。

4. 数据库实体模型

4.1 创建和删除数据库

用workbench的向导来创建和修改数据库能够提高效率,但作为 DBA (Database Administrator 数据库管理员),你必须要能理解并审核相关代码,确保其不会对数据库有不利影响,而且也有能力手动写代码完成创建和修改数据库的操作,可以不依赖(图形化和向导)工具。

创建和删除数据库代码:

CREATE DATABASE IF NOT EXISTS sql_store2;
DROP DATABASE IF EXISTS sql_store2;

4.2 创建表

DROP DATABASE IF EXISTS sql_store2;
CREATE DATABASE IF NOT EXISTS sql_store2;
-- 没有就创建,有就删除
USE sql_store2;  -- 创建数据库后一定要选择相关数据库
DROP TABLE IF EXISTS customers;
CREATE TABLE IF NOT EXISTS customers(customer_id INT PRIMARY KEY AUTO_INCREMENT,first_name VARCHAR(50) NOT NULL,points INT NOT NULL DEFAULT 0,email VARCHAR(255) NOT NULL UNIQUE
);

NOTE:

  1. 创建对象(不管是数据库还是表)有两种方式,DROP …… IF EXIXTS ……; CREAT …… 和 CREAT …… IF NOT EXISTS ……,注意两种方式的区别在于,当原对象存在时,前者是推倒重建,后者是保持原状放弃创建(所以按通常的需求来看还是前者更符合)。
  2. 括号中设置列的方式为 列名 数据类型 各种列性质,列间逗号分隔,常用的列性质有PRIMARY KEY 、AUTO_INCREMENT、 NOT NULL 、DEFAULT 0、 UNIQUE。

4.3 更改表

ALTER TABLE customersADD COLUMN last_name VARCHAR(50) NOT NULL AFTER first_name,ADD city VARCHAR(50) NOT NULL,MODIFY COLUMN first_name VARCHAR(60) DEFAULT '',
DROP COLUMN points;

NOTE:

  1. COLUMN 是可选的,有的人喜欢加上以增加可读性;
  2. AFTER first_name 是可选的,不加的话默认将新列添加到最后一列;
  3. MODIFY 修改已有列,经实验发现其实应该是重置该列(= DROP + ADD),所以注意要列出全部类型和属性信息,如上例中将 first_name 修改为 VARCHAR(60) 类型并将默认值修改为空字符串’',但忘了加 NOT NULL,刷新后发现 first_name 不再有 NOT NULL 属性;
  4. 列名最好不要有空格,但如果有的话可用反引号包裹,如 last name.
  5. 修改表永远不要直接在生产环境中进行,要首先在测试环境进行,确保没有错误和不良影响后再到生产环境进行修改。

4.4 创建关系

CREATE DATABASE IF NOT EXISTS sql_store2;
USE sql_store2;
DROP TABLE IF EXISTS orders;
DROP TABLE IF EXISTS customers; 
CREATE TABLE customers(customer_id INT PRIMARY KEY AUTO_INCREMENT,first_name VARCHAR(50) NOT NULL,points INT NOT NULL DEFAULT 0,email VARCHAR(255) NOT NULL UNIQUE
);
CREATE TABLE orders(order_id INT PRIMARY KEY,customer_id INT NOT NULL,order_date DATE NOT NULL,  -- 在添加完所有的列之后设置外键FOREIGN KEY fk_orders_customers(customer_id)REFERENCES customers(customer_id)ON UPDATE CASCADEON DELETE NO ACTION
);

Note:

  1. 外键名的命名习惯:fk_子表_父表
  2. 语法结构:
FOREIGN KEY 外键名 (外键字段)
REFERENCES 父表 (主键字段)
-- 【设置外键约束】
ON UPDATE CASCADE
ON DELETE NO ACTION
  1. 应该把orders表(子表)的DROP语句放到最前面,不然第二次运行会出问题。

4.5 更改主键和外键约束

USE sql_store2;
ALTER TABLE ordersDROP PRIMARY KEY,ADD PRIMARY KEY (order_id),DROP FOREIGN KEY fk_orders_customers,ADD FOREIGN KEY fk_orders_customers (customer_id)references customers (customer_id)ON UPDATE CASCADEON DELETE NO ACTION;

Note:

  1. 这里不管是之前创建orders表时设置外键还是这里通过修改ADD增加外键,外键名明明写的是 fk_orders_customers,实际上都会变成 orders_ibfk_1,要去设计模式手动修改才行,可能是bug
  2. 通过类似的 ALTER TABLE 语句增删主键:可增加多个主键,在括号内用逗号隔开,注意说的是 ADD 其实是重置,所以一次要把该表所有需要的主键声明完整。

4.6 字符集和排序规则

字符是以数字序列的形式储存于电脑中的,字符集是数字序列与字符相互转换的字典,不同的字符集支持不同的字符范围,有些支持拉美语言字符,有些也支持亚洲语言字符,有些支持全世界所有字符,查看MySQL支持的所有字符集:

SHOW CHARSET;

在这里插入图片描述
其中armscii8支持亚美尼亚语,big5支持繁体中文,gb2312和gbk支持简体中文(gk是国标的拼音简称,k是扩展的拼音简称),而utf-8支持全世界的语言,utf-8也是MySQL自版本5之后的默认字符集。还可以看到字符集描述,默认排序规则,最大长度。

排序规则(collation)指的是某语言内字符的排序方式,utf-8的默认排序规则是utf8_general_ci,其中ci表示case insensitive大小写不敏感,即MySQL在排序时不会区分大小写,这在大部分时候都是适用的,比如用户输入名字的时候大小写不固定,我们希望只按照字符顺序而不管大小写来对名字进行排序。总之,99.9%的情况下都不需要更改默认排序规则。

对于字符集来说,大部分时候用默认的utf-8就行了。但有时,我们可以通过更改字符集来减少空间占用,例如,我们某个特定的应用(对应的数据库)/特定表/特定列是只能输入英文字符的,那如果将该列的字符集从utf-8改为latin1,占用空间就会缩小到原来的1/3,以字段类型为CHAR(10)(固定预留10个字符)且有1百万条记录为例,占用空间就会从约30MB减到10MB。接下来将如何用菜单和代码方式更改库/表/列的字符集。

  • Workbench更改办法

    1. 菜单方式更改字符集:右键sql_store2 数据库,点击 Schema Inspector可查看;
    2. 要修改库或者表和列的字符集,直接点开库或者表的设计模式(扳手按钮)在里面选择更改即可。
  • 代码更改
    1)在创建数据库时设置字符集或更改已有数据库字符集

CREATE/ALTER DATABASE db_name
CHARACTER SET latin1

2)在创建表时设置字符集或更改已有表的字符集

CREATE/ALTER TABLE table1
(……)
CHARACTER SET latin1

3)在创建表时设置列的字符集

CREATE TABLE IF NOT EXISTS customers(
customer_id INT PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(50) CHARACTER SET latin1 NOT NULL,
points INT NOT NULL DEFAULT 0,
email VARCHAR(255) NOT NULL UNIQUE)

4.7 存储引擎

在MySQL中我们有若干种储存引擎,储存引擎决定了我们数据的储存方式以及可用的功能.

SHOW ENGINES;

储存引擎有很多,我们真正需要知道只有两个:MyISAM(读作 My-I-SAM) 和 InnoDBMyISAM是曾经很流行的引擎,但自MySQL5.5之后,默认引擎就改为InnoDB了,InnoDB支持更多的功能特性,包括事务、外键等等,所以最好使用InnoDB引擎是表层级的设置,每个表都可以设置不同的引擎(虽然这没必要)。

外键是十分重要的,它可以增加引用一致性/完整性(referential integrity),如果我们有一个老数据库的引擎是 MyISAM,我们想要给它设置外键,就必须要将其引擎升级为 InnoDB,可以在表的设计模式里选择更改,也可以用修改表的代码:

ALTER TABLE customers
ENGINE = InnoDB;

改变引擎是一个代价极高(expensive)的操作,它会重建整个表,在此期间无法方法访问数据。所以,不要轻易在生产环境中改变储存引擎,除非有特殊的理由。

相关文章:

MySQL:设计数据库与操作

设计数据库 1. 数据建模1.1 概念模型1.2 逻辑模型1.3 实体模型主键外键外键约束 2. 标准化2.1 第一范式2.2 链接表2.3 第二范式2.4 第三范式 3. 数据库模型修改3.1 模型的正向工程3.2 同步数据库模型3.3 模型的逆向工程3.4 实际应用建议 4. 数据库实体模型4.1 创建和删除数据库…...

OBS 免费的录屏软件

一、下载 obs 【OBS】OBS Studio 的安装、参数设置和录屏、摄像头使用教程-CSDN博客 二、使用 obs & 输出无黑屏 【OBS任意指定区域录屏的方法-哔哩哔哩】 https://b23.tv/aM0hj8A OBS任意指定区域录屏的方法_哔哩哔哩_bilibili 步骤: 1)获取区域…...

uniapp微信小程序使用xr加载模型

1.在根目录与pages同级创建如下目录结构和文件: // index.js Component({properties: {modelPath: { // vue页面传过来的模型type: String,value: }},data: {},methods: {} }) { // index.json"component": true,"renderer": "xr-frame&q…...

机器人运动范围检测 c++

地上有一个m行n列的方格,一个机器人从坐标(0,0)的格子开始移动,它每次可以向上下左右移动一个格子,但不能进入行坐标和列坐标的位数之和大于k的格子,请问机器人能够到达多少个格子 #include &l…...

kettle从入门到精通 第七十四课 ETL之kettle kettle调用https接口教程,忽略SSL校验

场景:kettle调用https接口,跳过校验SSL。(有些公司内部系统之间的https的接口是没有SSL校验这一说,无需使用用证书的) 解决方案:自定义插件或者自定义jar包通过javascript调用https接口。 1、http post 步…...

C++轻量级 线程间异步消息架构(向曾经工作的ROSA-RB以及共事的DOPRA的老兄弟们致敬)

1 啰嗦一番背景 这么多年,换着槽位做牛做马,没有什么钱途 手艺仍然很潮,唯有对于第一线的码农工作,孜孜不倦,其实没有啥进步,就是在不断地重复,刷熟练度,和同期的老兄弟们&#xf…...

Kotlin中的类

类初始化顺序 constructor 里的参数列表是首先被执行的,紧接着是 init 块和属性初始化器,最后是次构造函数的函数体。 主构造函数参数列表firstProperty 初始化第一个 init 块secondProperty 初始化第二个 init 块次构造函数函数体 class Example const…...

VSCode中常用的快捷键

通用操作快捷键 显示命令面板:Ctrl Shift P or F1,用于快速访问VSCode的各种命令。 快速打开:Ctrl P,可以快速打开文件、跳转到某个行号或搜索项目内容。 新建窗口/实例:Ctrl Shift N,用于打开一个新的…...

代码随想录-Day45

198. 打家劫舍 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个…...

Rust Eq 和 PartialEq

Eq 和 PartialEq 在 Rust 中&#xff0c;想要重载操作符&#xff0c;你就需要实现对应的特征。 例如 <、<、> 和 > 需要实现 PartialOrd 特征: use std::fmt::Display;struct Pair<T> {x: T,y: T, }impl<T> Pair<T> {fn new(x: T, y: T) ->…...

思考如何学习一门编程语言?

一、什么是编程语言 编程语言是一种用于编写计算机程序的人工语言。通过编程语言&#xff0c;程序员可以向计算机发出指令&#xff0c;控制计算机执行各种任务和操作。编程语言由一组语法规则和语义规则组成&#xff0c;这些规则定义了如何编写代码以及代码的含义。 编程语言…...

顺序串算法库构建

学习贺利坚老师顺序串算法库 数据结构之自建算法库——顺序串_创建顺序串s1,创建顺序串s2-CSDN博客 本人详细解析博客 串的概念及操作_串的基本操作-CSDN博客 版本更新日志 V1.0: 在贺利坚老师算法库指导下, 结合本人详细解析博客思路基础上,进行测试, 加入异常弹出信息 v1.0补…...

[论文阅读笔记33] Matching Anything by Segmenting Anything (CVPR2024 highlight)

这篇文章借助SAM模型强大的泛化性&#xff0c;在任意域上进行任意的多目标跟踪&#xff0c;而无需任何额外的标注。 其核心思想就是在训练的过程中&#xff0c;利用strong augmentation对一张图片进行变换&#xff0c;然后用SAM分割出其中的对象&#xff0c;因此可以找到一组图…...

阿里Nacos下载、安装(保姆篇)

文章目录 Nacos下载版本选择Nacos安装Windows常见问题解决 更多相关内容可查看 Nacos下载 Nacos官方下载地址&#xff1a;https://github.com/alibaba/nacos/releases 码云拉取&#xff08;如果国外较慢或者拉取超时可以试一下国内地址&#xff09; //国外 git clone https:…...

四、golang基础之defer

文章目录 一、定义二、作用三、结果四、recover错误拦截 一、定义 defer语句被用于预定对一个函数的调用。可以把这类被defer语句调用的函数称为延迟函数。 二、作用 释放占用的资源捕捉处理异常输出日志 三、结果 如果一个函数中有多个defer语句&#xff0c;它们会以LIFO…...

机器人----四元素

四元素 四元素的大小 [-1,1] 欧拉角转四元素...

IBM Spectrum LSF Application Center 提供单一界面来管理应用程序、用户、资源和数据

IBM Spectrum LSF Application Center 提供单一界面来管理应用程序、用户、资源和数据 亮点 ● 简化应用程序管理 ● 提高您的工作效率 ● 降低资源管理的复杂性 ● 深入了解流程 IBM Spectrum LSF Application Center 为集群用户和管理员提供了一个灵活的、以应用为中心的界…...

如何选择品牌推广公司?哪家好?收费标准及评价!

不管是什么品牌&#xff0c;推广对公司的成败起了很关键的作用。然而&#xff0c;面对市面上琳琅满目的品牌推广公司&#xff0c;如何选择一家既熟悉又靠谱的公司&#xff0c;成为许多企业主面临的难题。 作为一家手工酸奶品牌的创始人&#xff0c;目前全国也复制了100多家门店…...

JDeveloper 12C 官网下载教程

首先、我们要登录Oracle官网 Oracle 甲骨文中国 | 云应用和云平台 登录进去如果不是中文可以点击右上角带有国旗的图标就行更改&#xff0c;选择一个你能看懂的文字。 然后&#xff0c;点击“资源”—点击“开发人员下载” 然后&#xff0c;点击“开发工具” 这里有很多工具可…...

中英双语介绍美国的州:印第安纳州(Indiana)

中文版 印第安纳州简介 印第安纳州位于美国中西部地区&#xff0c;是一个以其农业、制造业和体育文化而著称的州。以下是对印第安纳州的详细介绍&#xff0c;包括其地理位置、人口、经济、教育、文化和主要城市。 地理位置 印第安纳州东临俄亥俄州&#xff0c;北接密歇根州…...

Flink实现准确和高效流处理的关键问题

时间相关: Watermark 水位线 水位线是插入到数据流中的一个标记,可以认为是一个特殊的数据。水位线主要的内容是一个时间戳,用来表示当前事件时间的进展。水位线是基于数据的时间戳生成的。水位线的时间戳必须单调递增,以确保任务的事件时间时钟一直向前推进,进展。水位线…...

isidentifier()方法——判断字符串是否为合法的Python标识符或变量名

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 语法参考 isidentifier()方法用于判断字符串是否是有效的Python标识符&#xff0c;还可以用来判断变量名是否合法。isidentifier()方法的语法格式如…...

天猫商品列表数据接口(Tmall.item_search)

天猫平台商品列表数据接口&#xff08;taobao.item_search&#xff09;是天猫开放平台提供的一个API接口&#xff0c;用于获取天猫平台上的商品列表数据。通过该接口&#xff0c;用户可以获取到商品的名称、价格、销量、评价等信息。下面将具体介绍这个接口的各个方面&#xff…...

React+TS前台项目实战(二十一)-- Search业务组件封装实现全局搜索

文章目录 前言一、Search组件封装1. 效果展示2. 功能分析3. 代码详细注释4. 使用方式 二、搜索结果展示组件封装1. 功能分析2. 代码详细注释 三、引用到文件&#xff0c;自行取用总结 前言 今天&#xff0c;我们来封装一个业务灵巧的组件&#xff0c;它集成了全局搜索和展示搜…...

SEO与AI的结合:如何用ChatGPT生成符合搜索引擎优化的内容

在当今数字时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;已成为每个网站和内容创作者都必须掌握的一项技能。SEO的主要目标是通过优化内容&#xff0c;使其在搜索引擎结果页面&#xff08;SERP&#xff09;中排名更高&#xff0c;从而吸引更多的流量。然而&#xf…...

【信息系统项目管理师知识点速记】组织通用管理:知识管理

23.3 知识管理 23.3.1 知识管理基础 知识管理是通过利用各种知识和技术手段,帮助组织和个人生产、分享、应用和创新知识,以形成知识优势并在个人、组织、业务目标、经济绩效和社会效益方面产生价值的过程。它能为组织带来知识增值,创造新的价值,提升决策效能和水平,是提…...

CM-UNet: Hybrid CNN-Mamba UNet for Remote Sensing Image Semantic Segmentation

论文&#xff1a;CM-UNet: Hybrid &#xff1a;CNN-Mamba UNet for Remote Sensing Image Semantic Segmentation 代码&#xff1a;https://github.com/XiaoBuL/CM-UNet Abstrcat: 由于大规模图像尺寸和对象变化&#xff0c;当前基于 CNN 和 Transformer 的遥感图像语义分割方…...

DP:子序列问题

文章目录 什么是子序列子序列的特点举例说明常见问题 关于子序列问题的几个例题1.最长递增子序列2.摆动序列3.最长递增子序列的个数4.最长数对链5.最长定差子序列 总结 什么是子序列 在计算机科学和数学中&#xff0c;子序列&#xff08;Subsequence&#xff09;是指从一个序列…...

Spring Data与多数据源配置

Spring Data与多数据源配置 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来探讨如何在Spring Data中配置和使用多个数据源。 在现代应用程序中&…...

【前端vue3】TypeScrip-类型推论和类型别名

类型推论 TypeScript里&#xff0c;在有些没有明确指出类型的地方&#xff0c;类型推论会帮助提供类型。 例如&#xff1a; 变量xiaoc被推断类型为string 如重新给xiaoc赋值数字会报错 let xiaoc "xiaoc"xiaoc 1111111111111如没有给变量指定类型和赋值&#xf…...

javaEE——Servlet

1.web开发概述 所谓web开发,指的是从网页中向后端程序发送请求,与后端程序进行交互 2.java后端开发环境搭建 web后端(javaEE)程序需要运行在服务器中的&#xff0c;这样前端才可以访问得到 3.服务器是什么&#xff1f; ①服务器就是一款软件&#xff0c;可以向其发送请求&#…...

Kotlin扩展函数(also apply run let)和with函数

also apply run let with的使用例子 private fun testOperator() {/*** also*/val person Person("ZhangSan", 18)person.also {// 通常仅仅打印使用, 也可以通过it修改it.name "ZhangSan1"println("also inner name: " it.name)}println(&qu…...

C语言笔记27 •单链表介绍•

1.链表的概念及结构 链表是⼀种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表 中的指针链接次序实现的。 2. 顺序表带来的问题 (1)中间/头部的插⼊删除&#xff0c;时间复杂度为O(N) (2)增容需要申请新空间&#xff0c;拷⻉数据&#xff…...

C++编程(五)单例模式 友元

文章目录 一、单例模式&#xff08;一&#xff09;概念&#xff08;二&#xff09;实现方式1. 饿汉式2. 懒汉式 二、友元&#xff08;一&#xff09;概念&#xff08;二&#xff09;友元函数1.概念2.语法格式3. 使用示例访问静态成员变量访问非静态成员变量 &#xff08;三&…...

012-GeoGebra基础篇-构造圆的切线

前边文章对于基础内容已经悉数覆盖了&#xff0c;这一篇我就不放具体的细节&#xff0c;若有需要可以复刻一下 目录 一、成品展示二、算式内容三、正确性检查五、文章最后 一、成品展示 二、算式内容 A(0,0) B(3,0) c: Circle(A,B) C(5,4) sSegment(A,C) DMidpoint(s) d: Circ…...

数据结构速成--查找

由于是速成专题&#xff0c;因此内容不会十分全面&#xff0c;只会涵盖考试重点&#xff0c;各学校课程要求不同 &#xff0c;大家可以按照考纲复习&#xff0c;不全面的内容&#xff0c;可以看一下小编主页数据结构初阶的内容&#xff0c;找到对应专题详细学习一下。 目录 …...

SpringMVC的基本使用

SpringMVC简介 SpringMVC是Spring提供的一套建立在Servlet基础上&#xff0c;基于MVC模式的web解决方案 SpringMVC核心组件 DispatcherServlet&#xff1a;前置控制器&#xff0c;来自客户端的所有请求都经由DispatcherServlet进行处理和分发Handler&#xff1a;处理器&…...

【PYG】Cora数据集分类任务计算损失,cross_entropy为什么不能直接替换成mse_loss

cross_entropy计算误差方式&#xff0c;输入向量z为[1,2,3]&#xff0c;预测y为[1]&#xff0c;选择数为2&#xff0c;计算出一大坨e的式子为3.405&#xff0c;再用-23.405计算得到1.405MSE计算误差方式&#xff0c;输入z为[1,2,3]&#xff0c;预测向量应该是[1,0,0]&#xff0…...

MyBatis-plus这么好用,不允许还有人不会

你好呀&#xff0c;我是 javapub. 做 Java 的同学都会用到的三件套&#xff0c;Spring、SpringMV、MyBatis。但是由于使用起来配置较多&#xff0c;依赖冲突频发。所有&#xff0c;各路大佬又在这上边做了包装&#xff0c;像我们常用的 SpringBoot、MyBatisPlus。 基于当前要…...

Linux驱动开发实战宝典:设备模型、模块编程、I2C/SPI/USB外设精讲

摘要: 本文将带你走进 Linux 驱动开发的世界,从设备驱动模型、内核模块开发基础开始,逐步深入 I2C、SPI、USB 等常用外设的驱动编写,结合实际案例,助你掌握 Linux 驱动开发技能。 关键词: Linux 驱动,设备驱动模型,内核模块,I2C,SPI,USB 一、Linux 设备驱动模型 Li…...

安全技术和防火墙

1、安全技术 1.1入侵检测系统 特点是不阻断网络访问&#xff0c;主要提供报警和事后监督。不主动介入&#xff0c;默默的看着你&#xff08;类似于监控&#xff09; 1.2入侵防御系统 透明模式工作&#xff0c; 数据包&#xff0c;网络监控&#xff0c;服务攻击&#xff0c;…...

Webpack: 开发 PWA、Node、Electron 应用

概述 毋庸置疑&#xff0c;对前端开发者而言&#xff0c;当下正是一个日升月恒的美好时代&#xff01;在久远的过去&#xff0c;Web 页面的开发技术链条非常原始而粗糙&#xff0c;那时候的 JavaScript 更多用来点缀 Web 页面交互而不是用来构建一个完整的应用。直到 2009年5月…...

python处理txt文件, 如果第一列和第二列的值在连续的行中重复,则只保留一行

处理txt文件, 如果第一列和第二列的值在连续的行中重复,则只保留一个实例,使用Python的内置函数来读取文件,并逐行检查和处理数据。 一个txt文件,里面的数据是893.554382324,-119.955825806,0.0299997832626,-0.133618548512,28.1155740884,112.876833236,46.7922,19.62582…...

C++17中引入了什么新的重要特性

C17是C标准的一个重要版本&#xff0c;它在语言核心和标准库中引入了许多新特性和改进&#xff0c;使得C编程更加现代化和高效。以下是C17中引入的一些重要新特性&#xff1a; 语言核心新特性 结构化绑定&#xff08;Structured Bindings&#xff09;&#xff1a; 结构化绑定…...

Andrej Karpathy提出未来计算机2.0构想: 完全由神经网络驱动!网友炸锅了

昨天凌晨&#xff0c;知名人工智能专家、OpenAI的联合创始人Andrej Karpathy提出了一个革命性的未来计算机的构想&#xff1a;完全由神经网络驱动的计算机&#xff0c;不再依赖传统的软件代码。 嗯&#xff0c;这是什么意思&#xff1f;全部原生LLM硬件设备的意思吗&#xff1f…...

用国内镜像安装docker 和 docker-compose (ubuntu)

替代方案&#xff0c;改用国内的镜像站(网易镜像&#xff09; 1.清除旧版本&#xff08;可选操作&#xff09; for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do apt-get remove $pkg; done 2.安装docker apt-get update 首先安装依赖 apt-g…...

Linux多线程【线程互斥】

文章目录 Linux线程互斥进程线程间的互斥相关背景概念互斥量mutex模拟抢票代码 互斥量的接口初始化互斥量销毁互斥量互斥量加锁和解锁改进模拟抢票代码&#xff08;加锁&#xff09;小结对锁封装 lockGuard.hpp 互斥量实现原理探究可重入VS线程安全概念常见的线程不安全的情况常…...

os实训课程模拟考试(大题复习)

目录 一、Linux操作系统 &#xff08;1&#xff09;第1关&#xff1a;Linux初体验 &#xff08;2&#xff09;第2关&#xff1a;Linux常用命令 &#xff08;3&#xff09;第3关&#xff1a;Linux 查询命令帮助语句 二、Linux之进程管理—&#xff08;重点&#xff09; &…...

QT/QML国际化:中英文界面切换显示(cmake方式使用)

目录 前言 实现步骤 1. 准备翻译文件 2. 翻译字符串 3.设置应用程序语言 cmake 构建方式 示例代码 总结 1. 使用 file(GLOB ...) 2. 引入其他资源文件 再次生成翻译文件 5. 手动更新和生成.qm文件 其他资源 前言 在当今全球化的软件开发环境中&#xff0c;应用程…...

设计模式在Java项目中的实际应用

设计模式在Java项目中的实际应用 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 引言 设计模式是软件开发中重要的思想工具&#xff0c;它提供了解决特定问题…...

uniapp做小程序内打开地图展示位置信息

使用场景&#xff1a;项目中需要通过位置信息打开地图查看当前位置信息在地图那个位置&#xff0c;每个酒店有自己的经纬度和详细地址&#xff0c;点击地图按钮打开内置地图如图 方法如下&#xff1a; <view class"dttu" click"openMap(info.locationY,info.…...

Element中的日期时间选择器DateTimePicker和级联选择器Cascader

简述&#xff1a;在Element UI框架中&#xff0c;Cascader&#xff08;级联选择器&#xff09;和DateTimePicker&#xff08;日期时间选择器&#xff09;是两个非常实用且常用的组件&#xff0c;它们分别用于日期选择和多层级选择&#xff0c;提供了丰富的交互体验和便捷的数据…...

Python创建MySQL数据库

一、使用Docker部署本地MySQL数据库 docker run --restartalways -p 3307:3306 --name mysql -e MYSOL_ROOT_PASSWORDlms123456 -d mysql:8.0.25 参数解析: 用户名:root 密码:lms123456 端口:3307 二、在Pycharm开发工具中配置连接MySQL数据库 三、安装zdppy_mysql pip inst…...

Laravel模型事件完全指南:触发应用程序的动态行为

标题&#xff1a;Laravel模型事件完全指南&#xff1a;触发应用程序的动态行为 在Laravel框架中&#xff0c;模型事件提供了一种优雅的方式来处理Eloquent模型生命周期中的各种关键时刻。通过监听和响应这些事件&#xff0c;开发者可以自动化许多常见的任务&#xff0c;如日志…...

Linux 安装pdfjam (PDF文件尺寸调整)

跟Ghostscript搭配使用&#xff0c;这样就可以将不同尺寸的PDF调整到相同尺寸合并了。 在 CentOS 上安装 pdfjam 需要安装 TeX Live&#xff0c;因为 pdfjam 是基于 TeX Live 的。以下是详细的步骤来安装 pdfjam&#xff1a; ### 步骤 1: 安装 EPEL 仓库 首先&#xff0c;安…...

adobe pdf设置默认打开是滚动而不是单页视图

上班公司用adobe pdf&#xff0c;自己还不能安装其它软件。 每次打开pdf&#xff0c;总是默认单页视图&#xff0c;修改滚动后&#xff0c;下次打开又 一样&#xff0c;有时候比较烦。 后面打开编辑->首选项&#xff0c; 如下修改&#xff0c;下次打开就是默认滚动了...

新一代哈弗H6究竟怎么样?能不能强势回归?

在还没拿销量周报、月报宣传的年代,哈弗H6是真真实实的做了几十个月的销量王者。累计已经被销售超400万台!前两天,新一代哈弗H6终于是迎来了上市发布会,那么这台车究竟怎么样?是不是诚意满满?相信很多人和我一样期待!这次新一代哈弗H6可以说是全方位的“进阶”,我觉得在…...

那么大的一个车卖24.9万?一起来看24款大众途昂

记得大众途昂刚上市的时候,所有看到这台车的人都会由衷感叹——“这车可真大”,那时的途昂还算是大众旗下偏高端的SUV,售价还要30多万起步。而如今,途昂还是那么大,但地位已不比当年,而且起售价格已经来到了24.9万。随着近年来汽车价格战的愈演愈烈,相比前几年,我们手持…...

npm : 无法加载文件 D:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本

安装npm时出现如下提示&#xff1a; 出现这个错误信息&#xff0c;是系统禁止执行PowerShell的脚本。 出现的原因是&#xff0c;系统默认的执行策略是Restricted&#xff08;默认设置&#xff09;&#xff0c;限制执行&#xff0c;所以会出现如上提示。 解决方法&#xff1a;…...

开源工具专题-04 Atlassian Crowd部署备份及迁移

开源工具专题-04 Atlassian Crowd部署备份及迁移 注&#xff1a; 本教程由羞涩梦整理同步发布&#xff0c;本人技术分享站点&#xff1a;blog.hukanfa.com转发本文请备注原文链接&#xff0c;本文内容整理日期&#xff1a;2024-05-29csdn 博客名称&#xff1a;五维空间-影子&…...

Big Demo Day第十三期活动即将启幕,Web3创新项目精彩纷呈,PEPE大奖等你抽取

5月28号在香港数码港 Big Demo Day第十三期 活动即将拉开帷幕&#xff0c;活动将汇集众多Web3领域的创新项目&#xff0c;为参会者带来一场科技与智慧交融的盛宴。在这里&#xff0c;你不仅能深入了解区块链、AI等前沿技术的最新应用&#xff0c;还能有机会赢取丰厚的PEPE大奖。…...

赶紧收藏!2024 年最常见 20道 Redis面试题(五)

上一篇地址&#xff1a;赶紧收藏&#xff01;2024 年最常见 20道 Redis面试题&#xff08;四&#xff09;-CSDN博客 九、Redis集群的主从复制模型是怎样的&#xff1f; Redis 集群的主从复制模型是一种数据冗余和高可用性策略&#xff0c;它允许数据在多个节点之间进行复制。…...