本内容没有涉及到数据库的查询操作,如有需求,请移步MySQL的简单查询操作
方式一:计算机管理 ——> 服务和应用程序 ——> 服务 ——> 找到对应的服务进行操作 方式二: 1、 以管理员的身份打开DOS命令行 2、 启动服务:net start 名(mysql7810) 3、 停止服务:net stop 名(mysql7810)
登录之前,服务必须是启动状态 方式一:打开MySQl的自己的DOS命令行,输入密码即可 方式二:以管理员的身份打开普通的DOS命令行,输入:"mysql -h主机名 -P端口号 -u用户名 -p密码" 1、 输入:mysql -h localhost -P 3306(端口号) -uroot(用户名) -pxxxx(密码) 2、 如果是在本机启动的服务,可以直接:mysql -uroot(用户名) -pxxxx(密码)
键 | 值 |
---|---|
-h | localhost |
-P | 3306,端口号 |
-u | root,用户名 |
-p | 用户的密码 |
SQL语言: 结构化查询语言(Structure Query Language),专门用于与数据库通讯的语言 特点: 1、 不是特有的语言,几乎所有DBMS都支持SQL语言 2、 简单易学 3、 简单,但是功能强大 规则: 1、 不区分大小写 2、 用 ";" 结尾,表示一条命令的结束 3、 注释:单行 “#” 或者 “--空格”;多行”/* */“ 4、 命令可以换行书写
1. 查看权限内可使用的所有数据库 SHOW DATABASES; 2. 使用指定的数据库 USE test; 3. 查看当前正在使用哪一个数据库 SELECT DATABASE(); 4. 创建一个新的数据库(字符集为utf8) CREATE DATABASE test CHARACTER SET utf8; CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8; 5. 更改指定数据库的字符集 ALTER DATABASE test CHARACTER SET utf8; 6. 更改数据库的名称 因为SQL语言没有提供直接的命令 我们可以将数据库备份成sql文件,之后在文件中更改参数即可 7. 删除指定的数据库 DROP DATABASE test; DROP DATABASE IF EXISTS test;
类型 | 说明 | 字节数 | 范围 |
---|---|---|---|
tinyint | 很小的整数 | 1 | 有符号:-2^7 ~ 2^7-1 无符合:0 ~ 2^8-1 |
smallint | 小整数 | 2 | 有符号:-2^15 ~ 2^15-1 无符合:0 ~ 2^16-1 |
mediumint | 中等整数 | 3 | 有符号:-2^23 ~ 2^23-1 无符合:0 ~ 2^24-1 |
int | 普通整数 | 4 | 有符号:-2^31 ~ 2^31-1 无符合:0 ~ 2^32-1 |
bigint | 大整数 | 8 | 有符号:-2^63 ~ 2^63-1 无符合:0 ~ 2^64-1 |
DROP TABLE IF EXISTS test; CREATE TABLE IF NOT EXISTS test ( t1 INT(10) ZEROFILL, # 如果不足10位,就在前面补'0',超过10位就正常显示 t2 INT(10), # 默认是有符号位 t3 INT(10) UNSIGNED, # 设置无符号位,即非负数 t4 INT(10) ZEROFILL UNSIGNED, # 二者搭配使用 t5 INT(10) ); DROP TABLE IF EXISTS test;
类型 | 特点 |
---|---|
float(M,D) | 单精度浮点型 |
double(M,D) | 双精度浮点型 |
decimal(M,D) | 定点型,可简写成dec(M,D) |
DROP TABLE IF EXISTS test; CREATE TABLE test ( f1 FLOAT (5, 2), # 浮点 f2 DOUBLE (7, 3), # 浮点 f3 DECIMAL(7, 3) # 定点 ); INSERT INTO test VALUES (3.4, 3.4, 3.4), (1234.5, 1234.5, 1234.5), (12345.6, 12345.6, 12345.6); SELECT * FROM test;
类型 | 格式 | 范围 | 对应的Java类 |
---|---|---|---|
date | YYYY-MM-DD | 从 ‘1000-01-01’ 到 ‘9999-12-31’ | LocalDate |
time | HH:MM:SS | 从 ‘-838:59:59’ 到 ‘838:59:59’ | LocalTime |
datetime | YYYY-MM-DD HH:MM:SS | 从’1000-01-01 00:00:00’ 到 ‘9999-12-31 23:59:59’ | LocalDateTime |
DROP TABLE IF EXISTS test; CREATE TABLE test ( t1 DATE, # 日期 t2 TIME, # 时间 t3 DATETIME, # 日期+时间 ); INSERT INTO test VALUES (NOW(), NOW(), NOW(), ('2021-01-01', '15:26:25', '2021-1-1 15:26:25'); SELECT * FROM test;
类型 | 对于长度len | 特点 | 空间 | 效率 |
---|---|---|---|---|
char(len) | 可以省略不写,默认为1 | 固定长度的字符串 | 比较耗费空间 | 效率高 |
varchar(len) | 不可以省略 | 可变长度的字符串 | 比较节省空间 | 效率低 |
DROP TABLE IF EXISTS test; CREATE TABLE test ( s1 CHAR, s2 CHAR(5), s3 VARCHAR(5) ); INSERT INTO test VALUES ('123456', '123456', '123456'); SELECT * FROM test;
DROP TABLE IF EXISTS test; CREATE TABLE test ( enums ENUM('a', 'b', 'c'), sets SET ('a', 'b', 'c') ); INSERT INTO test VALUES (2, 'a'), # b a (1, 'b'), # a b (5, 'a'), # null a ('b', 'b'); # b b SELECT * FROM test;
# 1. length():获取参数的字节个数 SELECT LENGTH('aaa'); # 一个字母占一个字节(utf8) SELECT LENGTH('中国人'); # 一个中文3个字节(utf8) # 2. upper()、lower():大小写转换 SELECT UPPER('Abc'); # ABC SELECT LOWER('Abc'); # abc # 3. concat():拼接字符串 SELECT CONCAT('aaa', 'bbb'); # aaabbb SELECT CONCAT('a', 'b', 'c'); # abc # 4. trim():去掉前后字符(默认去掉空格,可以指定去掉前后字符) SELECT LENGTH(' abc '); # 5 SELECT LENGTH(TRIM(' abc ')); # 3【默认去掉空格】 SELECT TRIM('a' FROM 'aaaa1234aa'); # 1234【去掉字符串前后两边的字符'a'】 # 5. instr(str1, str2):返回str2在str1中第一次出现的索引,找不到返回0(索引从1开始) SELECT INSTR('123456_123456', '123'); # 1 SELECT INSTR('123456_123456', '_123456'); # 7 SELECT INSTR('123456_123456', '0123'); # 0 # 6. replace(str, a, b) 将str中的a全部替换成b SELECT REPLACE('你是大XX,你个XX', 'XX', '***'); # 7. substr(str, pos, [len]):截取字符串【或者:substring(str, pos, [len])】 SELECT SUBSTR('12345', 1); # 12345 【截取字符串[pos - last](索引从1开始)】 SELECT SUBSTR('12345', 2); # 2345 SELECT SUBSTR('123456789', 1, 1); # 1 【截取字符串[pos - (pos + len - 1)](索引从1开始)】 SELECT SUBSTR('123456789', 1, 3); # 123 # 8. 字符串填充【lpad(str, len, chr)、rpad(str, len, chr)】 # 不够->补,按方向补指定的字符 # 超出->截,均在右边截断 # lpad():左填充 SELECT LPAD('wangks', 8, '+'); # ++wangks【在左边补充2个字符'+',使其长度为8】 SELECT LPAD('wangks', 5, '+'); # wangk【截断右边的字符's',使其长度为5】 # rpad():右填充 SELECT RPAD('wangks', 8, '+'); # wangks++【在右边补充2个字符'+',使其长度为8】 SELECT RPAD('wangks', 5, '+'); # wangk【截取右边的字符's',使其长度为5】
# 1. 绝对值【abs(s)】 SELECT ABS(-1), ABS(1); # 2. 平方根【sqrt(x)】 SELECT SQRT(4), TRUNCATE(SQRT(5), 5); # 3. 求余【mod(a, b):结果的正负由 a 决定】 SELECT MOD(12, 5); # 2 SELECT MOD(-12, 5); # -2 SELECT MOD(-12, -5); # -2 SELECT MOD(12, -5); # 2 # 4. 幂运算【pow(a, b)】 SELECT POW(2, 4); SELECT POW(2, 10); # 5. 数字截断,直接截断小数点指定位数后面的数【truncate(x, len)】 SELECT TRUNCATE(1.699, 2); # 1.69 SELECT TRUNCATE(1.699, 0); # 1 # 6. 四舍五入【round(x)、round(x, len)】 SELECT ROUND(1.1); # 1【直接保留到整数位】 SELECT ROUND(1.568, 2); # 1.57【指定小数点保留的位数】 # 7. PI的使用【pi():默认显示后6位】 SELECT PI(); # 8. ceil 向上取整,返回 >=本身 的 最小整数 SELECT CEIL(1.1); # 2 SELECT CEIL(1.0); # 1 # 9. floor 向下取整,返回 <=本身 的 最大整数 SELECT FLOOR(1.1); # 1 SELECT FLOOR(1.0); # 1
# 1. 【now():返回当前系统的 日期和时间】 SELECT NOW(); # 2. 【curdate():返回当前系统的 日期】 SELECT CURDATE(); # 3. 【curtime():返回当前系统的 时间】 SELECT CURTIME(); # 4. 获取指定时间的年、月、日、时、分、秒 SELECT YEAR(NOW()); # 获取参数 的 年 SELECT YEAR('1212-5-5'); # 1212 SELECT MONTH(NOW()); # 获取参数 的 月 SELECT MONTH('1212-5-5'); # 1212 SELECT DAY(NOW()); # 获取参数 的 日 SELECT MONTH('1212-5-5'); # 5 SELECT HOUR(NOW()); # 获取参数 的 时 SELECT HOUR('2021-08-17 18:49:58'); # 18 SELECT MINUTE(NOW()); # 获取参数 的 分 SELECT MINUTE('2021-08-17 18:49:58'); # 49 SELECT SECOND(NOW()); # 获取参数 的 秒 SELECT SECOND('2021-08-17 18:49:58'); # 58 # 5. 【DATEDIFF(d1, d2):返回两日期之间的天数之差,d1 - d2】 SELECT DATEDIFF('2001-12-15', NOW()); # 7148 /* %Y:年,4位数的年 %m:月,01 02 03... %d:日,01 02 03... %H:时,24小时制 %i:分,00 01 02... %s:秒,00 01 02... -------------------------- %y:年,2位数的年 %c:月,1 2 3 4.... %h:时,12小时制 */ # 6. 【date_format(date, str):日期 --> 字符串】 SELECT DATE_FORMAT(NOW(), '%Y--%d--%m'); SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日'); # 7. 【str_to_date(str1, tr2):字符串 --> 日期 SELECT STR_TO_DATE('12++2001++29', '%m++%Y++%d'); # 2001-12-29 SELECT STR_TO_DATE('2021年9月7日 8点2分0秒', '%Y年%m月%d日 %H点%i分%s秒'); # 2021-09-07 08:02:00
# 1. sum、avg、max、min【求和、平均值、最大值、最小值】 SELECT SUM(salary) FROM employees; SELECT AVG(salary) FROM employees; SELECT MAX(salary) FROM employees; SELECT MIN(salary) FROM employees; # 2. count【求个数,count(*)效率较好,绝对的忽略null值】 SELECT COUNT(*) FROM employees; # 求该表共有几行 SELECT COUNT(`commission_pct`) FROM employees; # 求有几行,但是参数为null的行不计算 SELECT COUNT(1) FROM employees; # 新增一列,每行的新列都是1,统计1的个数,即实现了统计行数 SELECT COUNT(2) FROM employees; # 新增一列,每行的新列都是2,统计2的个数,即实现了统计行数 SELECT COUNT('++--') FROM employees; # 新增一列,每行的新列都是++--,统计++--的个数,即实现了统计行数 # 3. continct 去重 SELECT COUNT(DISTINCT `job_id`) FROM employees; # 统计有多少个部门,先对部门id去重,求有多少行 SELECT DISTINCT IFNULL(department_id, 'xxx') FROM employees; # 查找员工表里面所有的部门id
# 1. 别名函数【as 或 空格】 SELECT POW(2, 10) AS 幂次方; SELECT MOD(51, 2); 取余 # 2. 设置字符集 SET NAMES gbk; SET NAMES utf8; # 3. 查看版本号 SELECT VERSION(); # 5.5.54 # 4. 代表当前用户 SELECT USER(); # 5. IFNULL(a, b) 当a为null时返回b,否则返回a SELECT IFNULL(NULL, '是null'); SELECT IFNULL(NULL, '是null'); # 6. 另类的加号‘+’【在MySQL中,‘+’仅表示运算符的加号】 /* 6.1 两个数值型,直接相加 6.2 有字符型,将其转换成数字型,如果成功,继续加法运算,否则将字符型转换成0 6.3 如果其中有一个null,则结果一定为null */ SELECT 100 + 100; # 200 SELECT 100 + 100 + NULL; # null SELECT 100 + 100 + '123'; # 323 SELECT 100 + 100 + 'abc'; # 200 # 7. 查看创建表时的SQL语句:【show create table 表名】 SHOW CREATE TABLE test;
类型 | 说明 | 级别 | 常用级别 |
---|---|---|---|
not null(非空约束) | 该字段的值不可以为空 | 列级 | 列级 |
default(默认约束) | 该字段有默认的值 | 列级 | 列级 |
primary key(主键约束) | 该字段的值具有唯一性、非空性【一个表中,最多有1个主键】 | 列级、表级 | 列级 |
unique(唯一约束) | 该字段的值具有唯一性,但是可以为空 | 列级、表级 | 表级 |
check(检查约束) | mysql中不支持 | 无 | 无 |
foreign key(外键约束) | 该字段的值必须来自主表的关联列的值 | 表级 | 表级 |
# 主表 DROP TABLE IF EXISTS otherTable; CREATE TABLE IF NOT EXISTS otherTable ( id INT, UNIQUE KEY (id) ); # 从表 DROP TABLE IF EXISTS stuinfo; CREATE TABLE IF NOT EXISTS stuinfo ( `id` INT(20), # 主键 `name` VARCHAR(50) NOT NULL, `nationals` VARCHAR(20) NOT NULL DEFAULT 'Chines', `age` INT(20) NOT NULL DEFAULT 999, `numbers` VARCHAR(30), # 唯一键 `majorId` INT, # 外键 PRIMARY KEY `bieming1` (id), # 起别名、表级约束 UNIQUE KEY `bieming2` (numbers), # 起别名、表级约束 CONSTRAINT fk_stuinfo_otherTable FOREIGN KEY(`majorId`) REFERENCES otherTable(id) # 外键的别名:fk_从表的名字_主表的名字 );
# 主表 DROP TABLE IF EXISTS otherTable; CREATE TABLE IF NOT EXISTS otherTable ( id INT, UNIQUE KEY(id) ); # 从表 DROP TABLE IF EXISTS stuinfo; CREATE TABLE IF NOT EXISTS stuinfo ( `id` INT(20) UNIQUE, # 主键 `name` VARCHAR(50), # 非空 `nationals` VARCHAR(20), # 默认 `numbers` VARCHAR(30), # 唯一 `majorId` INT # 外键 ); # ==================================================================================== # 1. 非空约束 ALTER TABLE stuinfo MODIFY COLUMN `name` VARCHAR(20) NOT NULL; # 列级 # 2. 默认约束 ALTER TABLE stuinfo MODIFY COLUMN `nationals` VARCHAR(20) DEFAULT 'Chines'; # 列级 # 3. 主键 ALTER TABLE stuinfo ADD PRIMARY KEY(id); # 表级 # 4. 唯一键 ALTER TABLE stuinfo ADD UNIQUE KEY(numbers); # 表级 ALTER TABLE stuinfo ADD CONSTRAINT `otherName1` UNIQUE KEY(numbers); # 表级 # 5. 外键 ALTER TABLE stuinfo ADD FOREIGN KEY(majorId) REFERENCES major(id); # 表级 ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorId) REFERENCES otherTable(id); # 表级
# 主表 DROP TABLE IF EXISTS otherTable; CREATE TABLE IF NOT EXISTS otherTable ( id INT, UNIQUE KEY(id) ); # 从表 DROP TABLE IF EXISTS stuinfo; CREATE TABLE IF NOT EXISTS stuinfo ( `id` INT(20), # 主键 `name` VARCHAR(50) NOT NULL, `nationals` VARCHAR(20) NOT NULL DEFAULT 'Chines', `age` INT(20) NOT NULL DEFAULT 999, `numbers` VARCHAR(30), # 唯一键 `majorId` INT, # 外键 PRIMARY KEY `bieming1` (id), # 起别名、表级约束 UNIQUE KEY `bieming2` (numbers), # 起别名、表级约束 CONSTRAINT fk_stuinfo_otherTable FOREIGN KEY(`majorId`) REFERENCES otherTable(id) # 外键的别名:fk_从表的名字_主表的名字 ); # ==================================================================================== # 1. 删除非空 ALTER TABLE stuinfo MODIFY COLUMN `name` VARCHAR(20); ALTER TABLE stuinfo MODIFY COLUMN `name` VARCHAR(20) NULL; # 2. 删除默认 ALTER TABLE stuinfo MODIFY COLUMN `nationals` INT; ALTER TABLE stuinfo MODIFY COLUMN `nationals` INT NULL; # 3. 删除主键 ALTER TABLE stuinfo DROP PRIMARY KEY; # 4. 删除唯一键【未成功】 ALTER TABLE stuinfo DROP INDEX numbers; # 5. 删除外键约束【未成功】 ALTER TABLE stuinfo DROP CONSTRAINT fk_stuinfo_otherTable;
# 1. 创建表时添加标识列 DROP TABLE IF EXISTS autos; CREATE TABLE autos ( `id` INT AUTO_INCREMENT, `name` VARCHAR(20) NOT NULL, PRIMARY KEY(`id`) ); # 2. 修改表时添加标识列 ALTER TABLE autos MODIFY COLUMN `id` INT PRIMARY KEY AUTO_INCREMENT; # 3. 修改表时删除标识列 ALTER TABLE autos MODIFY COLUMN id INT PRIMARY KEY; # 4. 设置步长 SET auto_increment_increment = 2; # 6. 清空所有数据时,有自增长字段 DELETE FROM autos; # 下次插入数据时,自增长列的值依然从断点处自增 TRUNCATE TABLE autos; # 下次插入数据时,自增长列的值从1开始
# 1. 查看当前库中所有的表 SHOW TABLES; # 2. 查看创建表时的SQL语句:【show create table 表名】 SHOW CREATE TABLE stuinfo; # 3. 清空表 TRUNCATE TABLE stuinfo; DELETE FROM stuinfo;
# 1. 创建 Book表 CREATE TABLE books( id INT, bName VARCHAR(20), price DOUBLE, authorId VARCHAR(20), publishDate DATETIME ); # 2. 修改字段名:要求修改字段名的时候,一定要加上字段的数据类型 ALTER TABLE books CHANGE COLUMN publishDate pubDate DATETIME; # 3. 修改字段的类型、约束、标识列 ALTER TABLE books MODIFY COLUMN `id` INT; ALTER TABLE books MODIFY COLUMN `id` INT PRIMARY KEY AUTO_INCREMENT; # 注意:标识列只可以和键级约束搭配 # 4. 添加新字段 ALTER TABLE books ADD COLUMN price DOUBLE DEFAULT 0; # 5. 删除字段 ALTER TABLE books DROP COLUMN price; # 6. 修改表名 ALTER TABLE books RENAME TO books_; # 7. 表的删除 DROP TABLE IF EXISTS books; # 8. 表的复制【用到的时候再查】
# 1. 插入数据 INSERT INTO tab_date(`id`, `name`) VALUES(1, 'Tom'); INSERT INTO tab_date VALUES(2, 'Jarry'); INSERT INTO tab_date SET `id` = 3, `name` = 'Jacck'; # 2. 修改单表的数据 UPDATE tab_date SET `name` = 'Toms' WHERE `id` = 1; UPDATE tab_date SET `name` = 'Tom' WHERE `id` = 1; # 3. 修改多表的数据 # 案例 -- 将id=4的男生的女朋友的手机号修改为'12345654321' UPDATE beauty b LEFT JOIN boys bo ON b.`boyfriend_id` = bo.`id` SET b.phone = 'xxxxx' WHERE bo.id = 4; # 4. 删除单表的一条数据 DELETE FROM tab_date WHERE id = 1; # 5. 清空数据 TRUNCATE tab_date; # 6. delete和truncate的区别 /* 1. delete 可以加WHERE 条件,TRUNCATE不能加 2. truncate删除,效率高一点点 3. 假如要删除的表中有自增长列 -- 用DELETE删除后, 再次插入数据,自增长列的值从断点开始 -- 用TRUNCATE删除后,再次插入数据,自增长列的值从1开始 4. truncate删除没有返回值,DELETE删除有返回值 5. truncate删除不能回滚,DELETE删除可以回滚 */ # 7. 删除和A表的一条数据有关的B表中的记录【多表删除】 /* 【sql92语法】 delete a, b frOM 表1, 表2 on 连接条件 wherE 筛选条件 【sql99语法】 delete a, b from 表1 (inner|lefT|RIGhT) JoIN 表2 ON 连接条件 where 筛选条件 */ # sql99:可以只删一个表,也可以两个表都删除 DELETE be FROM boys b INNER JOIN beauty be ON b.id = be.boy_id WHERE b.id = 1; # sql92:只可以实现两个表都删除 DELETE be, b FROM beauty be, boys b ON b.id = be.boy_id WHERE b.id = 1;
# 方式1:直接拷贝物理文件 # 方式2:在SQLyog工具中手动导出 1. 在想要导出的表或库 右键 选中导出 2. 一般限制导出 结构 和 数据 # 方式3:使用命令行 1. 导入 # 导入一个表 # 1. 登录服务 # 2. 选择库 # 3. source 备份文件 # 导入一个库 # 1. 登录 # 2. 直接导入库 2. 导出【mysqldump:不是SQL命令,故不可以登录sql之后再使用此命令】 # 2.1 导出一个表 # mysqldump -h主机 -u用户名 -p 库 表 > 地址 mysqldump -hlocalhost -uroot -p pdsu other > D:/a.sql # 2.2 导出多个表 # mysqldump -h主机 -u用户名 -p 库 表1 表2 表3 > 地址 mysqldump -hlocalhost -uroot -p pdsu other otherTable > D:/a.sql # 2.3 导出一个库 # mysqldump -h主机 -u用户名 -p 库 > 地址 mysqldump -hlocalhost -uroot -p pdsu > D:/a.sql
DROP TABLE IF EXISTS tab_md5; CREATE TABLE IF NOT EXISTS tab_md5 ( `id` INT(20), `pwd` VARCHAR(50) ); # 1. 插入明文 INSERT INTO tab_md5 VALUES (1, '123'), (2, '123456'); # 2. 插入密文 INSERT INTO tab_md5 VALUES (3, MD5('123')), (4, MD5('123456')); # 3. 明文与密文的校验 SELECT * FROM tab_md5 WHERE `id` = 4 AND `pwd` = MD5('123456'); # 4. 修改明文为密文 UPDATE tab_md5 SET `pwd` = MD5(`pwd`) WHERE id = 1; # --- 修改单独一个 UPDATE tab_md5 SET `pwd` = MD5(`pwd`); # --- 修改全部
# 用户管理的本质:对MySQL库下面的user表进行增删查改 # 1. 方式一:SQLyog可视化管理 # 2. 方式二:cmd # 1. 创建用户 CREATE USER wangks IDENTIFIED BY '123456'; # 2. 修改当前用户密码 SET PASSWORD = PASSWORD('7810'); # 3. 修改指定用户密码 SET PASSWORD FOR wangks = PASSWORD('123456'); # 4. 用户重命名 RENAME USER wangks TO newwangks; # 5. 删除用户 DROP newwangks; # 6. 授予用户部权限【除了不可以给别人这种权限,其余和root一样】 GRANT ALL PRIVILEGES ON *.* TO wangks1; # 7. 查看指定用户的权限 SHOW GRANTS FOR newwangks; # 8. 查看管理员权限 SHOW GRANTS FOR root@localhost;
一、糟糕的数据库 1. 数据冗余,浪费空间 2. 数据库的插入和删除麻烦 3. 可能有异常 4. 性能差 二、良好的数据库 1. 节省内存空间 2. 保证数据库的完整性 3. 方便我们开发系统 三、三大范式 1. 第一范式:要求数据库的每一列都是不可分割的原子数据项【原子性】 2. 第二范式: 前提:满足第一范式 确保数据表的每个字段和主键相关,而不能只与主键的某一部分相关 每张表只描述一件事情 3. 第三范式: 前提:满足第一、第二范式 确保数据表的每个字段必须和主键直接相关,而不可以间接相关 四、三大范式目的:规范数据库的设计,但是为了性能,有时故意设置冗余字段