本文主要讲解在mysql中的sql的一些基本操作,例如查询,删除,更新,插入。参考网络资料。
操作和管理数据库使用专业的工具更方便,可以自行参考网络教程安装使用Navicat。
现在test数据库下,有如下products表,表中有id,product_name,prod_price三列。
1.简单查询
单列检索
单条SQL语句结束可以加或者不加英文分号(;),多条SQL语句之间一定要加分号。如果使用的是mysql命令行,必须加上分号。SQL不分大小写。一般会使用SQL关键字大写,所有的列和表名小写,这样容易阅读和调试。
-- 从products表中选取prod_name列
SELECT product_name FROM products;
多列检索
-- 在SELECT关键字后面给出多个列名,列名间用英文逗号隔开,最后一个列名不加逗号
SELECT id, product_name FROM products;
检索所有列
-- 方式一,把所有列名都查询出来
SELECT id, product_name,prod_price FROM products;
-- 方式二,使用通配符。如果数据量太大,不建议使用通配符,因为*通配符会触发全表扫描,影响查询性能
SELECT * FROM products;
2.去重
查询一共有多少种价格,需要把价格相同的去重。
-- 去重前
SELECT prod_price FROM products;
-- 使用distinct去重后,DISTINCT 会作用于所有的列,而不是只作用于某一个列,且DISTINCT 关键字需要放在select关键字后面,列名之前
SELECT DISTINCT prod_price FROM products;
SELECT DISTINCT id, product_name,prod_price FROM products;
3.限制查询结果的记录行数
SELECT 语句返回所有的结果,为了返回前几行,可以使用LIMIT子句。返回的结果超过n条则只显示limit规定的前n条。
-- 只返回前2行
SELECT id, product_name,prod_price FROM products LIMIT 2
返回某一区间的记录,使用LIMIT M,N。LIMIT 1,2 指MySQL返回从行1开始的2行。第一个数为开始位置,第二个数为要检索的行数。检索出来的第一行为行0,而不是行1。LIMIT 1,2是检索第二行而不是第一行。
-- 返回从行1开始的2行
SELECT id, product_name,prod_price FROM products LIMIT 1,2;
-- LIMIT 2 OFFSET 1,等同于 LIMIT 1,2,也是从第1行之后开始取2行,第一行为行0,而不是行1。
SELECT DISTINCT id, product_name,prod_price FROM products LIMIT 2 OFFSET 1
4.检索排序
排序使用关键字ORDER BY,默认是升序(ASC),可以使用关键字降序(DESC)。关键字ORDER BY后面跟的是列名,表示按照某一列排序,列名后跟的是升序或降序的关键字。如果使用了where字句,那么order by需要在where之后。
SELECT id, product_name,prod_price FROM products ORDER BY prod_price ASC
升序(ASC)或降序(DESC)关键字只作用于前面一个列名,如果想指定每个列的升降序规则,需对每个列指定关键字,如果多个列进行排序时,优先按照前面的字段规则排序。
-- 以下sql是先按prod_price 升序排序,当prod_price 一样时,再按id降序排序
SELECT id, product_name,prod_price FROM products ORDER BY prod_price ASC, id DESC
5.数据过滤
使用where关键字
在SELECT语句中,根据WHERE子句中指定的搜索条件进行过滤,WHERE子句在FROM子句之后。如果使用了where字句,那么order by需要在where之后。
-- 如果过滤条件是字符串类型,那么MySQL在执行匹配时默认不区分大小写
SELECT DISTINCT id, product_name,prod_price FROM products WHERE id=2;
-- 英文单引号用来表示字符串类型,如果将数字与字符串类型的列比较,需要限定引号。用来与数值列进行比较的值不用引号。
SELECT DISTINCT id, product_name,prod_price FROM products WHERE product_name = '香蕉';
比较可以有: 大于 >,小于 <,不等于 <>,等于 =,介于之间 BETWEEN ... AND ...
-- 查询价格大于等于6小于等于9的记录,BETWEEN必须指定两个值,并用AND关键字分隔,BETWEEN匹配范围内所有的值,包括指定的开始值和结束值
SELECT * FROM products WHERE prod_price BETWEEN 6 AND 9
空值检查用 IS NULL,空值null和空的字符串('')不相等。
-- 查询价格为空值null的结果
SELECT * FROM products WHERE prod_price is NULL;
使用and,or操作符组合查询:
当筛选条件有多个列时,可以使用and(且),or(或)操作符组合使用where字句的过滤条件。每多一个过滤条件,多添加一个AND(多个条件都同时满足),or(OR操作符和AND操作符不同,它指示MySQL匹配检索任一条件的行)。WHERE可包含任意数目的AND和OR操作符,允许两者结合进行复杂或高级过滤。SQL优先处理AND操作符,再处理OR操作符。可以使用圆括号明确分组相应操作符。
-- id大于2且价格等于8.88
SELECT DISTINCT id, product_name,prod_price FROM products WHERE id >=2 and prod_price=8.88;
-- id等于1或价格等于6.66
SELECT DISTINCT id, product_name,prod_price FROM products WHERE id =1 or prod_price=6.66;
-- WHERE可包含任意数目的AND和OR操作符,允许两者结合进行复杂或高级过滤。SQL优先处理AND操作符,再处理OR操作符。
-- 可以使用圆括号明确分组相应操作符。
SELECT DISTINCT id, product_name,prod_price FROM products WHERE id =1 or prod_price>6.66 or id >=2 and prod_price=8.88;
-- 上面的sql等价于
SELECT DISTINCT id, product_name,prod_price FROM products WHERE (id >=2 and prod_price=8.88) or id =1 or prod_price>6.66;
IN操作符
IN操作符用来指定条件范围,在范围的每个条件都可以进行匹配。取值全都括在圆括号中,和OR操作符有相同的功能,但是IN操作符的语法更清楚且更直观,IN操作符一般比OR操作符清单执行更快,IN最大优点可以包含其他SELECT语句,使得更动态建立WHERE子句。
SELECT DISTINCT id, product_name,prod_price FROM products WHERE id IN (2,4);
NOT 操作符
NOT是用来否定后跟条件的关键字,not后面只能跟关键字,例如:not null,not in。
LIKE操作符
用于模糊过滤,用于过滤条件不是精确的值,一般LIKE关键字配合百分号%通配符一起使用,如果%出现在前面,则表示模糊搜索某个字符串结尾的值,如果%出现在后面,则表示模糊搜索某个字符串开头的值。如果前后都有%,则表示出现某个字符串的值,%出现次数不限。
-- prod_price 列以.6结尾的记录
SELECT id, product_name,prod_price FROM products WHERE prod_price LIKE '%.6'
-- prod_price 列包含.6的记录
SELECT id, product_name,prod_price FROM products WHERE prod_price LIKE '%.6%'
--prod_price 列以6.6开头的记录
SELECT id, product_name,prod_price FROM products WHERE prod_price LIKE '6.6%'
-- prod_price 列以6开头中间包含8的记录(为了验证这条sql数据库修改了价格)%出现次数不限
SELECT id, product_name,prod_price FROM products WHERE prod_price LIKE ''6%8%''
![prod_price 列包含.6的搜索结果(https://upload-images.jianshu.io/upload_images/27308516-18d5062573d36d29.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
下划线(_)通配符
在MySQL中,下划线(_)通配符,是一个非常强大的工具,用于匹配单个字符。也就是说,它可以用来查找任意一个字符或一组字符,这些字符可以出现在任何地方。
例如,如果要查找名称中包含字母“a”和“b”的所有用户,可以使用以下查询语句
-- “_”通配符被放置在名称中的“b”的位置,它将匹配任何单个字符,而不管这个字符是什么。因此,这个查询会返回所有名称中包含字母“A”和“B”的用户
SELECT * FROM users WHERE name LIKE ‘%a_b%’;
在实际使用中,“_”通配符非常灵活。例如,如果想查找所有以“s”开头,然后是任意一个字符,然后是“t”结尾的名称的用户,可以使用以下查询语句:
SELECT * FROM users WHERE name LIKE ‘s_t’;
除了单个字符之外,“_”通配符还可以匹配一系列字符。例如,如果想查找所有以“123”开头,然后是任意两个字母,然后是“xyz”结尾的名称的用户,可以使用以下查询语句:
-- 在这个例子中,使用“_”通配符将匹配两个字符,因此,这个查询会返回所有以“123”开头,然后是任意两个字母,然后是“xyz”结尾的名称的用户
SELECT * FROM users WHERE name LIKE ‘123__xyz’;
需要注意的是,在使用“_”通配符时,语句中百分号“%”的位置很重要。如果将百分号放在“_”通配符前面,它将匹配零个或多个字符,而不是一个单独的字符。例如,如果通过以下查询来寻找所有名称中包含字母“A”和“B”的用户:
SELECT * FROM users WHERE name LIKE ‘%a_b%’;
7.正则表达式
正则表达式是用来匹配文本的特殊的串(字符集合)。MySQL用WHERE子句对正则表达式提供了初步的支持,允许你指定正则表达式,过滤SELECT检索出的数据。
基本字符匹配
在MySQL的WHERE子句中使用REGEXP来使用正则表达式,匹配时默认不区分大小写,如果想要区分大小写可以使用BINARY关键字:
-- 查询英文名中出现app字符串的水果
SELECT * FROM `products` WHERE en_name REGEXP 'app';
-- 区分大小写,查询英文名中出现App字符串的水果
SELECT * FROM `products` WHERE en_name REGEXP BINARY 'a';
REGEXP和LIKE的区别:
1、在匹配内容上的区别
LIKE要求整个数据都要匹配,用Like,必须这个字段的所有内容满足条件;
REGEXP只需要部分匹配即可,只需要有任何一个片段满足即可。
2、在匹配位置上的区别
LIKE 匹配整个列,如果被匹配的文本在列值中出现,LIKE 将不会找到它,相应的行也不会被返回(除非使用通配符);
REGEXP 在列值内进行匹配,如果被匹配的文本在列值中出现,REGEXP 将会找到它,相应的行将被返回,并且 REGEXP 能匹配整个列值(与 LIKE 相同的作用)。
3、速度区别
对于数据有10万多条的表,REGEXP 的速度比LIKE查询更快。
常用的匹配字符:
反斜杠(\)需要使用两个反斜杠\\,特殊字符,前面加\是为了转义,再加一个\,是MySQL自己转义。
重复元字符:
定位元字符
8.数据处理函数
拼接字段
CONCAT(str1, str2,...):将多个值拼接成一个值,放在select关键之后,条件关键字之前。
-- price_table 是拼接后新列的别名
SELECT CONCAT(product_name,':¥',prod_price,'/kg') as price_table FROM `products` ;
算数计算
对检索出来的数据进行计算:
-- 计算每种水果的费用
SELECT *, prod_price * quantity as cost FROM products;
文本处理常用函数
- Left():返回串左边的字符
- Length():返回串的长度
- Locate():找出串的一个子串
- Lower():将串转换为小写
- LTrim():去掉串左边的空格
- Right():返回串右边的字符
- Rtrim():去掉串右边的空格
- Soundex():返回串的SOUNDEX值,SOUNDEX是一个将任何文本串转换为描述其语音表示的字母数字模式的算法。SOUNDEX考虑了类似的发音字符和音节,使得能对串进行发音比较而不是字母比较。简单说就是SOUNDEX是根据发音来模糊检索。如通过Soundex(Y lie)可以检索到Y lee的结果。
- SubString() 返回子串的字符
- Upper() 将串转换为大写
日期和时间处理函数
- addDate():增加一个日期(天、周等),
-- 从当前时间增加两天,使用具体的数字方式
select ADDDATE(NOW(),2);
-- 从当前时间增加1周,使用时间间隔表达式的语法:INTERVAL expr unit,
-- 其中expr指的是时间的间隔数量,通常是规定的时间表达式,unit 指的是时间间隔的单位,比如年月日等等
select ADDDATE(NOW(),INTERVAL 1 WEEK);
- addTime():增加一个时间(时、分等),使用方式和ADDDATE()类似
- CurDate():返回当前日期,不包含时间。
- CurTime():返回当前时间,不包含日期
- Date():返回日期间的日期部分
-- 以下sql返回:2023-11-10
select DATE('2023-11-10 12:00:00');
- DateDiff():计算两个日期之差
- Date_Add():高度灵活的日期运算函数,使用方式和ADDDATE()类似
- Date_Fromat():返回一个格式化的日期或时间串
- Day():返回一个日期的天数部分
- DayOfWeek():对于一个日期,返回对应的星期几
- Hour():返回一个时间的小时部分
- Minute():返回一个时间的分钟部分
- Month():返回一个时间的月份部分
- Now():当前日期和时间
- Second():返回给定日期时间的秒
- Time():返回给定日期时间的时间,包含时分秒
- Yead():返回给定日期时间的年份
数值处理函数
- Abs():返回一个数的绝对值
- Cos():返回一个角度的余弦
- Exp():返回一个数的指数值
- Mod():返回除操作的余数
- Pi():返回圆周率
- Rand():返回一个随机数
- Sin():返回一个角度的正弦
- Sqrt():返回一个数的平方根
- Tan():返回一个角度的正切
9.汇总数据
聚集函数
聚集函数作用于行组上,计算和返回单个值。
例如:
- AVG():返回某列的平均值,只能用来确定特定数值列的平均值,而且列名必须作为函数参数给出。AVG()函数忽略列值为NULL的行。例如AVG(score1)
- COUNT():返回某列的行数,COUNT(*)是对表中的行的数目进行计数,包括NULL值。COUNT(column)对特定列具有的值进行计数,不包括NULL值。
- MAX():返回某列的最大值,忽略为NULL的行,如果用于文本数据,MAX返回最后一行
- MIN():返回某列的最小值,忽略为NULL的行,如果用于文本数据,MIN返回第一行
- SUM():返回某列值之和。
除了COUNT(*)不忽略NULL值,其它均忽略
10.组合查询
利用UNION操作符将多条SELECT语句组合成一个结果集。MySQL允许执行多个查询(多条Select)语句,并将结果作为单个查询结果集返回。
有两种基本情况,其中需要使用组合查询:
- 在单个查询中从不同的表返回类似结构的数据
- 在单个表执行多个查询,按单个查询返回数据
UNION操作符
UNION使用很简单,只需要在每条select语句之间使用UNION关键字就可以。
例如:
-- 查询单价大于6小于9的水果,还有产品id为2,3的水果
SELECT * FROM `products` WHERE prod_price>6 AND prod_price<9 UNION SELECT * FROM products WHERE id IN (2,3);
UNION使用规则
- UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔。
- UNON的每个查询必须包含相同的列、表达式或聚集函数。
- 列的类型不必完全相同,但必须是可以隐式转换。
UNION包含或去重(使用UNION ALL)
UNION从查询结果集中自动去除了重复行,在使用UNION时,默认重复的行被自动去除。如果不想去除重复行,可以使用以UNION ALL。例如:
-- 查询单价大于6小于9的水果,还有产品id为2,3的水果,不去重
SELECT * FROM `products` WHERE prod_price>6 AND prod_price<9 UNION ALL SELECT * FROM products WHERE id IN (2,3);
对组合查询结果进行排序
使用UNION查询时,只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。对于结果集,不存在用一种方式排序,又用另一种方式排序另一部分,因此不允许使用ORDER BY子句。
例如:
-- 查询单价大于6小于9的水果,还有产品id为2,3的水果,不去重,并按单价倒叙,id升序排序
SELECT * FROM `products` WHERE prod_price>6 AND prod_price<9
UNION ALL SELECT * FROM products WHERE id IN (2,3) ORDER BY prod_price DESC, ID ASC;
11.全文本搜索
并非所有引擎都支持全文本搜索。MySQL支持几种基本的数据库引擎,其中使用最多的是MyISAM和InnoDB,前者MyISAM支持全文本搜索,而后者InnoDB在5.6之前不支持。但是MyISAM没有事务支持,因此如果使用事务,转换为MyISAM将导致问题。最好的选择可能是使用MySQL 5.6 或更高的版本,它支持使用InnoDB的全文索引。早期版本只支持MyISAM表的全文索引。
全文索引只能用于InnoDB或MyISAM表,并且只能为CHAR、VARCHAR或text列创建。
启用全文本搜索
一般在创建时启用全文本搜索。例如:
-- 为支持en_name进行全文本搜索,必须加上FULLTEXT(en_name)进行索引。
-- 在定义之后,MySQL自动维护该索引。在增加、更新或删除行时,索引随之自动更新。
CREATE TABLE `products` (
`id` int(11) NOT NULL COMMENT '主键',
`product_name` varchar(255) DEFAULT NULL COMMENT '产品名称',
`prod_price` decimal(10,2) DEFAULT NULL COMMENT '产品价格',
`en_name` varchar(255) DEFAULT NULL COMMENT '英文名称',
`quantity` int(255) DEFAULT NULL COMMENT '数量',
PRIMARY KEY (`id`),
FULLTEXT KEY `en_name` (`en_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4
不要在导入数据时使用FULLTEXT,导完数据后,再修改表,定义FULLTEXT,可以缩短总耗时。
使用以下语句创建全文索引:
ALTER TABLE products ADD FULLTEXT(en_name);
进行全文本搜索
使用两个函数Match()和Against()执行全文本搜索,其中Match()指定被搜索的列,Against()指定要使用的搜索表达式。全文搜索排除行的原理是:全文本搜索可以使得较高等级的行先返回,排除那些等级为0的行,排序结果(按等级以降序排序)。
SELECT
id,
product_name,
en_name
FROM
products
WHERE
MATCH ( en_name ) Against ( 'produced' );
使用扩展查询
查询扩展用来设法放宽所返回的全文本搜索结果的范围。比如你想找到包含’Oranges’的搜索结果,只有一个英文名里面包含’GuangXi’,但你还想找出可能与你的搜索有关的其它所有行,即使它们不包含词Oranges。
SELECT
id,
product_name,
en_name
FROM
products
WHERE
MATCH ( en_name ) Against ( 'Oranges' WITH QUERY EXPANSION )
第一行包含Oranges,优先级最高第一条展示。第二行及以后与Oranges无关,但是通过相关词bananas和 are produced in 关键词,也能被检索出来。
它的执行顺序为:
- 首先进行一个基本的全文本搜索,找出与搜索条件匹配的所有行;
- MySQL检查这些匹配行并选择有用的词(MySQL是如何判断的?)
- 最后,MySQL再次进行全文本搜索,这次不仅使用原来的条件,而且还使用步骤二中有用的词。
- 这样扩展搜索能够增加返回的行数,但是也增加了不想要的行数目。
布尔文本搜索
布尔方式是全文搜索的另一种形式,可以提供:要匹配的词,要排除的词(如果包含该词就不返回,即使包含了其它指定词),排列提示(指定词的优先级),表达式分组。
使用方式: MATCH ( 列名 ) Against( ' 匹配的词 ' IN BOOLEAN MODE)
布尔方式即便没有FULLTEXT索引也可以使用,但是一种非常缓慢的操作,尽量少用,尤其在数据量大的时候。
全文布尔索引操作符:
+ :包含,词必须存在
- :排除,词必须不存在
> :包含,而且增加等级值
< :包含,且减少等级值
() :把词组成子表达式
~ :取消一个词的排序值
* :词尾的通配符
"" :定义一个短语
-- 这个匹配搜索必须包含bananas和oranges的行
SELECT
en_name
FROM
products
WHERE
MATCH ( en_name ) Against ( '+bananas +oranges' IN BOOLEAN MODE );
-- 这个搜索匹配短语bananas 或oranges而不是同时匹配两个词
SELECT
en_name
FROM
products
WHERE
MATCH ( en_name ) Against ( 'bananas oranges' IN BOOLEAN MODE );
-- 这个搜索匹配oranges 和bananas,增加前者的等级,降低后者的等级
SELECT
en_name
FROM
products
WHERE
MATCH ( en_name ) Against ( '>oranges <bananas' IN BOOLEAN MODE );
-- 搜索同时匹配词oranges 和bananas,降低后者的等级
SELECT
en_name
FROM
products
WHERE
MATCH ( en_name ) Against ( '+oranges +(<bananas)' IN BOOLEAN MODE );
有几点全文本搜索的重要说明。
- 在索引全文本数据时,默认短词被忽略且从索引中排除。(3个或以下字符为短词,可以更改)
- MySQL自带一个内建的非用词(stopword)列表,在全文本搜索数据时总是被忽略。(可以自定义覆盖该列表)
- 许多词出现频率过高,一个词出现在50%以上的行中,将它作为一个非用词忽略。(在布尔方式中不生效)
- 如果表行数少于3行,全文本搜索不返回结果(要么不出现,出现就大于等于50%)
- 忽略词中的单引号。例如,don’t索引为dont
12.插入数据
INSERT是用来插入行到数据库表的。插入可以用几种方式使用:
- 插入完整的行
- 插入行的一部分
- 插入多行
- 插入某些查询的结果
插入完整的行
INSERT INTO products
VALUES
( 5, '苹果梨', 4.78, 'ApplePairs are new plant and produced in DongBei', 0 );
存储到每个表列中的数据在VALUES子句中给出,对每个列必须提供一个值。如果某个列没有值,应该使用NULL(假设表对该列允许为空)。每个列必须按照表定义中出现次序填充。第一列id为Null时,需要在建表的时候id设置为自增长。
这种写法高度依赖于表中列的定义次序,而且以后表结构变动,SQL也会失效。
正常开发中更多使用以下SQL:
INSERT INTO products ( id, product_name, prod_price, en_name, quantity )
VALUES
( 6, '冻梨', 5.28, 'CoolPairs are new fruit and produced in DongBei', 0 );
这两条SQL结果完全相同,但是后者在表名后明确的给出了列名。插入时,会将VALUES响应值对应到列表中的对应项。这样values的值取决于表名后的列名顺序,这样更改表结构,INSERT语句依然正常工作。
values必须和列名数量一一对应,数据类型也要兼容。可以省略部分列,但必须满足两个条件之一:一是该列定义为NULL值,二是表定义中给出了默认值
插入多行
单条INSERT有多组值,每组值用一对圆括号括起来,用逗号隔开。这样执行速度比多个单条INSERT语句插入快。
INSERT INTO products ( id, product_name, prod_price, en_name, quantity )
VALUES
( 5, '苹果梨', 4.78, 'ApplePairs are new plant and produced in DongBei', 0 ),
( 6, '冻梨', 5.28, 'CoolPairs are new fruit and produced in DongBei', 0 );
插入某些查询的结果
INSERT SELECT 将一条SELECT语句的结果插入表中。INSERT SELECT的列名不需要完全匹配,只要数据类型能够兼容即可,但插入和查询的列的数量必须要一致。另外可以使用WHERE子句过滤插入的数据。
INSERT INTO products_copy1 ( id, product_name, prod_price, en_name, quantity ) SELECT
id,
product_name,
prod_price,
en_name,
quantity
FROM
products
13.更新和删除数据
更新数据
update语句用于更新表中的数据。可以更新特定的行,也可以更新所有行。
update语句的组成:
1.要更新的表
2.列名和对应的新值
3.确定要更新的过滤条件
-- UPDATE语句总是以要更新的表名开始,SET命令是用新值赋给被更新的列,WHERE限定哪一行,否则会更新这张表的所有选中列
-- 在更新多个列时,每个“列=值”用逗号分隔,最后一列不用逗号。
UPDATE products
SET quantity = 2,
prod_price=3.98
WHERE
id = 5;
IGNORE关键字,如果UPDATE语句更新多行,并且在一行或者多行时出现一个错误,则整个UPDATE操作被取消。可以使用IGNORE关键字:UPDATE INGORE products...
删除数据
DELETE语句从一个表中删除数据。DELETE FROM要求指定从中删除数据的表名。where子句过滤要删除的行。
DELETE不需要列名或通配符,它删除的是整行而不是删除列。如果要删除列,可以使用UPDATE,设置为NULL。
DELETE删除的是表的内容而不是表,如果不加WHERE限定,删除表中的所有行,所以一定要加限定条件WHERE。
DELETE
FROM
products
WHERE
id = 5;
更快地删除
当真的需要删除整个表内容,使用TRUNCATE TABLE语句,它完成相同工作,但速度更快。(TRUNCATE实际是删除原来的表,并重新创建一个表,而不是逐行删除表数据。)
更新和删除的指导原则:
- 除非确实打算更新和删除每一行,否则绝对不要使用不带WHERE子句的UPDATE或DELETE语句
- 保证每个表都有主键,尽可能像WHERE子句那样使用它
- 在对UPDATE或DELETE语句使用WHERE子句前,可以使用SELECT进行测试,保证过滤的是正确的记录,以防编写的WHERE子句不正确。
- 使用强制实施引用完整性的数据库(可以通过在数据库中定义外键来实现。当一个表的外键引用另一个表的主键时,数据库会检查是否存在引用关系,并在必要时防止删除或更新主表中的行),这样MySQL将不允许删除具有其他表相关联的数据的行.
以下是一个使用外键约束的例子,确保当删除一个学生时,与之关联的成绩记录也将被删除:
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(50)
);
CREATE TABLE grades (
id INT PRIMARY KEY,
student_id INT,
grade INT,
FOREIGN KEY (student_id) REFERENCES students(id) ON DELETE CASCADE
);
在上面的例子中,grades表中的student_id列被定义为外键,并且在students表中的id列上有一个主键约束。当在students表中删除一个行时,与之关联的grades表中的行也将被删除,因为我们使用了ON DELETE CASCADE选项。这个选项确保了引用完整性,因为它会防止删除students表中的行,如果在grades表中有与之关联的行。
参考:https://blog.csdn.net/Dawn510/article/details/109609278