在复习MySQL时的一些笔记,记录的细节多一点,基础少一点。
show databases;
use databaseName;
show tables;
show tables from databaseName; # 不改变数据库
select database(); # 当前所在数据库
create table tableName(
id int,
name varchar(20));
desc tableName; # 显示表的结构
select version(); # 登录到mysql服务端,查看服务器版本
#mysql --version; || mysql -V 没有登录
#DQL 数据查询
select * from tableName;
#为字段起别名 as xxxxx as可以省略
#去重
select distinct fieldName from tableName;
#连接成一个字段
select concat(fieldName1,fieldName2[,...]) from tableName;
# mysql中‘+’号的作用:运算符 如果一方为null 结果为null
#判断是否为null
select ifnull(expr, return); #如果expr为null返回return
#模糊查询like 占位符 %(任意数量占位符) _(一个占位符)
#escape '$' 指定$为转移字符
#安全等于 <=>
#order by fieldName (desc | asc) 除了limit外一般都放在order by前面
#length(fieldName) 计算长度
#分类:
#单行函数:如concat、length、ifnull
#字符函数
length(str)#获取参数值的字节个数,汉字为3(UTF-8)
concat(str...)#拼接字符串
upper(str)、lower(str)#转换为大小写
substr(str, pos[, len])、substring()#注意SQL的索引是从1开始!!!
instr(str, substr)#返回substr在str中的第一个起始索引,找不到返回0
trim(str)#取出前后的空格 trim('a' from 'aaaaaaaaaa123aaaaaa')去掉a
lpad(str, len, padstr)、rpad()#用padstr实现左填充指定长度 最终长度为len 长度超过len会从右边截断
replace(str, from_str, to_str)#将str中的from_str变为to_str
#数学函数
round(x[, D])#四舍五入, 为保留的位数
ceil(x)、floor(x)#向上取整、向下取整
truncate(x, D)#将x小数点后保留D位
mod(x,y)#返回x%y
#日期函数
now()#返回当前系统日期+时间
curdate()#返回当前系统日期
curtime()#返回xxxxxxx时间
year(date)、month(date)、monthname(date)#返回date的年、月、日、时、分、秒,date可以是字符类型
str_to_date(str, format)#将str按format格式解析为日期类型
date_format(date, format)#将日期转成字符类型
datediff(date1, date2)#返回date1-date2的天数
#其他函数
version()#版本号
database()#查看当前数据库
user()#查看当前用户
#流程控制函数
if(expr1,expr2,expr3)#实现if else的效果,如果条件expr1成立,返回true执行expr2,返回false执行expr3
case()#实现switch case的效果
select salary 原始工资, department_id,
case department_id
when 30 then salary*1.1
when 40 then salary*1.2
when 50 then salary*1.3
else salary
end as 新工资
from employees;
#实现if else if else的效果
case
when 条件1 then 语句1
when 条件2 then 语句2
when 条件3 then 语句3
else 语句n
end
#分组函数:
#功能:做统计使用,又称为统计函数、聚合函数、组函数
sum([distinct] x)、avg()、max()、min()、count()#求和、平均值、最大值、最小值、计算非空个数,这些函数都忽略null值
#★★★★★★MYISAM存储引擎(内部有一个计数器)下,count(*)的效率最高
#★★★★★★INNODB存储引擎下,count(*)和count(1)的效率差不多,比count(fieldName)高,因为后者有一个筛选过程。
#和分组函数一同查询的字段有限制,如select avg(salary), employee_id from employees;
#group by xxx,xxx
#如查询每个部门的平均工资,
select avg(salary) from employees group by department_id;
#添加分组前筛选条件 where(where筛选条件的字段都来自于原始表)
#添加分组后筛选条件 having
#如查询哪个部门的员工个数大于2
select department_id from employees group by department_id having count(*)>2;
#查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
select job_id, max(salary) where commission_pct is not null group by job_id having max(salary)>12000;
# 数据源
#分组前筛选 原始表
#分组后筛选 分组后的结果集
#★★★★★★★★分组函数做条件肯定是放在having子句中
#★★★★★★★★能用分组前筛选的,就优先考虑使用分组前筛选
#分类:
#按年代分类:
#sql92标准 mysql仅仅支持内连接
★★★★★★#sql99标准【推荐】:mysql支持内连接+外链接(左外和右外)+交叉连接
#按功能分类:
#内连接:
#等值连接:多表等值连接的结果为多表的交集部分,n表连接至少需要n-1个连接条件
#非等值连接
#自连接
#外连接:用于查询一个表有,另一个表没有的数据
#外链接的查询结果为主表中的所有记录
#如果从表中有匹配的,则显示匹配的值
#如果从表中没有和它匹配的,则显示null
#外链接查询结果=内连接结果+主表中有而从表中没有的记录
#左外连接,left左边的是主表
#右外连接,right右边的是主表
#全外连接:结果=内连接结果+表1有表2没有+表2有表1没有 mysql不支持
#交叉连接:笛卡尔积
#sql92语法
select a.*,b.* from a,b where a.id = b.a_id; ...
#sql99语法
select 查询列表 from
表1 别名 [连接类型]
join 表2 别名
on 连接条件
[where 筛选条件]
[group by 分组]
[having 筛选条件]
[order by 排序列表]
#连接类型
内连接:inner
外连接:left [outer] right [outer] full [outer]
交叉连接:cross
#出现在其他语句中的select语句
#分类:
#按子查询出现的位置
#select后面:仅仅支持标量子查询
#查询每个部门的员工个数
select d.*, (
select count(*)
from employees e
where e.department_id = d.department_id
)
from departments d;
#from后面:支持表子查询
#查询每个部门的平均工资的工资等级
select ag_dep.*, g.grade_level
from (
select avg(salary) ag,department_id
from employees
group by department_id
) ag_dep
inner join job_grades g
on ag_dep.ag between lowest_sal and highest_sal;
★★★#where或having后面:★★★标量子查询,★★★列子查询,行子查询
#标量子查询:如谁的工资比Abel高?
select name
from employees
where salary > (
select salary
from employees
where name = 'Abel'
);
#列子查询:返回location_id是1400或1700的部门中的所有员工的姓名
select name
from employees
where department_id in (
select distinct department_id
from departments
where location_id in (1400, 1700)
);
#行子查询:查询员工编号最小并且工资最高的员工信息
select *
from employees
where employee_id = (
select MIN(employee_id)
from employees
) and salary = (
select MAX(salary)
from employees
);
#exists后面(相关子查询):表子查询,返回1或0
select bo.*
from boys bo
where not exists(
select boyfriend_id
from beauty b
where bo.id = b.boyfriend_id
);
#按结果集的行列数不同:
#标量子查询(结果集只有一行一列):一般搭配单行操作符使用 > < >= <= = <>
#列子查询(结果集只有一列多行) in any/some all
#行子查询(结果集有多行多列)
#表子查询(结果集一般为多行多列)
select 查询列表
from 表
[join type join 表2
on 连接条件
where 筛选条件
group by 分组字段
having 分组后的筛选
order by 排序字段]
limit offset, size;
#offset要显示条目的起始索引(从0开始)
#size要显示的条目个数
#union 合并:将多条查询的结果合并成一个结果
#要求多条查询的列数是一致的
#要求多条查询的每一列的类型和顺序最好一致
#union关键字默认去重,如果使用union all 可以包含重复项
#查询部门编号>90或邮箱包含a的员工
select * from employees where department_id>90
union
select * from employees where email like '%a%';
#插入:insert
#修改:update
#删除:delete
insert into 表名(列名,...) values(值1,...);
#支持多行插入和子查询
insert into 表名 set 列名=值, 列名=值, ...;
#不支持多行插入,不支持子查询
#修改单表
update 表名 set 列名=值,.... where 筛选条件
#修改多表
#sql92语法
update 表1 别名,表2 别名
set 列=值,...
where 连接条件 and 筛选条件;
#sql99语法
update 表1 别名
连接类型 join 表2 别名
on 连接条件
set 列=值,...
where 筛选条件;
#删除单表
delete from 表名 where 筛选条件
#删除多表
#sql92语法
delete 表1的别名,表2的别名
from 表1 别名, 表2 别名
where 连接条件 and 筛选条件;
#sql99语法
delete 表1的别名,表2的别名
from 表1 别名
连接类型 join 表2 别名
on 连接条件
where 筛选条件;
#清空表
truncate table 表名; #不能使用where
#加入删除的表中有自增长列,如果用delete删除后,在插入数据,自增长列的值从断点开始,
#truncate删除后,再插入数据,自增长列的值从1开始
#truncate删除没有返回值,delete删除后有返回值
#truncate删除不能回滚,delete删除可以回滚
#库的创建
create database [if not exists] 库名;
#库的修改
rename database 旧库名 to 新库名;#版本升级后,废弃了,因为不安全,数据有可能丢失
#更改库的字符集
alter database 库名 character set 编码方式;
#库的删除
drop database [if exists] 库名;
#表的创建
create table [if not exists] 表名(
列名 列的类型[(长度) 约束],
....
列名 列的类型[(长度) 约束]
);
#表的修改
#alter table 表名 add|drop|modify|change|rename column 列名 列类型 约束;
#列名
alter table 表名 change column 旧列名 新列名 新列类型;
#列的类型或约束
alter table 表名 modify column 旧列名 新列类型;
#添加列
alter table 表名 add column 新列名 新类型;
#删除列
alter table 表名 drop column [if exists] 列名;
#表名
alter table 表名 rename to 新表名;
#表的删除
drop table [if exists] 表名;
#表的复制
#仅仅复制的是表的结构
create table 新表 like 需要复制的表;
#复制表的结构+数据(可以只复制部分列或数据)
create table 新表
select * from 需要复制的表;
#仅仅复制某些字段
create table 新表
select 字段1,字段2...
from 需要复制的表
where 0;
#数值型:
#整型
#tinyint 占1字节 有符号-128~127 无符号0~255
#smallint 占2字节 有符号-32768~32767 无符号0~65535
#mediumint 占3字节 有符号。。。。
#int、integer 占4字节
#Bigint 占8字节
#设置无符号 数据类型为 int unsigned
#超出范围会报out of range异常,并插入临界值
#如果不设置长度会有默认的长度,设置长度的时候 数据类型为 int(7) zerofill,如果不加zerofill长度无效,如果插入数据长度小于设置的长度,进行0填充。并且此时字段成为无符号。
#实数:
#定点数:
#dec(M,D)、decimal(M,D) 占M+2个字节,最大取值范围和double相同,保存精度更高。默认M=10,D=0
#浮点数:
#float(M,D) 占4个字节
#double(M,D) 占8个字节
#M:整数部位长度+小数部位 D:小数部位长度
#如果超过范围,插入临界值
#字符型:
#较短的文本:char(M)、varchar(M) M是最多字符数,char默认为1可以省略,varchar不可省略。
#char 固定长度的字符 比较耗费空间 效率高
#varchar 可变长度的字符 比较节省空间 效率低
#enum('a','b','c') 只可以选择一个插入
#set 可以选择多个插入 insert into 表名 values('a,b');
#binary varbinary 用于保存较短的二进制
#较长的文本:text、blob(较长的二进制数据
#日期型:
#date 占4字节 最小值1000-01-01 最大值9999-12-31
#datetime 占8字节 最小值1000-01-01 00:00:00 最大值9999-12-31 23:59:59
#timestamp 占4字节 最小值19700101080001 最大值2038年的某个时刻
#受时区的影响
#time 占3字节 最小值-838:59:59 最大值838:59:59
#year 占1字节 最小值1901 最大值2155
#set time_zone='+09:00'修改时区
#为了保证数据的准确和可靠性
#分类:六大约束
#not null:非空
#default:默认值
#primary key:主键
#unique:唯一
#check:检查约束[mysql中不支持]
#foreign key:外键
create table 表名(
字段名 字段类型 列级约束,
字段名 字段类型,
表级约束
);
#外键约束不能作为列级约束
#非空和默认约束不能作为表级约束
#添加删除约束
#创建表时
#表级约束
#[constraint 约束名] 约束类型(字段名)
constraint 主键名 primary key(主键字段[, 主键字段]);
constraint 唯一键名 unique(唯一字段);
constraint 检查约束 check(检查字段 = '字段值'[or ...]);
constraint 外键名 foreign key(外键字段) references 主表名(主表主键);
#通用写法
drop table if exists stuinfo;
create table stuinfo(
id int primary key,
stuname varchar(20) not null,
sex char(1),
age int default 18,
seat int unique,
majorid int,
constraint fk_stuinfo_major foreign key(majorid) references major(id)
);
#修改表时
#列级约束
alter table 表名 modify column 字段名 字段类型 约束;
#表级约束
alter table 表名 add [constraint 约束名] 约束类型(字段名);
#删除约束
alter table 表名 modify column 字段名 字段类型; alter table 表名 drop (primary key | index 索引名 | foreign key 外键名);
#外键
#要求在从表设置外键关系
#从表的外键列的类型和主表的关联列的类型要求一致或兼容,名称无要求
#主表中的关联列必须是一个键(主键、唯一)
#插入数据,先插入主表,再插入从表
#删除数据,先删除从表,在删除主表
#标识列 auto_increment
#设置步长为3
set auto_increment_increment=3;
#标识列只能是数值型
#一个表最多有一个
#要求和key共同作用一个字段
Transaction Control Language
事务:一个或一组sql语句组成一个执行单元,要么全部执行,要么全部不执行。
set autocommit=0;
start trasaction;#可选
#编写sql语句
commit;#提交事务
rollback;#回滚事务
savepoint name;#节点名,设置保存点
rollback to a;#回滚到savepoint a
对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题。
脏读
对于两个事务T1、T2,T1读取了已经被T2更新但还没有被提交的字段之后,若T2回滚,T1读取的内容就是临时且无效的。(在一个事务内,读取到假数据)
不可重复读
对于两个事务T1、T2,T1读取了一个字段,然后T2更新了该字段之后,T1再次读取同一字段,值就不同了。(在一个事务内,读取到的数据不一致)
幻读
对于两个事务T1、T2,T1从一个表中读取了一个字段,然后T2在该表中插入了一些新的行之后,如果T1再次读取同一个表,就会多出几行。(一个事务内,结果集不同)
Oracle支持两种事务隔离级别:read committed(默认),serializable。
MySQL支持四中:read uncommitted、read committed、repeatable read(默认)、serializable
select @@tx_isolation;#查看当前隔离级别
set session transaction isolation level read uncommitted;#将隔离级别设置为read uncommitted
set global transaction isolation level read committed;#设置数据库系统的全局隔离级别
delete支持回滚,truncate不支持回滚。
虚拟表,和普通表一样使用
mysql5.1版本出现的新特性,是通过表动态生成的数据。
多个地方用到同样的查询结果。
该查询结果使用的sql语句较复杂。
#视图创建
create view 视图名
as
查询语句;
#视图修改
create or replace view 视图名
as
查询语句;
alter view 视图名
as
查询语句;
#视图删除
drop view 视图名, 视图名,...;
#视图查看
desc 视图名;
show create view 视图名;
#视图更新
insert into 视图名 values(值1, 值2....);
update 视图名 set 字段1=值1,... where 筛选条件;
delete from 视图名 where 筛选条件;
#不允许更新的视图
#包含以下关键字的sql语句:分组函数、distinct、group by、having、union或者union all
#常量视图
#select中包含子查询
#连接
#from一个不能更新的视图
#where子句的子查询引用了from子句中的表
#视图占用了一点点物理空间,保存sql的逻辑
#系统变量:变量由系统提供,属于服务器层面,包含全局变量和会话变量
#查看所有的系统变量:
show [global|session] variables;
#查看满足条件的:
show [global|session] variables like '%%';
#查看指定的某个系统变量:
select @@[global|session].系统变量名;不写默认为会话
#为某个系统变量赋值:
set [global|session] 系统变量名=值;
set @@[global|session].系统变量名=值;
#全局变量
#作用域:服务器每次启动将为所有的全局变量赋初始值,针对所有的会话(连接)有效,但不能跨重启。
#会话变量
#作用域:仅仅针对于当前会话(连接)有效。
#自定义变量:用户自己定义
#使用步骤:声明,赋值,使用。
#用户变量:
#作用域:针对于当前会话(连接)有效。
#声明并初始化
set @用户变量名=值;
set @用户变量名:=值;
select @用户变量名:=值;
#赋值(更新用户变量值)
#同声明初始化
#或者
select 字段 into 变量名 from 表名;
#应用在任何地方,也就是begin end里面或外面
#局部变量:
#作用域:仅仅在定义它的begin end中有效
#声明:
declare 变量名 类型;
declare 变量名 类型 default 值;
#赋值:
set 局部变量名=值;
set 局部变量名:=值;
select @局部变量名:=值;
select 字段 into 变量名 from 表名;
#使用
select 局部变量名;
#应用在begin end中的第一句话★★★★★★
一组预先编译好的SQL语句的集合,理解成批处理语句。
减少了编译次数并且减少了和数据库服务器的链接次数,提高了效率。
#创建
delimiter $
create procedure 存储过程名(参数列表)
begin
#存储过程体;
end $
#★★★★注意:
#参数列表包含三部分:参数模式 参数名 参数类型 如 in stuname varchar(20)
#参数模式
#in:该参数可以作为输入,该参数需要调用方传入值
#out:该参数可以作为输出,该参数可以作为返回值
#inout:该参数既可以作为输入,又可以作为输出
#如果存储过程体只有一句话,begin end可以省略
#存储过程体的每条SQL语句的结尾要求必须加分号。而存储过程的结尾可以使用delimiter重新设置 语法:delimiter 结束标记
#调用
call 存储过程名(实参列表);
#空参列表 call myp1()$
#带in模式参数的存储过程 call myp2('参数')$
#带out模式参数的存储过程 call myp3('参数', @用户变量名)$
#带inout模式参数的存储过程 先设置用户变量然后call myp4(@用户变量名)$
#删除
drop procedure 存储过程名, 存储过程名2;
#查看
show create procedure 存储过程名;
和存储过程的区别:
存储过程可以有0个返回,也可以有多个返回。
函数有且仅有1个返回。
#创建
create function 函数名(参数名 参数类型) returns 返回类型
begin
函数体
end
#调用
select 函数名(参数列表)
#查看
show create function 函数名;
#删除
drop function 函数名;
#顺序结构
#分支结构
if(expr1, expr2, expr3); 如果expr1成立,返回expr2,否则返回expr3
#if实现多重if
if 条件1 then 语句1;
elseif 条件2 then语句2;
...
else 语句n;
end if;
#switch
case 变量|表达式|字段
when 要判断的值 then 返回的值1
...
else 要返回的值n
end
#多重if
case
when 要判断的值 then 返回的值1
...
else 要返回的值n
end
#循环结构
#while
[标签:] while 循环条件 do
循环体;
end while [标签];
#loop
[标签:] loop
循环体;
end loop [标签];
#repeat
[标签:] repeat
循环体;
until 结束循环的条件
end repeat [标签];
#iterate:类似continue
#leave:类似break
概念:在mysql中的数据用各种不同的技术存储在文件(或内存)中。
show engines; 进行查看存储引擎
在mysql中用的最多的存储引擎:
innodb、myisam、memory
innodb支持事务,而其他两个不支持。