From 2a682effc48a0eb4f05a79bf8de733c73386eba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A8=8A=E5=B0=8F=E9=83=AD?= <2966479092@qq.com> Date: Thu, 23 Feb 2023 10:19:01 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...60\346\215\256\347\261\273\345\236\213.md" | 698 ++++++++++++++++++ 1 file changed, 698 insertions(+) create mode 100644 "47\346\250\212\345\260\217\351\203\255/20230216 SQL\350\257\255\345\217\245,\346\225\260\346\215\256\347\261\273\345\236\213.md" diff --git "a/47\346\250\212\345\260\217\351\203\255/20230216 SQL\350\257\255\345\217\245,\346\225\260\346\215\256\347\261\273\345\236\213.md" "b/47\346\250\212\345\260\217\351\203\255/20230216 SQL\350\257\255\345\217\245,\346\225\260\346\215\256\347\261\273\345\236\213.md" new file mode 100644 index 0000000..1ebf7af --- /dev/null +++ "b/47\346\250\212\345\260\217\351\203\255/20230216 SQL\350\257\255\345\217\245,\346\225\260\346\215\256\347\261\273\345\236\213.md" @@ -0,0 +1,698 @@ +# 第4章 SQL语句 + +SQL:结构化查询语言,(Structure Query Language),专门用来操作/访问数据库的通用语言。 + +## 4.1 SQL的分类 + +| 名称 | 解释 | 命令 | +| :-------------------: | :-------------------------------------------: | :----------------------------------------------------------: | +| DDL (数据定义语言) | 定义和管理数据对象结构,如数据库,数据表等 | 创建(create),修改(alter),删除(drop) show(展示)结构 | +| DML (数据操作语言) | 用于操作数据库对象中所包含的数据 | 增(insert),删(delete),改(update) 数据 | +| DQL (数据查询语言) | 用于查询数据库数据 | 查(select) | +| DCL (数据控制语 言) | 用于管理数据库的语言,包括管理权限及数 据更改 | grant(授权),commit(确认),rollback(回滚) | + +其他语句:USE语句,SHOW语句,SET语句等。这类的官方文档中一般称为命令。 + +## 4.2 SQL语法规范 + +(1)mysql的sql语法不区分大小写 + +- A:数据库的表中的数据是否区分大小写。这个的话要看表格的字段的数据类型、编码方式以及校对规则。 + +​ ci(大小写不敏感),cs(大小写敏感),_bin(二元,即比较是基于字符编码的值而与language无关,区分大小写) + +- B:sql中的关键字,比如:create,insert等,不区分大小写。但是大家习惯上把关键字都“大写”。 + + +(2)命名时:尽量使用26个英文字母大小写,数字0-9,下划线,不要使用其他符号 + +(3)建议不要使用mysql的关键字等来作为**表名、字段名、数据库**名等,如果不小心使用,请在SQL语句中使用`(飘号/反引号)引起来,说明 : 反引号用于区别MySQL保留字与普通字符而引入的 (键盘esc下面的键) + +(4)数据库和表名、字段名等对象名中间不要包含空格 + +```mysql +create database my mxdx; + +ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'mxdx' at line 1 +``` + +(5)同一个mysql软件中,数据库不能同名,同一个库中,表不能重名,同一个表中,字段不能重名 + +```mysql +mysql> show databases; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| mxdx | +| mysql | +| performance_schema | +| sys | ++--------------------+ +5 rows in set (0.00 sec) + +mysql> create database mxdx; +ERROR 1007 (HY000): Can't create database 'mxdx'; database exists +``` + +```mysql +mysql> show tables; ++---------------------+ +| Tables_in_mxdx | ++---------------------+ +| student | +| temp | ++---------------------+ +2 rows in set (0.00 sec) + +mysql> create table temp(id int); +ERROR 1050 (42S01): Table 'temp' already exists +``` + +``` +mysql> create table tt( + -> id int, + -> id int + -> ); +ERROR 1060 (42S21): Duplicate(重复) column name 'id' +``` + +## 4.3 SQL脚本中如何加注释 + +SQL脚本中如何加注释 + +- 单行注释:#注释内容(mysql特有的) + +- 单行注释:--空格注释内容 其中--后面的空格必须有 + +- 多行注释:/* 注释内容 */ + +```mysql +create table tt( + id int, #编号 + `name` varchar(20), -- 姓名 + gender enum('男','女') + /* + 性别只能从男或女中选择一个, + 不能两个都选,或者选择男和女之外的 + */ +); +``` + +## 4.4 mysql脚本中的标点符号 + +mysql脚本中标点符号的要求如下: + +1. 本身成对的标点符号必须成对,例如:(),'',""。 + +2. 所有标点符号必须英文状态下半角输入方式下输入。 + + +几个特殊的标点符号: + +1. 小括号(): + - 在创建表、添加数据、函数使用、子查询、计算表达式等等会用()表示某个部分是一个整体结构。 + - 思考: 2+3 * 6 =20 和 (2+3) * 6 =30的区别 + +2. 单引号'':**字符串和日期类型的数据值使用单引号''引起来**,数值类型的不需要加标点符号。 +3. “2023-10--10” +4. 双引号"":列的别名可以使用引号"",**给表名取别名不要用引号**。 +5. 在MySQL中双引号通常等价于单引号 + + +```sql +create table tt( + id int + ; + +ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 2 +``` + +```mysql +create table temp( + c char +); +insert into temp values('尚) ; #缺一半单引号 + +insert into temp values(‘尚’) ; #标点符号是中文 +``` + +```mysql +mysql> select * from student; ++------+------+ +| id | name | ++------+------+ +| 1 | 张三 | +| 2 | 李四 | ++------+------+ +2 rows in set (0.00 sec) + +mysql> select id "学号",name "姓名" from student; ++------+------+ +| 学号 | 姓名 | ++------+------+ +| 1 | 张三 | +| 2 | 李四 | ++------+------+ +2 rows in set (0.00 sec) +``` + +# 第5章 MySQL支持的数据类型 + +## 5.1 数值类型:包括整数和小数 + +数值类型主要用来存储数字,不同的数值类型提供不同的取值范围,可以存储的值范围越大,所需要的存储空间也越大。 + +对于MySQL中的数值类型,还要做如下说明: + +- 关键字INT是INTEGER的同义词。 +- 关键字DEC和FIXED是DECIMAL的同义词。 + +### 5.1.1 整数类型 + +![image-20211127205706588](第4章 SQL语句.assets/image-20211127205706588.png) + +**说明:** + +对于整数类型,MySQL还支持在类型名称后面加小括号(M),而小括号中的M表示显示宽度,M的取值范围是(0, 255)。int(M)这个M在字段的属性中指定了unsigned(无符号)和zerofill(零填充)的情况下才有意义。表示当整数值不够M位时,用0填充。如果整数值超过M位但是没有超过当前数据类型的范围时,就按照实际位数存储。当M宽度超过当前数据类型可存储数值范围的最大宽度时,也是以实际存储范围为准。 + +```mysql +#演示整数类型 +#创建一个表格,表格的名称“t_int”, +#包含两个字段i1和i2,分别是int和int(2)类型 +#create table t_int(i1 int,i2 int(2)); +create table t_int( + i1 int, + i2 int(2) #没有unsigned zerofill,(2)没有意义 +); + +#查看当前数据库的所有表格 +show tables; +show tables from 数据库名; + +#查看表结构 +desc 表名称; +desc t_int; + +mysql> desc t_int; ++-------+------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++-------+------+------+-----+---------+-------+ +| i1 | int | YES | | NULL | | +| i2 | int | YES | | NULL | | ++-------+------+------+-----+---------+-------+ +2 rows in set (0.01 sec) + +#创建一个表格,表格的名称“t_int2”, +#包含两个字段i1和i2,分别是int和int(2)类型 +create table t_int2( + i1 int, + i2 int(2) unsigned zerofill +); + +mysql> desc t_int2; ++-------+--------------------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++-------+--------------------------+------+-----+---------+-------+ +| i1 | int | YES | | NULL | | +| i2 | int(2) unsigned zerofill | YES | | NULL | | ++-------+--------------------------+------+-----+---------+-------+ +2 rows in set (0.01 sec) + +#添加数据到表格中 +insert into 表名称 values(值列表); +insert into t_int values(1234,1234); +insert into t_int2 values(1234,1234); + +#查询数据 +select * from 表名称; +select * from t_int; +select * from t_int2; + +#添加数据到表格中 +insert into 表名称 values(值列表); +insert into t_int values(1,1); +insert into t_int2 values(1,1); + +insert into t_int values(12222228854225548778455,12222228854225548778455); +mysql> insert into t_int values(12222228854225548778455,12222228854225548778455); +ERROR 1264 (22003): Out of range value for column 'i1' at row + +``` + + + +### 5.1.2 小数类型 + +MySQL中使用浮点数和定点数来表示小数。 + +浮点数有两种类型:单精度浮点数(FLOAT)和双精度浮点数(DOUBLE),定点数只有DECIMAL。浮点数和定点数都可以用(M,D)来表示。 + +- M是精度,表示该值总共显示M位,包括整数位和小数位,对于FLOAT和DOUBLE类型来说,M取值范围为0~255,而对于DECIMAL来说,M取值范围为0~65。 +- D是标度,表示小数的位数,取值范围为0~30,同时必须<=M。 + +DECIMAL实际是以字符串形式存放的,在对精度要求比较高的时候(如货币、科学数据等)使用DECIMAL类型会比较好。浮点数相对于定点数的优点是在长度一定的情况下,浮点数能够表示更大的数据范围,它的缺点是会引起精度问题。 + +![image-20211127210358326](第4章 SQL语句.assets/image-20211127210358326.png) + +```mysql +#演示小数类型 +#创建表格 +create table t_double( + d1 double, + d2 double(5,2) #-999.99~999.99 +); + +#查看表结构 +desc t_double; + +#添加数据 +insert into t_double values(2.5,2.5); + +#查看数据 +select * from t_double; +mysql> select * from t_double; ++------+------+ +| d1 | d2 | ++------+------+ +| 2.5 | 2.50 |#d2字段小数点后不够2位用0补充 ++------+------+ +1 row in set (0.00 sec) + +#添加数据 +insert into t_double values(2.5526,2.5526); +insert into t_double values(2.5586,2.5586); + +mysql> select * from t_double; ++--------+------+ +| d1 | d2 | ++--------+------+ +| 2.5 | 2.50 | +| 2.5526 | 2.55 |#小数点后有截断现象,并且会四舍五入 +| 2.5586 | 2.56 |#小数点后有截断现象,并且会四舍五入 ++--------+------+ +3 rows in set (0.00 sec) + + +#添加数据 +insert into t_double values(12852.5526,12852.5526); + +#d2字段整数部分超过(5-2=3)位,添加失败 +mysql> insert into t_double values(12852.5526,12852.5526); +ERROR 1264 (22003): Out of range value for column 'd2' at row 1 + + +#创建表格 +create table t_decimal( + d1 decimal, #没有指定(M,D)默认是(10,0) + d2 decimal(5,2) +); + + +#查看表结构 +desc t_decimal; +mysql> desc t_decimal; ++-------+---------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++-------+---------------+------+-----+---------+-------+ +| d1 | decimal(10,0) | YES | | NULL | | +| d2 | decimal(5,2) | YES | | NULL | | ++-------+---------------+------+-----+---------+-------+ +2 rows in set (0.01 sec) + +#添加数据 +insert into t_decimal values(2.5,2.5); + +#查看数据 +select * from t_decimal; +mysql> select * from t_decimal; ++------+------+ +| d1 | d2 | ++------+------+ +| 3 | 2.50 | #d1字段小数点后截断 ++------+------+ +1 row in set (0.00 sec) + +insert into t_decimal values(12852.5526,12852.5526); + +-- 把小数赋值给整数类型的字段时,会截断小数部分,考虑四舍五入 +insert into t_int2 values(1.5,1.5); +``` + + + +## 5.2 字符串类型 + +MySQL的字符串类型有CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM、SET等。MySQL的字符串类型可以用来存储文本字符串数据,还可以存储二进制字符串。 + +文本字符串类型: + +![image-20211127210547156](第4章 SQL语句.assets/image-20211127210547156.png) + +二进制字符串类型: + +![image-20211127210608685](第4章 SQL语句.assets/image-20211127210608685.png) + +### 1、CHAR(M)为固定长度的字符串 + +CHAR(M)为固定长度的字符串, M表示最多能存储的字符数,取值范围是0~255个字符,如果未指定(M)表示只能存储1个字符。例如CHAR(4)定义了一个固定长度的字符串列,其包含的字符个数最大为4,如果存储的值少于4个字符,右侧将用空格填充以达到指定的长度,当查询显示CHAR值时,尾部的空格将被删掉。 + +```mysql +create table temp( + c1 char, + c2 char(3) +); +``` + +```mysql +insert into temp values('男','女');#成功 + +insert into temp values('桃花岛','桃花岛');#失败 +ERROR 1406 (22001): Data too long for column 'c1' at row 1 + +insert into temp values('男','桃花岛');#成功 +``` + +### 2、VARCHAR(M)为可变长度的字符串 + +- M表示最多能存储的字符数,最大范围由字符集及M共同决定 +- M不可缺省,必须指定(M),否则报错。 +- 实际长度达不到M值时,以实际长度为准。 +- VARBINARY类型的数据除了存储数据本身外,还需要1或2个字节来存储数据的字节数。 + +```mysql +create table temp( + name varchar #错误 +); +``` + +```mysql +create table temp( + name varchar(3) #最多不超过3个字符 +); +``` + +```mysql +insert into temp values('桃花岛'); + +insert into temp values('桃花岛真好');#ERROR 1406 (22001): Data too long for column 'name' at row 1 + +insert into temp values('好'); +``` + +```mysql +drop table temp; +create table temp( + name varchar(65535) +); +#ERROR 1074 (42000): Column length too big for column 'name' (max = 21845); use BLOB or TEXT instead +因为当前的表是UTF8,一个汉字占3个字节 +``` + +![image-20211127210826463](第4章 SQL语句.assets/image-20211127210826463.png) + +**使用场景**: + +- 身份证号、手机号码、QQ号、用户名username、密码password、银行卡号等固定长度的文本字符串适合使用CHAR类型; +- 评论、朋友圈、微博不定长度的文本字符串更适合使用VARCHAR类型。 + +## 5.3 日期时间类型 + +![image-20211127212047635](第4章 SQL语句.assets/image-20211127212047635.png) + +- 如果仅仅是表示年份信息,可以只使用YEAR类型,这样更节省空间,格式为“YYYY”,例如“2022”。YEAR允许的值范围是1901~2155。 +- 如果要表示年月日,可以使用DATE类型,格式为“YYYY-MM-DD”,例如“2022-02-04”。 +- 如果要表示时分秒,可以使用TIME类型,格式为“HH:MM:SS”,例如“10:08:08”。 +- 如果要表示年月日时分秒的完整日期时间,可以使用DATATIME类型,格式为“YYYY-MM-DD HH:MM:SS”,例如“2022-02-04 10:08:08”。 +- 如果需要经常插入或更新日期时间为系统日期时间,则通常使用TIMESTAMP类型,格式为“YYYY-MM-DD HH:MM:SS”,例如“2022-02-04 10:08:08”。TIMESTAMP与DATETIME的区别在于TIMESTAMP的取值范围小,只支持1970-01-01 00:00:01 UTC至2038-01-19 03:14:07 UTC范围的日期时间值,其中UTC是世界标准时间,并且TIMESTAMP类型的日期时间值在存储时会将当前时区的日期时间值转换为时间标准时间值,检索时再转换回当前时区的日期时间值,这会更友好。而DATETIME则只能反映出插入时当地的时区,其他时区的人查看数据必然会有误差的。另外,TIMESTAMP的属性受MySQL版本和服务器SQLMode的影响很大。 + +```mysql +create table temp( + d1 datetime, + d2 timestamp +); +``` + +```mysql +insert into temp values('2021-9-2 14:45:52','2021-9-2 14:45:52'); +``` + +```mysql +#修改当前的时区 +set time_zone = '+9:00'; +``` + +```mysql +insert into temp values('202192144552','202192144552'); +#ERROR 1292 (22007): Incorrect datetime value: '202192144552' for column 'd1' at row 1 +``` + +```mysql +insert into temp values('20210902144552','20210902144552'); +``` + +```mysql +insert into temp values('2021&9&2 14%45%52','2021#9#2 14@45@52'); +``` + +```mysql +create table temp( + d year +); +``` + +```mysql +insert into temp values(2021); +insert into temp values(85); +insert into temp values(22); +insert into temp values(69); +insert into temp values(0); +insert into temp values('0'); +``` + +```mysql +mysql> select * from temp; ++------+ +| d | ++------+ +| 2021 | +| 1985 | +| 2022 | ++------+ +3 rows in set (0.00 sec) +``` + +## 5.4 Enum和Set类型 + +无论是数值类型、日期类型、普通的文本类型,可取值的范围都非常大,但是有时候我们指定在固定的几个值范围内选择一个或多个,那么就需要使用ENUM枚举类型和SET集合类型了。 + +比如性别只有“男”或“女”;上下班交通方式可以有“地铁”、“公交”、“出租车”、“自行车”、“步行”等。 + +枚举和集合类型字段声明的语法格式如下: + +- 字段名ENUM(‘值1’,‘值2’,…‘值n’) + + +- 字段名 SET(‘值1’,‘值2’,…‘值n’) + + +ENUM类型的字段在赋值时,只能在指定的枚举列表中取值,而且一次只能取一个。枚举列表最多可以有65535个成员。ENUM值在内部用整数表示,每个枚举值均有一个索引值, MySQL存储的就是这个索引编号。例如,定义ENUM类型的列(‘first’, ‘second’, ‘third’)。 + +![image-20211127211743925](第4章 SQL语句.assets/image-20211127211743925.png) + +SET类型的字段在赋值时,可从定义的值列表中选择1个或多个值的组合。SET列最多可以有64个成员。SET值在内部也用整数表示,分别是1,2,4,8……,都是2的n次方值,因为这些整数值对应的二进制都是只有1位是1,其余是0。 + +![image-20211127211806889](第4章 SQL语句.assets/image-20211127211806889.png) + + **演示枚举类型:** + +```mysql +create table temp( + gender enum('男','女'), + hobby set('睡觉','打游戏','泡妞','写代码') +); +``` + +```mysql +insert into temp values('男','睡觉,打游戏'); #成功 + +insert into temp values('男,女','睡觉,打游戏'); #失败 +#ERROR 1265 (01000): Data truncated for column 'gender' at row 1 + +insert into temp values('妖','睡觉,打游戏');#失败 +#ERROR 1265 (01000): Data truncated for column 'gender' at row 1 + +insert into temp values('男','睡觉,打游戏,吃饭'); +#ERROR 1265 (01000): Data truncated for column 'hobby' at row 1 +``` + +```mysql +#文本类型中的枚举和集合 +#枚举:固定的几个字符串值,从中选择一个 +#集合:固定的几个字符串值,从中选择任意几个 + +create table t_enum_set( + gender enum('男','女'), + hobby set('游戏','睡觉','打代码','运动') +); + +#查看表结构 +desc t_enum_set; + +mysql> desc t_enum_set; ++--------+------------------------------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++--------+------------------------------------+------+-----+---------+-------+ +| gender | enum('男','女') | YES | | NULL | | +| hobby | set('游戏','睡觉','打代码','运动') | YES | | NULL | | ++--------+------------------------------------+------+-----+---------+-------+ +2 rows in set (0.01 sec) + + +#添加数据 +insert into t_enum_set +values('男','游戏'); + +#查看数据 +select * from t_enum_set; + +#添加数据 +insert into t_enum_set +values('男,女','游戏,睡觉'); + +mysql> insert into t_enum_set + -> values('男,女','游戏,睡觉'); +ERROR 1265 (01000): Data truncated for column 'gender' at row 1 + +#添加数据 +insert into t_enum_set +values('男','游戏,睡觉'); + +#添加数据 +insert into t_enum_set +values('妖','游戏,睡觉'); +mysql> insert into t_enum_set + -> values('妖','游戏,睡觉'); +ERROR 1265 (01000): Data truncated for column 'gender' at row 1 + +#添加数据 +insert into t_enum_set +values('男','游戏,睡觉,做饭'); +mysql> insert into t_enum_set + -> values('男','游戏,睡觉,做饭'); +ERROR 1265 (01000): Data truncated for column 'hobby' at row 1 + +insert into t_enum_set +values(2, 2); + +mysql> select * from t_enum_set; ++--------+-----------+ +| gender | hobby | ++--------+-----------+ +| 男 | 游戏 | +| 男 | 游戏,睡觉 | +| 女 | 睡觉 | ++--------+-----------+ +3 rows in set (0.00 sec) + +insert into t_enum_set +values(2, 5); +#5 可以看出 1和4的组合,00001 和 0100,0101 + +insert into t_enum_set +values(2, 7); +mysql> select * from t_enum_set; ++--------+------------------+ +| gender | hobby | ++--------+------------------+ +| 男 | 游戏 | +| 男 | 游戏,睡觉 | +| 女 | 睡觉 | +| 女 | 游戏,打代码 | +| 女 | 游戏,睡觉,打代码 | ++--------+------------------+ +5 rows in set (0.00 sec) + +insert into t_enum_set +values(2, 15); +mysql> select * from t_enum_set; ++--------+-----------------------+ +| gender | hobby | ++--------+-----------------------+ +| 男 | 游戏 | +| 男 | 游戏,睡觉 | +| 女 | 睡觉 | +| 女 | 游戏,打代码 | +| 女 | 游戏,睡觉,打代码 | +| 女 | 游戏,睡觉,打代码,运动 | ++--------+-----------------------+ +6 rows in set (0.00 sec) + +insert into t_enum_set +values(2, 25); +mysql> insert into t_enum_set + -> values(2, 25); +ERROR 1265 (01000): Data truncated for column 'hobby' at row 1 +``` + +## 5.5 数据字段属性 + + **unsigned** + +- 无符号的 + +- 声明该数据列不允许负数 + + **ZEROFILL** + +- 0填充的 + +- 不足位数的用0来填充 , 如int(3),5则为005 + +**auto_increment** + +- 自动增长的 , 每添加一条数据 , 自动在上一个记录数上加 1(默认) +- 通常用于设置主键 , 且为整数类型 +- 可定义起始值和步长 + - 当前表设置步长(AUTO_INCREMENT=100) : 只影响当前表 + - SET @@auto_increment_increment=5 ; 影响所有使用自增的表(全局) + +**NULL 和 NOT NULL** + +- 默认为NULL , 即没有插入该列的数值 +- 如果设置为NOT NULL , 则该列必须有值 + +**DEFAULT** + +- 默认的 + +- 用于设置默认值 + +- 例如,性别字段,默认为"男" , 否则为 "女" ; 若无指定该列的值 , 则默认值为"男"的值 + +- ```mysql + -- 目标 : 创建一个school数据库 + -- 创建学生表(列,字段) + -- 学号int 登录密码varchar(20) 姓名,性别varchar(2),出生日期(datatime),家庭住 址,email + -- 创建表之前 , 一定要先选择数据库 + CREATE TABLE IF NOT EXISTS `student` ( + `id` int(4) NOT NULL AUTO_INCREMENT COMMENT '学号', + `name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名', + `pwd` varchar(20) NOT NULL DEFAULT '123456' COMMENT '密码', + `sex` varchar(2) NOT NULL DEFAULT '男' COMMENT '性别', + `birthday` datetime DEFAULT NULL COMMENT '生日', + `address` varchar(100) DEFAULT NULL COMMENT '地址', + `email` varchar(50) DEFAULT NULL COMMENT '邮箱', + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 + -- 查看数据库的定义 + SHOW CREATE DATABASE school; + -- 查看数据表的定义 + SHOW CREATE TABLE student; + -- 显示表结构 + DESC student; + -- 设置严格检查模式(不能容错了) + SET sql_mode='STRICT_TRANS_TABLES'; + ``` + + -- Gitee From dc070fe267d3fe6518e8d89b0f72776cc0fd7d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A8=8A=E5=B0=8F=E9=83=AD?= <2966479092@qq.com> Date: Thu, 23 Feb 2023 10:26:02 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E7=AC=AC=E4=BA=8C=E6=AC=A1=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../20230218 SQL\347\272\246\346\235\237.md" | 391 ++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 "47\346\250\212\345\260\217\351\203\255/20230218 SQL\347\272\246\346\235\237.md" diff --git "a/47\346\250\212\345\260\217\351\203\255/20230218 SQL\347\272\246\346\235\237.md" "b/47\346\250\212\345\260\217\351\203\255/20230218 SQL\347\272\246\346\235\237.md" new file mode 100644 index 0000000..1b7ac73 --- /dev/null +++ "b/47\346\250\212\345\260\217\351\203\255/20230218 SQL\347\272\246\346\235\237.md" @@ -0,0 +1,391 @@ +# 约束 主键、唯一、非空、默认、自增、外键 + +1、主键约束 +(1)关键字是primary key +(2)特点 +A:每一个表只能有一个主键约束 +B:主键约束的字段值是不允许为null,也不允许重复的 +*/ + +CREATE TABLE teacher( + tid INT PRIMARY KEY, + tname VARCHAR(20) +); + +INSERT INTO teacher VALUES(1,'柴'); +/* +上面的insert语句执行两遍,就会报错 +错误代码: 1062 +Duplicate(重复的) entry(输入) '1' +for key 'teacher.PRIMARY' + +意思:违反了主键约束 +*/ + +INSERT INTO teacher VALUES(2,'柴'); +INSERT INTO teacher VALUES(NULL,'王'); +/* +错误代码: 1048 +Column 'tid' cannot be null +主键不允许为null +*/ + + +CREATE TABLE teacher( + tid INT PRIMARY KEY, + tname VARCHAR(20) PRIMARY KEY +); +/* +错误代码: 1068 +Multiple(重复的,多倍的) primary key defined(定义)*/ + + +/* +需求: + 有一个学生表: + stu(sid,sname,tel) + course(cid,cname,description) + xuanke(sid,cid,score) 记录某个学生选择的某门课的成绩 + + stu表可以选择sid作为主键 + course表可以选择cid作为主键 + xuanke表可以选择sid + +*/ +CREATE TABLE stu( + sid INT PRIMARY KEY, + sname VARCHAR(20), + tel CHAR(11) +); +CREATE TABLE course( + cid INT PRIMARY KEY, + cname VARCHAR(50), + description VARCHAR(100) +); +INSERT INTO stu VALUES(1,'张三','10086'); +INSERT INTO stu VALUES(2,'李四','10010'); + +INSERT INTO course VALUES(1,'java','基础课'); +INSERT INTO course VALUES(2,'mysql','高级课'); + +/* +表达 张三,选择了java和mysql课程,成绩分别为89和96分 + 李四,选择了java和mysql课程,成绩分别为88和100分 +*/ +/* +create table xuanke( + sid int primary key, + cid int PRIMARY KEY, + score int +);*/ +/* +错误代码: 1068 +Multiple primary key defined +*/ +/* +create table xuanke( + sid int primary key, + cid int, + score int +); +insert into xuanke values(1,1,89); +INSERT INTO xuanke VALUES(1,2,96);*/ +/* +错误代码: 1062 +Duplicate entry '1' for key 'xuanke.PRIMARY' +*/ +/* +create table xuanke( + id int primary key, + sid int , + cid int, + score int +);*/ +#解决方案一,单独使用一个id列当主键 + +#解决方案二:复合主键 +CREATE TABLE xuanke( + sid INT , + cid INT, + score INT, + PRIMARY KEY(sid,cid) #它俩的组合不能为NULL,并且唯一 +); +INSERT INTO xuanke VALUES(1,1,89); +INSERT INTO xuanke VALUES(1,2,96); +INSERT INTO xuanke VALUES(2,1,88); +INSERT INTO xuanke VALUES(2,2,100); + + +#建表后增加主键约束 +ALTER TABLE 表名称 ADD PRIMARY KEY(字段列表); +#(字段列表)如果是一个字段,就是一个字段是主键 +#(字段列表)如果是多个字段,就是复合主键 + +#例如 +ALTER TABLE student ADD PRIMARY KEY(sid); + +#如果想要删除主键约束 +ALTER TABLE 表名称 DROP PRIMARY KEY; + +ALTER TABLE student DROP PRIMARY KEY; + + +/* +如果希望某个字段的值,是唯一的,但不要求非空,它也不是主键。 +就可以给这样的字段加唯一键约束 + +2、唯一键约束: +(1)关键字:unique key +(2)特点 +A:允许为null,但是不能重复 +B:一个表可以有多个唯一键约束 +*/ +CREATE TABLE student( + sid INT PRIMARY KEY, + sname VARCHAR(20), + birthday DATE, + score INT, + gender ENUM('男','女'), + weight DOUBLE(4,1), + tel CHAR(11) UNIQUE KEY +); +INSERT INTO student(sid,sname,tel) VALUES +(1,'张三',NULL), +(2,'李四','10086'); + +INSERT INTO student(sid,sname,tel) VALUES +(3,'王五','10086'); + +#建表后增加唯一键约束 +ALTER TABLE 表名称 ADD UNIQUE KEY (字段列表); + +ALTER TABLE student ADD UNIQUE KEY(sname); + +DESC student; + + +#如果要用语句删除唯一键约束 +/* +mysql中,会给主键约束,唯一键约束,外键约束,自动创建索引。 +在底层会单独的索引表,来记录每一个索引值对应的数据地址。 +好比 书的目录页,单独有几页来存储 标题和页面, +哪个标题和对应的页面就像是索引表的意思。 +索引的作用是提高查询的效率。 +像唯一键约束,主键约束等,它们都是表中“关键“信息,可以通过它们快速的定位到某个记录。 +而且实际中根据“关键”信息查询记录的情况更多。 +例如:在一个大的学生信息管理系统中,查询自己的数据,那么根据“学号”或“身份证号”,“姓名”。 +*/ +ALTER TABLE 表名称 DROP INDEX 索引名; + + + + +/* +如果某个字段,不要求唯一,但是要求非空。那么就可以给字段加非空约束。 +3、非空约束 +*/ + +CREATE TABLE student( + sid INT PRIMARY KEY, + sname VARCHAR(20), + birthday DATE, + score INT NOT NULL, + gender ENUM('男','女'), + weight DOUBLE(4,1), + tel CHAR(11) UNIQUE KEY +); +INSERT INTO student(sid,sname,tel) VALUES +(3,'王五','10086'); +/* +错误代码: 1364 +Field 'score' doesn't have a default value*/ + +INSERT INTO student(sid,sname,score,tel) VALUES +(3,'王五',89,'10086'); + + +/* +4、默认值约束 +如果某个字段,在添加数据时未指定值时,希望不要用NULL处理,而是按照一个默认值处理, +就可以使用默认值约束。 +例如:学生性别,在未指定时,默认按照 男 处理 +*/ +CREATE TABLE student( + sid INT PRIMARY KEY, #主键约束 + sname VARCHAR(20) UNIQUE KEY, #唯一键约束 + birthday DATE, + score INT NOT NULL, #非空约束 + gender ENUM('男','女') NOT NULL DEFAULT '男', #非空 + 默认值约束 + weight DOUBLE(4,1), + tel CHAR(11) UNIQUE KEY #唯一键约束 +); +INSERT INTO student(sid,sname,score,tel) + VALUES(1,'张三',89,'10086'); + + INSERT INTO student(sid,sname,score,gender,tel) + VALUES(2,'小翠',89,'女','10010'); + + + #删除score的非空约束 + ALTER TABLE student MODIFY score INT; + + #增加非空约束 + ALTER TABLE student MODIFY score INT NOT NULL; + + #删除gender的默认值约束,保留非空约束 + ALTER TABLE student MODIFY gender ENUM('男','女') NOT NULL; + + #删除gender的非空约束,保留默认值约束 + ALTER TABLE student MODIFY gender ENUM('男','女') DEFAULT '男'; + + #保留非空和默认值约束 + + ALTER TABLE student MODIFY gender ENUM('男','女') DEFAULT '男' NOT NULL; + + +​ +/* +查看一个表的约束名等信息,查看系统库“information_schema”的“table_constraints” +*/ +SELECT * FROM information_schema.table_constraints WHERE table_name = '表名称'; + +SELECT * FROM information_schema.table_constraints WHERE table_name= 'student'; + +/* + +5、检查约束 (MySQL5.7不支持CHECK约束,在MySQL8.0中开始支持CHECK约束) +*/ + +CREATE TABLE student( + sid INT PRIMARY KEY, #主键约束 + sname VARCHAR(20) , + age INT CHECK (age>=18 && age<=35) +); +INSERT INTO student VALUES(1,'张三',25); +INSERT INTO student VALUES(2,'李四',45); +/* +Check constraint 'student_chk_1' is violated(侵犯,无效). +违反了检查约束*/ + +/* +6、外键约束 +约束两个表的关系,或者是一个表的两个字段之间的关系。 + +(1)主表(父表)和从表(子表) +主表:被依赖,被参考 +从表:依赖别人的,参考别人的 + +例如:员工表和部门表 +员工表中有一个部门编号字段,它的值是依赖于部门表的部门编号。 +员工表是从表。 +部门表示主表。 + +例如:学生表、课程表和选课表 +选课表中的学号,它的值是依赖于学生表的学号。 +选课表是从表, +学生表是主表。 +选课表中的课程编号,它的值是依赖于课程表的课程编号。 +选课表是从表, +课程表示主表。 + +选课表有两个外键。 + +例如:订单表,用户表 +订单表中有一个字段(用户名),它的值依赖于用户表。 +订单表就是从表, +用户表就是主表。 + +例如:订单明细表和订单表。 +订单明细表中的订单编号,它的值是依赖于订单表的订单编号。 +订单表就是主表, +订单明细表就是从表。 + +(2)外键的建立和指定要在从表中定义 +(3)关键字 foreign key +(4)格式 foreign key (从表的字段) references 主表(被依赖字段) +(5)要求 +A:主表必须先存在 +B:主表被依赖字段必须有索引,所以通常是主键列或唯一键列等才能作为被依赖字段。 +C:删除表时,要么先删除从表,再删除主表,要么先解除外键约束,然后各自删除。 +D:从(子)表的依赖字段的数据,必须在主(父)表被依赖字段中选择。 + 添加和修改都是这样的。 +E:主(父)表被依赖字段的数据不能轻易的删除和修改,要看是否被引用 + +外键约束等级为 on update/delete cascade /(set null) +*/ +/* +部门表 +*/ +CREATE TABLE dept( + did INT PRIMARY KEY, + dname VARCHAR(20) +); +CREATE TABLE emp( + eid INT, + ename VARCHAR(20), + deptid INT, #这里的部门编号可以和dept表中的部门编号名字不一样,但是数据类型和逻辑意义要一样 + FOREIGN KEY (deptid) REFERENCES dept(did) +); +#emp依赖于dept表 + +#删除表 +DROP TABLE dept; #失败 + +INSERT INTO emp VALUES(1,'张三',1); +/* +错误代码: 1452 +Cannot add or update a child row: +a foreign key constraint fails (`0106db`.`emp`, CONSTRAINT `emp_ibfk_1` FOREIGN KEY (`deptid`) REFERENCES `dept` (`did`))*/ + +INSERT INTO dept VALUES(1,'财务'); +INSERT INTO emp VALUES(1,'张三',1); + + +CREATE TABLE emp( + eid INT, + ename VARCHAR(20), + deptid INT, #这里的部门编号可以和dept表中的部门编号名字不一样,但是数据类型和逻辑意义要一样 + FOREIGN KEY (deptid) REFERENCES dept(did) ON UPDATE CASCADE ON DELETE SET NULL # 更新时级联操作,删除时设置为null +); + + +/* +7、自增属性 +维护某个字段的值自动增长的一个属性。 +它的要求: +(1)一个表最多只能有一个字段是自增的 +(2)自增的字段必须是整数类型 +(3)自增的字段必须是键约束的字段(通常是主键、唯一键) + +自增字段赋值为null和0的时候,会自增, +如果赋值为其他的值,按照你指定的值来。 +*/ +CREATE DATABASE mxdx; +USE mxdx; + +CREATE TABLE stu( + sid INT AUTO_INCREMENT PRIMARY KEY, + sname VARCHAR(20) +); +/* +错误代码: 1075 +Incorrect table definition; +there can be only one auto column(只能是一个自动列) + and(并且) it must be defined as a key(必须是键列) +*/ + + +INSERT INTO stu VALUES(NULL,'张三'); +INSERT INTO stu VALUES(NULL,'李四'); +INSERT INTO stu VALUES(0,'王五'); +INSERT INTO stu VALUES(-1,'赵六'); +INSERT INTO stu VALUES(8,'王八'); +INSERT INTO stu VALUES(NULL,'小九'); + +ALTER TABLE 表名称 AUTO_INCREMENT = 起始值; +ALTER TABLE stu AUTO_INCREMENT = 1001; + +INSERT INTO stu VALUES(NULL,'小十'); +INSERT INTO stu VALUES(NULL,'小十1'); + +SHOW CREATE TABLE stu; \ No newline at end of file -- Gitee