列属性
主键,唯一键和自增长
主键:primary key,用来唯一的约束该字段里面的数据,不能重复,一张表中只能有一个主键
增加主键
SQL操作中有多种方式给表增加主键:大体分为三种
1、在创建表的时候,直接在字段后加 primary key
--增加主键
create table my_pri1(
id int primary key comment '学号',
name varchar(20) not null comment '姓名'
)charset utf8;
2、
--复合主键
create table my_pri2(
number char(10) comment '学号',
course char(10) comment '课程代码',
score tinyint unsigned default 60 comment '成绩',
primary key(number,course)
)charset utf8;
3、当表已经创建好之后,再次额外追加主键,可以通过修改 表字段属性,也可以直接追加
--追加主键
create table my_pri3(
course char(10) not null comment '课程编号',
name varchar(20) not null comment '课程名'
)charset utf8;
alter table my_pri3 modify course char(10) primary key comment '课程编号';
或
add primary key(course);
追加主键前提:表中字段对应的数据本身是独立的(不重复的)。
主键约束
主键对应的字段中的数据不允许重复:一旦重复,数据操作失败
--向pri1表插入数据
insert into my_pri1 values(1,'学生一'),(2,'学生二');
insert into my_pri2 values('number0001','course0001',65),('number0002','course0002',89);
--主键冲突
insert into my_pri1 values(1,'学生三');
insert into my_pri2 values('number0001','course0001',78);
更新主键&删除主键
没有办法更新主键:主键必须先删除才能增加
alter table 表名
--删除主键
desc my_pri3;
alter table my_pri3 drop primary key;
主键的分类
在实际创建表的过程中,很少使用真实业务数据作为主键字段(业务主键,如学号,课程号),
大部分的时候是使用逻辑性的字段(字段没有业务含义),将这种主键称为逻辑主键。
create table my_student(
id int primary key auto_increment comment '逻辑主键 自增长',
number char(10) not null comment '学号',
name varchar(10) not null
)charset utf8;
自增长
当对应的字段,不给值,或者说给默认值,或者给NULL的时候,会自动的被系统触发,
系统会从当前字段中已有的最大值再进行+1操作,得到一个新的不同的字段。
自增长通常是跟主键搭配。
auto_increment 自增长特点:
1、任何一个字段要做自增长必须前提是本身是一个索引(key 一栏有值)
2、自增长字段必须是数字(整型)
3、一张表最多只能有一个自增长
4、自增长默认第一个元素是1,每次自增1
--自增长
create table my_auto(
id int primary key auto_increment comment '自增长',
name varchar(20) not null
)charset utf8;
自增长使用
当自增长给定的值为NULL或者默认值的时候会触发自增长
--触发自增长
insert into my_auto(name) values("自增长");
insert into my_auto values(null,"自增长2");
insert into my_auto values(default,"默认值");
注意:自增长如果对应的字段输入了值,那么自增长失效,但是下一次还是能够正确的自增长(从最大值+1)
insert into my_auto values(6,"指定值");
insert into my_auto values(default,"自增长3");
如何确定下一次是什么自增长?可以通过查后表创建语句看到
show create table my_auto;
修改自增长
1、自增长如果是涉及到字段改变:必须先删除自增长后增加(一张表只能有一个自增长)
2、修改当前自增长已存在的值:修改只能比当前已有的自增长的最大值大,不能小(小不生效)
alter table my_auto auto_increment =20;
insert into my_auto values(null,'修改1');
--向下修改,无效
alter table my_auto auto_increment=10;
insert into my_auto values(null,"修改2");
为什么自增长是从1开始?每次加1?
所有系统的实现(如字符集,校对集)都是由系统内部的变量进行控制的
查看自增长对应
--查看自增长变量
show variables like 'auto_increment%';
| auto_increment_increment | 1 步长
| auto_increment_offset | 1 起始值
+--------------------------+------
可以修改变量实现不同的效果:修改是对整个数据修改,而不是单张表:(修改是会话级)
set auto_increment_increment = 5 ; --一次自增5
show variables like 'auto_increment%';
insert into my_auto values(null,"修改会话级");
删除自增长
自增长是字段的一个属性:可以通过modify来进行修改(保证字段没有auto_increment)
--删除自增长
alter table my_auto modify id int primary key ; --错误,主键是单独存在的
alter table my_auto modify id int; --有主键的时候,不需要再加主键
唯一键
一张表往往很多字段需要具有唯一性,数据不能重复,但是一张表中只能有一个主键
唯一键可以解决唯一性约束
唯一键默认的允许字段为空,而且可以多个为空(空字段不参与唯一比较)
增加唯一键
方案1:在创建表的时候,字段之后直接跟unique/unique key
create table my_unique1(
number char(10) unique comment '学号:唯一,允许为空',
name varchar(20) not null
)charset utf8;
方案2:在所有字段后增加unique key(字段列表)
create table my_unique2(
number char(10) not null comment '学号',
name varchar(20) not null,
unique key(number)
)charset utf8;
方案3:在创建表之后增加unique key
create table my_unique3(
id int primary key auto_increment,
number char(10) not null,
name varchar(20) not null
)charset utf8;
alter table my_unique3 add unique key(number);
唯一键约束
唯一键本质与主键相同,唯一的区别是允许为空
insert into my_unique1 values(null,'唯一空');
insert into my_unique1 values('number0001','学生一'),(null,'唯一空二');
insert into my_unique1 values('number0001','学生二'); --报错
如果唯一键也不允许为空,与主键的约束是一样的
更新唯一键&删除唯一键
更新唯一键:先删除后新增(可以有多个,可以不删除)
alter table my_unique1 drop unique key; --错误:唯一键有多个
alter table my_unique1 drop index 索引名字; --默认使用字段名作为索引名
desc my_unique3;
alter table my_unique3 drop index number ;
索引
几乎所有的索引都是建立在字段之上
索引:系统根据某种算法,将已有的数据(未来可能新增的数据),单独建立一个文件,文件能
够实现快速的匹配数据,并且能够快速找到对应表的记录。
索引的意义:
1、提升查询数据的效率
2、约束数据的有效性(唯一性等)
增加索引的前提条件:索引本身会产生索引文件(有时候可能比数据文件还大),会非常耗费
磁盘空间。
如果某个字段需要作为查询的条件经常使用,那么可以使用索引。
mysql中提供了多种索引
1、主键索引 primary key
2、唯一索引 unique key
3、全文索引 fulltext index
4、普通索引 index
全文索引:针对文章内部的关键字进行索引
全文索引最在的问题:在于如何确定关键字
英文很容易:英文单词与单词之间有空格
中文很难:没有空格,而且中文可以各种随意组合(分词)
关系
将实体与实体的关系,反应到最终数据库的设计上来,将关系分为:一对一,一对多,多对多
所有的关系都是指的表与表之间的关系
一对一
一张表的一条记录一定只能与另外一张表的一条记录进行对应,反之亦然。
学生表:姓名,性别,年龄,身高,体重,籍贯,家庭住址,紧急联系人
其中姓名、性别、年龄、身高,体重属于常用数据,但是籍贯、住址和联系人为不常用数据
如果每次查询都是查询所有数据,不常用的数据就会影响效率,实际又不用
常用信息表:ID(P),姓名,性别,年龄,身高,体重
不常用信息表:ID(P),籍贯,家庭住址,紧急联系人
解决方案:将常用的和不常用的信息分享存储,分成两张表
不常用信息表和常用信息表,保证不常用信息表与常用信息表能够对应上:找一个具有唯一性的
字段来共同连接两张表。
一个常用表中的一条记录永远只能在一张不常用表中匹配一条记录,反之亦然。
一对多
一张表中有一条记录可以对应另外一张表中的多条记录;但是反过来,另外一张表的一条记录
只能对应第一张表的一条记录,这种关系就是一对多或多对一
母亲与孩子的关系:母亲,孩子两个实体
母亲表:ID(P),名字,年龄,性别
孩子表:ID(P),名字,年龄,性别
以上关系:一个妈妈可以在孩子表中找到多条记录(也可能是一条),但是一个孩子只能找到一个妈妈
是一种典型的一对多的关系。
但是以上设计:解决了实体的设计表问题,但是没有解决关系问题,孩子找不到母亲,母亲也找不到孩子
解决方案:在某一张表中增加一个字段,能够找到另外一张表中的记录:在孩子表中增加一个字段
指向母亲表,因为孩子表的记录只能匹配到一条母亲表的记录。
母亲表:ID(P),名字,年龄,性别
孩子表:ID(P),名字,年龄,性别,母亲表ID(母亲表主键)
多对多
一对表中(A)的一条记录能够对应另外一张表(B)中的多条记录;同时B表中的一条记录
也能对应A表中的多条记录
老师和学生
老师表 T_ID(P),姓名,性别
学生表 S_ID(P),姓名,性别
以上设计方案:实现了实体的设计,但是没有维护实体的关系
一个老师教过多个学生,一个学生也被多个老师教过
解决方案:增加一张中间关系表
老师与学生的关系表:ID(P),T_ID,S_ID
老师表与中间表形成一对多的关系,而中间表是多表;维护了能够唯一找到一表的关系;
同样的学生表与中间表也是一个一对多的关系;
学生找老师:找出学生ID--->中间表寻找匹配记录(多条)--->老师表匹配(一条)
老师找学生:找出老师ID--->中间表寻找匹配记录(多条)--->学生表匹配(一条)
范式
Normal Format,是一种离散数学中的知识,是为了解决一种数据的存储与优化的问题;
保存数据的存储之后,凡是能够通过关系寻找出来的数据,坚决不再重复存储;终极
目标是为了减少数据的冗余。
范式:是一种分层结构的规范,分为6层:每一层都比上一层更加严格;若要满足下一层
范式前提是满足上一层范式
六层范式:1NF,2NF,3NF,...6NF,1NF是最底层,要求最低
mysql属于关系型数据库:有空间浪费;也是致力于节省存储空间;在设计数据库的时候,
会利用到范式来指导设计。
但是数据库不单是要解决空间问题,要保证效率问题;范式只为解决空间问题,所以数据库
的设计又不可能完全按照范式的要求实现;一般情况下,只有前三种范式需要满足。
范式在数据库的设计当中是有指导意义:但是不是强制规范。
1NF 第一范式
在设计表存储数据的时候,如果表中设计的字段存储的数据,在取出来使用之前还需要额外
的处理(拆分),那么说表的设计不满足第一范式;
第一范式要求字段具有原子性。原子性指字段不可再分。
讲师代课表:讲师姓名(P)、性别、班级(P)、教室、代课时间(天)、代课时间段(开始--结束)
不满足1NF,代课时间段需要拆分
解决方案:将代课时间段拆分成开始和结束
讲师代课表:讲师姓名(P)、性别、班级(P)、教室、代课时间(天)、开始时间、结束时间
2NF 第二范式
在数据表设计的过程中,如果有复合主键(多字段主键),且表中有字段并不是由整个主键来确定,
而是依赖主键中的某个字段(主键的部分);存在字段依赖主键的部分的问题,称之为部分依赖;
第二范式就是要解决部分依赖。
讲师代课表:讲师姓名(P)、性别、班级(P)、教室、代课时间(天)、开始时间、结束时间
以上表中:因为讲师没有办法作为独立主键,需要结合班级才能作为主键(复合主键)
代课时间,开始和结束字段都与当前的代课主键(讲班和班级)决定,但性别并不依赖班级,
同时教室不依赖讲师,性别只依赖讲师,教室只依赖班级,出现了性别和教室依赖主键中的一
部分,部分依赖,不符合2NF。
解决方案1:可以将性别与讲师单独成表,班级与教室也单独成表
解决方案2:取消复合主键,使用逻辑主键
讲师代课表:ID(P)、讲师姓名、性别、班级、教室、代课时间(天)、开始时间、结束时间
3NF 第三范式
要满足必须满足第二范式
第三范式:理论上讲,应该一张表中的所有字段都应该直接依赖主键(逻辑主键:代表的是业务主键),
如果表设计中存在一个字段,并不直接依赖主键,而是通过某个非主键字段依赖,最终实现依赖主键;
把这种不是直接依赖主键,而是依赖非主键字段的依赖关系称之为传递依赖。
第三范式要求解决传递依赖。
讲师代课表:ID(P)、讲师姓名、性别、班级、教室、代课时间(天)、开始时间、结束时间
以上设计方式中:性别依赖讲师存在,讲师依赖主键;教室依赖班级,班级依赖主键
解决方案:将存在传递依赖的字段,以及依赖的字段本身单独取出,形成一个单独的表,然后
在需要对应的信息的时候,使用对应的实体表的主键加进来。
讲师代课表:ID(P)、讲师ID、班级ID、代课时间(天)、开始时间、结束时间
讲师表: ID(P)、讲师姓名、性别 (ID等价于讲师)
班级表: ID(P)、班级、教室 (ID等价于班级)
逆规范化
有时候,在设计表的时候,如果一张表中有几个字段是需要从另外的表中去获取信息,理论上讲,
的确可以获取到想要的数据,但是就是效率低一点,会刻意的在某些表中,不去保存另外表的主
键(逻辑主键),而是直接保存想要的数据信息;这样一来,在查询数据的时候,一张表可以直接
提供数据,而不需要多表查询(效率低);但是会导致数据冗余增加。
数据高级操作
数据操作:增删改查
基本语法
insert into 表名[(字段列表)] values(值列表);
在数据插入的时候,假设主键对应的值已经存在:插入一定会失败!
主键冲突
当主键存在冲突的时候,可以选择性的进行处理:更新和替换
1、主键冲突:更新操作
insert into 表名[(字段列表:包含主键)] values(值列表) on duplicate key update 字段 = 新值;
show tables; --查看所有数据表
insert into my_class values('PHP0810','b205');
insert into my_class values('PHP0810','b206'); --主键冲突
--冲突处理:更新
insert into my_class values('PHP0810','b206')
on duplicate key update
room = 'b206';
2、主键冲突:替换
replace into 表名[(字段列表)] values(值列表);
--主键冲突:替换
replace into my_class values('PHP0810','b207');
--没有冲突,直接插入
replace into my_class values('PHP0811','b208');
蠕虫复制
从已有的数据中去获取数据,然后将数据又进行新增操作:数据成倍的增加
表创建的高级操作:从已有表创建新表(复制表结构)
create table 表名 like 数据库.表名;
create table my_utf8(
name varchar(20)
)charset utf8;
--复制创建表(只复制结构,不复制数据)
create table my_copy like my_utf8;
蠕虫复制:先查出数据,然后将查出的数据新增一遍
insert into 表名[(字段列表)] select 字段列表/* from 数据表名;
insert into my_copy select username from t_user;
insert into my_copy select username from my_copy;
意义:
1、从已有表中拷贝数据到新表中
2、可以迅速的让表中的数据膨胀到一定的数量级;测试表的压力以及效率。
更新数据
基本语法
update 表名 set 字段 = 值 [where 条件]
高级新增语法
update 表名 set 字段 = 值 [where 条件][limit 限制数量]
update my_copy set name='修改后' where name like '%C%' limit 3;
删除数据
与更新类似:可以通过limit限制数量
--删除数据:限制数量为2
delete from my_copy where name ='修改后' limit 2;
删除:如果表中存在主键自增长,那么当删除之后,自增长不会还原
思路:数据的删除是不会改变表结构,只能删除表后重建表
truncate 表名; --先删除表,后新增表
--清空表:重置自增长
truncate my_student;
查询数据
基本语法
select 字段列表/* from 表名 [where 条件]
完整语法
select[select 选项] 字段列表[字段别名]/* from 数据源 [where 条件子句]
[group by子句][having子句][limit子句]
select选项:
select 对查出来的结果的处理方式
ALL:默认的,保留所有的结果
distinct 去重
select distinct * from my_copy;
字段别名
当数据进行查询出来的时候,有时候名字并不一定满足需求(多表字段会有同名字段)
需要对字段名进行重命名:别名
语法:字段名 [as] 别名
数据源
数据的来源,关系型数据库的来源都是数据表:本质上只要保证数据类似二维表,最
终都可以作为数据源。
数据源分为多种:单表数据源,多表数据源,查询语句
单表数据源:select * from 表名;
select * from my_copy;
多表数据源:select * from 表名1,表名2...;
select * from my_copy,my_student;
从一张表中取出一条记录,去另外一张表中匹配所有记录,而且全部保留(记录数和字段数),
将这种结果称为:笛卡尔积(交叉连接);没太大用,应该尽量避免。
子查询:数据的来源是一条查询语句
select * from (select 语句 ) as 别名;
select * from (select * from my_student ) as student;
where子句
用来判断数据,筛选数据
where子句返回结果:0或者1,0代表false,1代表true;
判断条件:
比较运算符:>,<,>=,<=,!=,<>,=,like,between and,in/not in
逻辑运算符:&&(and),||(or),!(not)
where原理:where是唯一一个直接从磁盘获取数据的时候就开始判断的条件;
从磁盘取出一条记录,开始进行where判断,判断的结果如果成立保存到内存;
如果失败直接放弃。
alter table my_student add age tinyint unsigned;
alter table my_student add height tinyint unsigned;
--增加值 rand取得一个0到1之间的随机数
update my_student set age=floor(rand()*20+20),height=floor(rand()*20+170);
条件查询1:要求找出学生id为1或者3或者5的学生
select * from my_student where id in (1,3,5);
条件查询2:找出身高在180到190之间的学生
select * from my_student where height between 180 and 190;
between本身是闭区间;左边的值必须小于或者等于右边的值。
group by 分组
根据某个字段分组
--根据性别分组
select * from my_student group by sex;
分组的意义:是为了统计数据(按组统计:按分组字段进行数据统计)
SQL提供一系列统计函数
count() :统计分组后的记录数:每一组有多少记录
max() :统计每组中最大的值
min() : 统计最小值
avg() : 统计平均值
sum() : 统计和
--分组统计:身高高矮,年龄平均和总年龄
select sex,count(*),max(height),min(height),avg(age),sum(age) from my_student group by sex;
分组不统计没有意义
count函数:里面可以有两种参数*/字段名,NULL不统计
分组会自动排序:根据分组字段:默认升序
group by 字段 [asc|desc] ---对分组的结果然后合并之后的整个结果排序
多字段分组:先根据一个字段进行分组,然后对分组后的结果再次按照其他字段进行分组。
select c_id,sex,count(*) from my_student group by c_id,sex ;
函数:group_concat(字段),可以对分组的结果中的某个字段进行字符串连接(保留该组所有的值)
select c_id,sex,count(*),group_concat(name) from my_student group by c_id,sex;
回溯统计:with rollup
任何一个分组后的结果都会有一个小组,最后都需要向上级分组进行汇报统计,
根据当前分组的字段,就是回溯统计
select c_id,count(*) from my_student group by c_id;
--回溯统计
select c_id,count(*) from my_student group by c_id with rollup;
select c_id,sex,count(*),group_concat(name) from my_student group by c_id,sex;
--多字段分组回溯统计
select c_id,sex,count(*),group_concat(name) from my_student group by c_id,sex with rollup;
having子句
与where子句一样:进行条件判断的。
where是针对磁盘数据进行判断;进入到内存之后,会进行分组操作,分组结果就需要having来处理。
--求出所有班级人数大于等于2的学生人数
select c_id,count(*) from my_student group by c_id having count(*)>=2;
having能够使用字段别名,where不能;where是从磁盘取数据,而别名是在数据进入内存后才产生。
select c_id,count(*) as total from my_student group by c_id having total>=2;
select name as 名字,number from my_student having 名字 like 'Jim';
order by子句
排序:根据某个字段进行升序或都降序排序,依赖校对集。
order by 字段名 asc|desc;
asc 升序 desc 降序
排序可以进行多字段排序;先根据某个字段进行排序,然后排序好的内部,再按照某个数据进行
再次排序。
--多字段排序:先班级排序,再性别排序
select * from my_student order by c_id asc,sex desc;
limit子句
是一种限制结果的语句:限制数量
limit有两种使用方式
方案1:只用来限制长度(数据量) :limit 数据量
--查询前两个
select * from my_student limit 2;
方案2:限制起始位置,限制数量:limit 起始位置,长度
--查询从第2个数开始找2个 记录数从0开始编号
select * from my_student limit 1,2;
可以用来实现分页,为用户节省时间,提高服务器的响应效率,减少资源浪费
分享到:
相关推荐
【标题】基于Myeclipse与MySQL数据库表格的增删改查 在开发Web应用程序时,数据库操作是必不可少的一部分。Myeclipse是一款强大的Java集成开发环境,而MySQL则是一款广泛使用的开源关系型数据库管理系统。本教程将...
MySQL是世界上最流行的关系型数据库管理系统之一,被广泛应用于网站开发、数据分析、企业系统等领域。这份学习文档涵盖了MySQL的基础知识和核心概念,对于初学者来说是一个很好的起点。 1. **DOS下的常用操作**:在...
如果发现某列有重复属性,应当创建新的实体,用一对多关系与原实体关联。 2. 第二范式(2NF):在此基础上,要求每个实体的实例都能被唯一识别,通常通过添加主键来实现。此外,非主属性应完全依赖于主键,避免部分...
在数据库操作中,增、删、改、查(CRUD)是最基本的操作。增加数据涉及INSERT语句,删除数据用DELETE,更新数据用UPDATE,查询数据则用SELECT。掌握这些基础SQL语句是数据库操作的基础。 索引是提高查询效率的关键...
该书不是入门教程,而是为已经熟悉基本的增删改查操作的读者设计,特别是对SQL语言有一定了解但对MySQL内部运作不熟悉的程序员。 作者强调,本书并非传统的学术著作或权威教材,没有繁复的代码示例和详尽的理论证明...
数据库是存储数据的场所,用户可以通过执行增删改查等操作来管理数据。数据库系统采用一定的数据模型,如关系型模型,以确保数据的结构化和有序性。关系型数据库中,数据以表格的形式存储,每个表格由若干列和行组成...
系统可能利用了MySQL的表结构来存储班级、学生和教师等信息,通过SQL(Structured Query Language)进行数据的增、删、改、查操作。 【班级信息管理】 班级信息管理系统主要负责管理与班级相关的各种数据,如班级...
此外,练习可能包含对数据库的增删改查(CRUD)操作,如INSERT用于插入新记录,UPDATE用于修改现有记录,DELETE用于删除记录,以及ALTER TABLE语句来修改表结构。这些基本操作是数据库管理员日常工作中不可或缺的...
**增删改查操作** CRUD是任何数据管理系统的核心功能。在学生管理系统中,这些操作可能涉及到以下细节: 1. **创建(Create)**:使用INSERT语句向数据库添加新学生信息。 2. **读取(Read)**:使用SELECT语句...
用户可以通过SQL语言对数据库中的数据执行增、删、改、查等操作。在MySQL中,数据以表格的形式存在,核心元素包括数据行、数据列、数据表以及数据库(表的集合)。常见的关系型数据库有MySQL、Oracle、Microsoft SQL...
- **增删改查**:详述INSERT、UPDATE、DELETE语句的用法。 - **聚合函数**:如SUM、AVG、COUNT等函数的使用方法。 #### 三、数据库设计 - **实体关系模型**:ER图的绘制方法及原则。 - **范式化**:第一范式至第三...
基础操作是数据库管理的基础,涵盖数据库和数据表的操作,以及数据的增删改查。创建、修改和删除数据库与数据表是数据库结构管理的核心。对数据表进行CRUD(创建、读取、更新和删除)操作是处理数据的基础。SQL语言...
- **接口设计**:定义清晰的API接口,使得前端能够调用后台服务,执行增删改查操作。这些接口可能遵循RESTful原则,使用HTTP的GET、POST、PUT、DELETE方法对应数据库的查询、创建、更新和删除。 - **安全性**:后台...
通过学习,读者将能够编写出复杂的SQL查询语句,实现对数据库数据的增、删、改、查。 三、数据库设计与范式理论 良好的数据库设计是保证数据一致性和效率的关键。本指南会讲解第一范式(1NF)、第二范式(2NF)、第...
接下来,将深入探讨SQL语言,包括数据的增删改查(CRUD)操作,以及如何利用SELECT语句进行复杂的查询和聚合函数的使用。 在数据库设计方面,小辉老师会讲解关系模型、范式理论以及如何进行数据库规范化,确保数据...
例如,普通用户可能只有阅读权限,而管理员则有增删改查的权限。 6. **事务处理**:百科系统中可能涉及多表操作,如同时更新文章内容和版本信息,此时需确保事务的ACID(原子性、一致性、隔离性和持久性)属性,...
一旦连接建立,就可以执行SQL语句进行数据的增删改查操作。 3. **安全性**: 在处理数据库连接时,安全措施至关重要。使用预编译的SQL语句可防止SQL注入攻击,同时应定期更改数据库密码,并限制对敏感数据的访问...
使用SQL语言进行数据的增删改查操作,并通过事务处理来保证数据的一致性。 最后,为了验证数据库设计的正确性,我们需要进行数据建模,绘制ER图(实体关系图),并编写相应的SQL脚本来创建数据库表。在实际运行系统...