目录
数据库(Database)
MySql
1.DDL、DML与DQL
2.数据库设计与约束
3.数据类型
4.变量的类型
5.存储过程
6.函数
7.触发器
8.游标
9.事务
10.视图
11.索引
数据库即存储数据的仓库,常见的数据存储方式有普通文本文件、excel文件、xml文件(多见于配置文件)以及数据库,其中数据库可以保证完整性与安全性,在数据库中基本的单元为表,而表与表的关系表现为一对一,一对多与多对多的关系。其中常见的的为一对多的关系。大多数数据库依靠数据管理系统(database management system)进行数据的管理,关系型数据库的管理软件通过关系型数据库管理系统(relational dbms)与关系型数据库进行交互。
mysql自身的特点:开源,支持大型数据库64位表文件可达8TB,使用标准的SQL语言,移植性好,可运行于多种系统,同时支持多种语言,流行的C与JAVA都支持,同时良好的支持PHP这一最流行的Web开发语言。
mysql在dos命令行的常用指令:
1.net start/stop mysql 启动或停止mysql服务
2.mysql -u root -p 以root用户登录mysql服务器
3.在mysql服务器中:exit 退出服务器
学习之前需要知道的名词:DB(database)数据库、DBA(database administrator)数据库管理员、DBMS(database management system)数据库管理系统、RDBMS(relational DBMS)关系型数据库、SQL(structured query language)结构查询语言、DDL(data definition language)数据定义语言、DML(data manipulation language)数据操作语言、DQL(data query language)数据查询语言、DCL(data control language)数据控制语言。
SQL是一种用于管理关系型数据库,与数据库中的数据进行通讯的计算机语言,目前仍是最普遍的数据库语言,可以说是数据库管理的标准语言。
DCL是数据控制语言,不做太多需求,核心的关键字为grant(提供权限)、revoke(解除权限)
学习数据库首先要明确数据库的操作无非是增删改查的操作,从这四个方向学习即可掌握,首先谈DDL,即数据定义语言,具体含义顾名思义也可以看懂,是对数据的定义,大体上分为create、drop、alter三个主要的方向,具体使用如下:
create database database_name; #创建数据库
use database_name; #使用该数据库
drop database database_name; #删除数据库
alter database database_name character set=charset_name;
#多使用utf-8,如果录入中文前未设置合适的字符集,更改后还需将数据重新录入
create table table_name( #创建表,其中col_type对应表中字段的数据类型,需注意的是最后一列
col_name col_type, 的声明不用加逗号
...
);
create table tab_name1 as (select * from tab_name2); #复制表,包括内容
create table tab_name1 like tab_name2 #仅复制表的结构
drop table table_name; #删除表
alter table rename [to|as] new_tab_name; #更改表名
alter table change column old_col_name new_col_name col_type #更改列的名称与类型
alter table table_name add column col_name col_type; #新增一列
alter table table_name modify column col_name col_type; #修改列属性
alter table table_name drop column col_name; #删除列
truncate table table_name; #清空表内容
DML:数据操作语言,具体的有增删改功能,分别对应insert、delete、update具体用法如下:
insert into table_name(col_name1,col_name2) values(value1,value2);
# 列名与值相对应,当插入多组数据时,方便的做法和还有
insert into table_name(col_name1,col_name2) values
(value1,value2),
(value1,value2),
(value1,value2),
(value1,value2); #这样相当于插入四组数据
update table_name set col_name=value [where ...]
#更改数据的时候常需要设置条件,否则整列都会被置为value
delete from table_name [where....]
#从数据中删除,where后为筛选的条件
DQL:数据查询语言,负责查的功能,以select为核心,还有高级查询和复杂查询部分,分别为子查询(select的嵌套使用,多表现为一层一层查找符合要求的外键),组合查询(select union select,表现为行的添加合并,要求两个select的结果列数相同,最好值得类型也相同,union all不会去掉重复的部分,单独使用union会去掉重复的部分),联接查询(内联与外联,其中外联又分左联和右联,体现在以哪一张表的内容为基准,有多退少补的特点)具体的用法如下:
select col_name1,col_name2 #执行顺序:先根据where设置的条件筛选表的内容,然后根据group
from table_name 的内容进行分组,根据select的内容,有聚合函数的会为每组计算聚合函数的
where .... 结果,根据having的条件将组过滤,留下符合需求的组,最后根据order by的
group by col_name 依据进行排序
having ...
order by col__name;
#可以通过AS给字段或者表起别名,便于阅读与使用,select的结果整体也可以用AS起名,当做临时表使用
select col_name as 别名 from table_name
#limit为限制行数,此处是从第一行开始输出十行
select * from table_name limit 0,10;
#distinct可以去除重复字段,与group不同,如果还有别的字段被查询,而且没有重复,distinct实际没有起到
#作用
select distinct col_name from tab_name;
#有条件的筛选,满足condition1 与/或 condition2的才被取出
select * from tab_name where condition1 and/or condition2;
#值得注意的运算符 sql中<>和!=同义,即不等的意思
select * from tab_name where col_name<>value;
#between 可以设置值范围要求,但是是闭区间,这句表示该字段(不)在[borderlow,borderup]中的时候
select * from tab_name where col_name (not)between borderlow and borderup;
#in 可以匹配多个值,这句表示当该字段是三个值之中的任意一个时
select * from tab_name where col_name in ('value1','value2','value3');
#like 模糊查询,第一行表示以a开头的任意字符串,第二行则限制为以a开头的长度为2的字符串
select * from tab_name where col_name like 'a%';
select * from tab_name where col_name like 'a_';
#order by 查询排序 asc为升序排列,desc为降序排列,这句为根据该字段排序,不声明时默认为asc
select * from tab_name order by col_name;
#聚合分组
select max(col_name),min(col_name),avg(col_name),sum(col_name),count(col_name)
from tab_name
group by col_name
#聚合常与分组配合,上述为根据col_name进行分组,并为每组计算出该组的最大、最小、平均、和、行数
#聚合函数一定会分组,如果没有group by则默认将整张tab_name表作为组,计算出的就是整张表的相关结果
#聚合分组后每一组为一行数据,如果没有做相应的处理,可能会丢失第一行之后的数据
#分组后的筛选条件用having,表示对每组的结果进行筛选,而where是对原表,这也是为什么where后不能跟
#聚合函数的表达式判断
#子查询
select col_name
from tab_name
where col_name in/=(
select col_name
from tab_other_name
)
#上述为子查询的一种情况,其实就是select之间的嵌套,先通过内层的select进行初步的筛选,然后再进行
#外层的筛选,其中in对应多个可能值,=则要求内层提供的col_name为唯一的值,子查询的过程更像是通过外#键建立起来的表与表的关系进行对一个表一个表中内容的筛选
#exists特点:
select col_name from tab_name where exists(子查询)
#子查询本身就是条件判断,判断的依据是,如果结果至少有一条,则返回真,否则返回假
#any与all
#此处不过多赘述,与字面意思相同>any(子查询)就是只要大于子查询结果中任意的值就满足条件,而>all(子查询)则要求大于结果中所有的值才满足条件
#union 组合查询:组合查询的本质是合并行,制造一个新的临时表进行查询
select col_name1,col_name2 from tab_name1
union(all)
select col_name1,col_name2 from tab_name2;
#中间的临时表就表现为两个表中的两个字段的合并,唯一值得注意的是加all的时候不会去重复,即两个表如
#果出现相同的内容,不会剔除重复的,而不加all的时候会自动把重复的内容进行剔除,同时union的字段数应#该一致,建议值的类型也相同
#join 联接查询:联接查询本质是合并列,将多表的列合并成一个临时表,对临时表进行查询
#inner join:内联接
select *
from tab_name1 inner join tab_name2
on tab_name1.primarykey=tab_name2.foreignkey;
#on后为联接的条件,即临时表的内容为两者满足该条件的行合并列,整合为新的一行,内联接时,不满足联接#条件的被剔除,会丢掉不满足条件的行,两表的地位相同
#left/right join:左/右联接
select *
from tab_name1 left/right join tab_name2
on tab_name1.primarykey=tab_name2.foreignkey;
#左联接与右联接其实就是两表地位不同,有一个基准表,left和right分别代表左边和右边为基准表,制作中
#间表时候,基准表的内容全部保留,另一张表满足条件的与基准表该行合并列组成新的行,不满足条件的则自#动在内容补上空,当然了如果基准表该条件的内容为另一张表的子集则表现为,基准表的内容另一张表都有对#应的,此时表现出的结果和inner join无异
数据完整性:域完整性,实体完整性,参照完整性,自定义完整性
七大约束:主键,外键,自增,唯一,非空,控制,默认值
三大范式:1.列的原子性:列的内容必须拆分到底,一列只显示一个内容,列不可再分
2.行的唯一性:每行必须可以被唯一区分,表现为一个表一个类,不要出现其他事物的特性,表不可再分
3.每列与主键直接相关而不是间接相关:表现为列不能互相推出列,列的内容不能重复出现在别的 表中,除非作 为外键
a.主键约束
主键就是用来唯一标识每一行的列,可以一个或者多个(但不建议组合主键),在进行主键的选择时,应当尽量选择单个 列,并且选择相对更新更少的列来做主键,避免数据的不稳定。
主键的使用:
create table book(
book_id int primary key,
sort varchar(10),
book_name varchar(50),
writer varchar(10),
output varchar(50),
price int
#也可在最后使用联合主键其中中括号内的一般省略
#[constraint pk_colname]primary key(book_id,sort)
);
#如果在表创建以后定义,则使用语法为:
alter table book add constraint pk_bookid primary key(book_id);
#删除主键
alter table book drop primary key;
b.外键约束
外键就是表与表之间对应的列,不同于只能有一个主键,表可以有多个外键,使用时要求与主表中的主键或者唯一相对应,是表与表之间引用完整性的保证,使用如下:
create table borrow(
reader_id int,
book_id int,
borrow_date datetime,
foreign key(reader_id) references reader(reader_id),
foreign key(book_id) references book(book_id)
)
#上述为在创建表时进行声明外键
#如果对已经创建好的表进行外键的声明,类似主键的语法:
alter table borrow add constraint fk_readerid foreign key(reader_id)
references reader(reader_id)
on delete cascade on update cascode;
#其中reader为reader_id的主表,references之后的字段为当前表该字段的来源
#最后一行的on delete/update 代表在进行数据的删除和更新时外键的表现,其主要分为如下几种情况:
#cascade :父表删除更新之后,子表最值删除更新
#set null:父表删除更新时,当子表的外键不为not null时,子表的外键被置为空
#no action:innodb拒绝删除父表内容
#restrict:拒绝更新删除父表
#删除外键
alter table tab_name drop foreign key fk_name;
#由于外键可能不止一个,所以相比于主键需要加上要删除的外键的名称
c.其他约束:自增(auto_increment)、唯一(unique)、非空(not null)、控制(mysql不支持,可以通过set('','')或者 enum('','')实现)、默认值(default default_value)。
mysql中数据类型常用的大致分为:
1.字符串型:char(n),varchar(n)
2.数字型:整形:int,浮点型:float,decimal(m,n)
3.文本型:text
4.二进制型:blob 多用于存储图片
5.日期型:datetime,date
变量分为用户变量和系统变量,其中用户变量根据变量定义的位置不同,还可分为局部和全局,二者的声明方式有所不同;系统变量分为全局变量和会话变量,全局变量多是配置文件中涉及的变量,会话变量为此次连接所复制的一份变量。针对用户变量的两种情况其实际声明如下:
#用户全局变量的声明:
set @var_name = value;
#用户局部变量的声明(多在函数体和存储过程中):
declare var_name var_type default default_value;
#两种方式对应的调用和赋值也有所不同
#全局的赋值:
set @var_name = value;
#局部的赋值:
set var_name = value; #正常赋值
select col_name into var_name from tab_name; #还可以通过表中的数据进行赋值
#输出(sql中用输出可能不太准确,不过也是显示结果的)
select var_name;
#全局变量的调用要加上@来表示引用才可以,而局部可以直接使用变量名
存储过程和函数很像,都是完成特定任务的语法块,不同之处在于存储过程没有返回值,而且存储过程第一次运行时会进行预编译,以后调用的时候从服务器的缓存中调运,执行效率要高很多。其参数分为in与out类,如果不做声明,则默认为in,具体的语法如下:
create procedure proDemo()
begin
declare result int default -1;
select year(now())-year(sBirthday) into result from student where sName='张三';
if(result<12 && result>=0)then
select '是儿童';
elseif(result<18)then
select '是少年';
elseif(result<25)then
select '是青年';
elseif(result<60)then
select '是壮年';
elseif(result<200)then
select '是老年';
else
select '是妖怪';
end if;
end
call proDemo; #存储过程的调用与函数不同,需要使用关键字call,无参数时可不加()
drop procedure proDemo;
#上述代码是一个简单的存储过程,判断年龄区间并进行相应的操作,其语法上与函数差异并不是很大,需要注意的就是参数和返回值的问题
函数与其他语言体现在语法的区别,概念上没有太大的区别,以一个代码块为例:
create function primeJudge(number int) returns varchar(20)
begin
declare i int default 2;
declare flag int default 1;
label_1:while(i < number)do
if((number mod i)=0)then
set flag = 0;
leave label_1;
else
set i = i + 1;
end if;
end while label_1;
if(flag = 1)then
return '是质数';
else
return '不是质数';
end if;
end
#上述函数的功能是判断一个输入的数字是否为质数
#常用的库函数:
ifnull(expr1,expr2) #如果expr1为空则返回expr2,否则返回expr1,用于把null变为0
nullif(expr1,expr2) #如果两个表达式相同,则返回null否则返回expr1
concat(str1,str2,...,strn) #将多个字符串进行拼接
sunstring(index,length) #从下表为index-1位置开始截取length长度的字符串
uuid() #生成唯一的字符串
last_insert_id #返回最后插入的id
curdate()或者current_date() #返回当前的日期
curtime()或者current_time() #返回当前的时间
now() 返回当前的日期和时间
触发器是指在对表进行操作时会被触发的预设的代码块,不用调用,在对表内容进行操作时会自动触发,其声明方法如下:
create trigger tri_name before/after delete/update/insert on table_name for each row
begin
code_block;
end
#其中before,after分别对应相应的增删改操作进行之前还是之后执行code_block
#for each row是指每一行都被监视,更改它们都会触发触发器的内容
#在code_block中可能涉及对原表与新内容的操作,分别使用old与new来调用
游标本身有点像其他语言的数组一样,是select结果的结果集,但是不能像数组一样方便的使用下标调用,本质上也是指针操作,需要和fetch词进行配合,实例代码如下:
create table reader(
rid int primary key,
rname varchar(20),
rsex enum('男','女'),
rschool varchar(20)
);
create table reader_male(
rid int primary key,
rname varchar(20),
rsex enum('男','女'),
rschool varchar(20)
);
create table reader_female(
rid int primary key,
rname varchar(20),
rsex enum('男','女'),
rschool varchar(20)
)
insert into reader values(1,'令狐冲','男','华山派');
insert into reader values(2,'周芷若','女','峨眉派');
insert into reader values(3,'杨过','男','古墓派');
insert into reader values(4,'赵敏','女','汝阳王府');
insert into reader values(5,'灭绝师太','女','峨眉派');
insert into reader values(6,'范遥','男','明教');
#此处之上是添加表的内容
#定义的存储过程要完成读取表reader并按照性别分组插入reader_male和reader_female之中
drop procedure if exists readerord;
create procedure readerord()
begin
declare rdsex varchar(5); #定义变量用于接收游标中的内容
declare rdname varchar(20);
declare rdid int;
declare rdschool varchar(20);
declare flag int default false;
#定义游标(游标的声明和变量一样先名字后类型,可以当做特殊的数据类型):
declare cur_ord cursor for select rid,rname,rsex,rschool from reader;
declare continue handler for not found set flag=true; #异常处理,当游标的内容读完时
对应not found,此时设置flag为ture
open cur_ord; #游标的开启与关闭都需要手动,不能忘记开关两步操作
label1:while(true)do
fetch cur_ord into rdid,rdname,rdsex,rdschool; #fetch将指针指向的内容into
if(flag)then 给变量们,并且将指针指向下一
leave label1; 内容
elseif(rdsex='男')then
insert into reader_male values(rdid,rdname,rdsex,rdschool);
elseif(rdsex='女')then
insert into reader_female values(rdid,rdname,rdsex,rdschool);
end if;
end while label1;
select * from reader_male;
select * from reader_female;
close cur_ord;
end
call readerord;
#在定义的存储过程的过程中,使用了异常处理机制:
declare continue handler for not found set flag=true;
#其中处理的结果可以分为continue、exit、undo分别对应继续执行接下来的内容、跳出begin end块、不支
#持该句翻译过来就是当遇到没有找到的情况是将flag置为true,并继续执行接来下的内容
和生活中的事务一样,它描述的一件事,不能再进行分割,是需要一起完成的内容,适合多用户同时进行操作的系统。其具有的特点为ACID:
原子性(atom):事务是一个需要被完成的整体,其内部的每一步是需要一起完成的,因此不能再分割,是最小的逻辑体
一致性(constant):执行前后保证数据库的一致性,正确得转换状态
隔离性(isolation):事务与事务之间相互独立,互相之间不影响对方的成功与否
持久性(duration):执行之后数据库更新,效果被保留下来,不会丢失结果
事务控制语句:commit提交,rollback回滚,savepoint name保存点,rollback to name回滚到name的地方,release savepoint name 删除一个保存点,set transaction 设置事务的隔离级别
视图是窗口,对表进行查看与操作的窗口,操作的本质是对原表进行的操作,在使用时DQL的语法可以正常使用,但使用DML时要收到原表约束和完整性的限制,与表一样不可以重名,在原表变化后,应当重新建立视图,创建的方式如下:
create view view_name as
select col_name
from table_name
索引的作用是快速找到某一值,在没有索引的情况下,查找的过程需要将整张表遍历查找,当数据量庞大时,适当的使用索引可以增加查找的效率,所有的列都可以被索引,但是大量使用索引也会增加服务器负担,因为索引本身的存储也需要占用资源,特别是索引经常改动的字段时,成本将会很高。索引的使用简单概括如下:
#创建索引
create index index_name on tab_name(username(length));
#添加索引
alter table tab_name add index index_name(col_name);
#删除索引
drop index index_name on tab_name