mysql语法笔记

冷暖自知 提交于 2020-04-08 13:59:49

SQL语法笔记

基础查询

  1. distinct去除重复行;
  2. concat()使用concat包含多个字段作为一个字段输出;
    select concat(last_name ,',', first_name ,',',salary) as 员工工资 from employees; 
  3. as 别名,as也可以省略但是加as可以提高可读性;
  4. ifnull()函数:如果连接查询某个字段包含null,会导致该列的数据显示为空,使用ifnull判断一下可以有效解决该问题
    select concat(department_id,',',last_name,',',manager_id) from employees ; 
    -- 上图是不加ifnull函数,返回的值中有null 
    select concat(department_id,',',last_name,',',ifnull(manager_id,0)) as 奖金率 from employees ; 
  5. limit 限制输出返回行输
  6. 字符型和日期型的常量值必须用单引号引起来,数值型不需要
  7. isnull函数,判断某字段或表达式是否为null,如果是则返回1,否则返回0
    select isnull(commission_pct), commission_pct from employees; 

    条件查询

  8. select 查询字段 from 表名 where 筛选条件;

    先运行from表名,先判断表是否存在,再判断条件是否成立,最后是查询

  9. 条件运算符:> < <> != >= <=;
    -- 大于 
    select concat(last_name,' ',first_name,': ',department_id,', ',salary) as 员工工资 from employees where salary > 12000; 
    -- 小于 
    select concat(last_name,' ',first_name,': ',department_id,', ',salary) as 员工工资 from employees where salary < 12000; 
    -- 不等于 mysql官方推荐使用 <> 方式来表示不等于 
    select concat(last_name,' ',first_name,': ',department_id,', ',salary) as 员工工资 from employees where salary <> 12000; 
    select concat(last_name,' ',first_name,': ',department_id,', ',salary) as 员工工资 from employees where salary != 12000; 
    -- 大于等于 
    select concat(last_name,' ',first_name,': ',department_id,', ',salary) as 员工工资 from employees where salary >= 12000; 
    -- 小于等于 
    select concat(last_name,' ',first_name,': ',department_id,', ',salary) as 员工工资 from employees where salary <= 12000; 
  10. 逻辑运算符:&& || ! and or not ;
    -- and 
    select * from departments where department_id = 10 and manager_id = 200 ; 
    -- or 
    select * from departments where department_id=10 or location_id=1700 ; 
    -- not 
    select * from departments where not(department_id=10 or location_id=1700); 
  11. 模糊查询:like , between and ,in , is null,is not null ;
    /* 
    %表示任意多个字符; 
    _表示任意单个字符; 
    ESCAPE可以指定转义符,不能使用%作为转义符; 
    between and : 表示大于等于左边的值小于等于右边的值。 
    */ 
    -- %任意多个字符 
    select * from admin where username like '%oh%'; 
    -- _任意单个字符 
    select * from admin where username like '__h_' ; 
    -- ESCAPE指定转义符,\也可以作为转义符 
    select * from admin where username like 'ma_$_hu' ESCAPE '$' ; 
    -- between and 
    select concat(last_name,first_name,': ',salary) as 员工工资 from employees where salary between 10000 and 12000 ; 
    -- in in内不能包含通配符 
    select * from beauty where boyfriend_id in (8,9,3); 
    -- is null 、is not null is只能搭配null使用 
    select last_name ,first_name ,salary ,commission_pct from employees where commission_pct is null ; 
    select last_name, first_name ,salary , commission_pct from employees where commission_pct is not null; 
    -- <=> 安全等于,即可以判断null也可以判断其他值 
    select last_name ,first_name ,salary , commission_pct from employees where commission_pct <=> null ; 
    select concat(last_name,first_name,': ',salary) from employees where salary <=> 12000; 

    排序查询

  12. order by 排序字段 asc | desc
    -- asc 升序 
    select * from employees order by salary desc ; 
    -- desc 降序 
    select * from employees order by salary asc; 
  13. 按表达式排序
    select * , salary * 12 *(1+ifnull(commission_pct,0)) as 年薪 from employees order by salary * 12 *(1+ifnull(commission_pct,0)) desc; 
  14. 按照别名排序
    select * , salary * 12 *(1+ifnull(commission_pct,0)) as 年薪 from employees order by 年薪 desc; 
  15. 按照函数排序
    select length(last_name) as 字节长度,last_name , salary from employees order by 字节长度 desc; 
  16. 按多个字段排序
    select * from employees order by salary desc , employee_id ; 

    常用函数

    一、单行函数

  17. 字符函数
    -- length(): 获取参数值的字节个数; 
    select length(last_name) from employees; 
    -- concat(): 拼接字符串 
    select concat(last_name,',',first_name) as 姓名 from employees ; 
    -- upper(): 将字符变大写 
    select upper(`john`) ; 
    -- lower(): 将字符变小写 
    select lower('JOHN'); 
    -- substr(): 截取从指定字符后面所有字符 
    select substr('I love you km',3) ; 
    -- substr(): 截取从指定字符后面指定长度的字符 
    select substr('I love you km',3,4) ; 
    select concat(upper(substr(last_name,1,1)) ,'_',substr(last_name,2),first_name) as 姓名 from employees; 
    -- instr 返回子串第一次出现的索引,如果找不到返回零 
    select instr('I love you km','km') ; 
    select instr('I love you km','kmd') ; 
    -- trim 删除指定字符前后的字符,默认删除前后的空格 
    select trim(' zhangcuisan '); 
    select trim('a' from 'aaazhangsuisanaaa'); 
    -- lpad 用指定的字符实现左填充指定字符 
    select lpad('km', 10 ,'love') ; 
    -- rpad 用指定的字符实现右填充指定字符 
    select rpad('km', 10 ,'love') ; 
    -- replace 替换指定字符 
    select replace('字符串','原来字符','想要替换成的字符') 
    select replace('I love you km','km','kanmin') ; 
    select replace('kmkmkmI love you km','km','kanmin') ; 
  18. 数学函数
    -- round(),四舍五入 
    select round(浮点数,需要保留的小数点位数); 
    select round(1.68) ; 
    select round(1.6874,3) ; 
    -- ceil(),向上取整,返回>=该参数的最小整数 
    select ceil(1.68) ; 
    -- floor(),向下取整,返回<=该参数的最小整数 
    select floor(1.68) ; 
    -- truncate(),截断 
    select truncate(1.68973335,4); 
    -- mod(),取余 
    select mod(10,3) ; 
  19. 日期函数
    -- now(),返回当前系统日期加时间 
    select now() ; 
    -- curdate(),返回当前系统日期,不包含时间 
    select curdate(); 
    -- curtime(),返回当前系统时间,不包含日期 
    -- year(),获取时间年份 
    select year(now()) ; 
    -- month(),获取时间月份 
    select month(now()) ; 
    -- monthname(),获取英文的时间月份 
    select monthname('2019-08-09'); 
    -- str_to_date(),将字符转换为日期 
    select str_to_date('1998-08-09','%Y-%m-%d') as 年月日; 
    -- date_format(),将日期转换为字符 
    select date_format(now(),'%Y年%m月%d日') as 年月日 ; 
    select last_name, first_name , salary , commission_pct, date_format(hiredate,'%Y年%m月%d日') as 入职日期 from employees where commission_pct is not null ; 
    -- datediff(),计算两个日期之间相差的天数 
    语法是 select datediff('第一个时间','第二个时间') ;计算的是由第一个时间减去第二个时间的值 
    select datediff(now(),'19980129') as 活了多少天; 
  20. 其他函数
    -- version(),查看当前版本号 
    select version(); 
    -- database(),查看当前数据库 
    select database(); 
    -- user(),查看当前用户 
    select user(); 
  21. 流程控制函数
    -- if(),语法if(‘表达式’,'[true]输出这个信息','[false]输出这个信息') 
    select last_name, commission_pct,if(commission_pct is null ,'没奖金,呵呵','有奖金,嘻嘻') as 奖金情况 from employees ; 
    -- case(),语法 
    case 要判断的字段或表达式 
    when 常量1 then 要显示的值1或语句1 
    when 常量2 then 要显示的值2或语句2 
    ... 
    else 要显示的值n或语句n 
    end 
    select salary ,department_id ,case department_id when department_id = 30 then salary * 1.1 when department_id=40 then salary * 1.2 when department_id = 50 then salary * 1.3 else salary end as 新工资 from employees ; 
    case 
    when 条件1 then 要显示的值1或语句1 
    when 条件2 then 要显示的值2或语句2 
    。。。 
    else 要显示的值n或语句n 
    end 
    select last_name ,salary ,department_id ,case when salary > 20000 then 'A' when salary > 15000 then 'B' when salary > 10000 then 'C' else 'D' end as 工资级别 from employees ; 

    二、分组函数

  22. sum() 求和
    select sum(salary) from employees; 
  23. avg() 平均值
    select round(avg(salary),2) from employees; 
  24. min() 最小值
    select min(salary) from employees; 
  25. max() 最大值
    select max(salary) from employees; 
  26. count() 非null总行数
    select count(commission_pct) from employees; 

    特点

    sum、avg 一般用于处理数值型
    max、min、count可以处理任何类型
    以上分组函数都可以忽略null值
    可以实现和distinct搭配去重的运算

  27. 和分组函数一同查询的字段要求是group by 后的字段

    分组查询

    /* 
    语法: 
    select 分组函数,列(要求出现在group by的后面) 
    from 表 
    [where 筛选条件] 
    group by 分组的列表 
    [order by 子句] 
    注意: 
    查询列表必须特殊,要求是分组函数和group by 后出现的字段 
    */ 
    -- 分组后的筛选,数据源是分组后的结果集,意思是将分组查询输出后,对输出结果进行过滤,使用having关键字; 
    select count(*) as a,department_id from employees group by department_id having count(*) > 2 ; 
    -- 分组前筛选,数据源是原始表,需要把where 语句写在groub by 之前 
    select max(salary),job_id from employees where commission_pct is not null group by job_id ; 
    -- 分组函数做条件肯定是放在having子句中 
    -- 按多个字段分组,group by 子句支持单个字段分组和多个字段分组 
    select avg(salary), department_id ,job_id from employees group by job_id ,department_id ; 
    select avg(salary), department_id ,job_id from employees group by job_id ,department_id order by avg(salary) desc ; 

    连接查询

    /* 
    含义:多表查询, 
    按功能分类: 
    > 内连接: 
    > 等值连接 
    > 非等值连接 
    > 自连接 
    > 外连接: 
    > 左外连接 
    > 右外连接 
    > 全外连接 
    > 交叉连接 
    */ 

    SQL 92语法

  28. 等值连接
    select beauty.boyfriend_id as a , name , boyName from beauty , boys where beauty.boyfriend_id =boys.id; 
    select last_name, department_name from employees as a , departments as b where a.department_id=b.department_id ; 
  29. 非等值连接

    select e.job_id , j.job_title , e.salary 
    from employees as e , jobs as j 
    where e.job_id=j.job_id 
    and salary between 10000 and 20000
    order by salary desc; 
  30. 自连接

    -- 连接同一个表内的数据
    select e.employee_id , e.last_name , m.manager_id from employees as e , employees as m where e.employee_id=m.manager_id;

sql 99语法

sql 99语法
/*
语法:
            select 查询列表
            from  表1  别名 【连接类型】
            join  表2  别名 
            on 连接条件
            【where 筛选条件】
            【group by 分组】
            【having 筛选条件】
            【order by排序列表】

分类:
内连接:inner
外连接:
                左外:left outer 
                右外: right  outer 
                全外:full outer 
交叉连接:cross
*/
  1. 等值连接

    select last_name , department_name 
    from employees as e 
    inner join departments as d 
    on e.department_id=d.department_id;
    -- 添加筛选条件
    select last_name ,job_title 
    from employees as e 
    inner join jobs as d 
    on e.job_id=d.job_id
    where last_name like '%e%';
    -- having 字句和排序
    select department_name ,count(*)
    from departments as d 
    inner join employees as e 
    on d.department_id=e.department_id
    group by department_name
    having count(*) > 3 
    order by count(*) desc ;
    -- 三表连接
    select last_name, department_name, job_title
    from employees as e 
    inner join departments as d 
    on e.department_id=d.department_id
    inner join jobs as j 
    on e.job_id=j.job_id
    order by department_name desc ;
  2. 非等值连接

    SELECT salary ,grade_level 
    from employees as e 
    inner join job_grades as j 
    on e.salary between j.lowest_sal and j.highest_sal;
    -- 非等值连接加筛选
    select count(*),grade_level 
    from employees as e 
    inner join job_grades as j 
    on e.salary between j.lowest_sal and j.highest_sal
    group by grade_level
    having count(*) > 20 ; 
  3. 自连接

    select e.last_name as 员工名,e.employee_id as 员工ID , m.last_name as 领导名 ,m.employee_id as 领导编号
    from employees as e 
    inner join employees as m 
    on e.manager_id = m.employee_id;
  4. 左外连接

    select d.*,e.employee_id 
    from departments as d 
    left outer join employees as e 
    on d.department_id=e.department_id
    where e.employee_id is NULL;
  5. 右外连接

    select d.* , e.employee_id 
    from employees as e 
    right outer join departments as d 
    on e.department_id=d.department_id
    where e.employee_id is NULL ;

子查询

含义:出现在其他语句中的select语句,称为子查询或内查询

外部的查询语句,称为主查询或外查询

分类

/*
按子查询出现的位置:
            select 后面:
                    仅仅支持标量子查询
            from后面:
                    支持表子查询
            where或having后面:
                    标量子查询(单行)
                    列子查询(多行)
                    行子查询
            exists后面(相关子查询)
                    表子查询
按结果集的行列数不同:
            标量子查询(结果集只有一行一列)
            列子查询(结果集只有一列多行)
            行子查询(结果集有一行多列)
            表子查询(结果集一般为多行多列)
*/

一、where或having后面

/*
1.标量子查询(单行子查询)
2.列子查询(多行子查询)
3.行子查询(多列多行)
特点:
    1.子查询放在小括号内
    2.子查询一般放在条件的右侧
    3.标量子查询,一般搭配着单行操作符使用
    >  <  >= <= = <>
    列子查询,一般搭配着多行操作符使用
    in , any/some, all 
    4.子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
*/
  1. 标量子查询

    select min(salary),department_id 
    from employees 
    group by department_id 
    having min(salary) >  (
    select min(salary) 
    from employees 
    where department_id = 50 
    );
  2. 列子查询(多行子查询)

    select last_name 
    from employees 
    where department_id in (
        select department_id
        from departments
        where location_id IN (1400,1700)
    );
    -- any 关键字,只要是查询出来的子句中的任意一个值就可以
    select last_name,employee_id ,job_id ,salary 
    from employees 
    where salary < any (
    select DISTINCT salary 
    from employees 
    where job_id = 'IT_PROG'
    )
    and job_id<>'IT_PROG';
    -- all关键字,条件要满足all后面的所有字段才成立,类似于下面这条sql中,比所有的员工工资都低
    select employee_id , last_name,job_id,salary 
    from employees 
    where salary < all(
    select salary 
    from employees 
    where job_id='IT_PROG'
    );
  3. 行子查询(结果集一行多列或多行多列)

    -- 行子查询,必须使用等号连接子查询,并且子查询返回的数据是同一行数据
    select * 
    from employees 
    where (employee_id,salary)=(
    select min(employee_id),max(salary)
    from employees
    );

二、select 后面

  1. select场景

    -- select 后面仅仅支持标量子查询
    select d.* ,(
                select count(*)
                from employees as e 
                where e.department_id=d.department_id
                ) as 个数
    from departments as d ; 

三、from后面

  1. 场景一

    -- 在from 后面添加子查询,将子查询出来的数据作为查询表,必须要将子查询出来的数据取别名,如果子查询中有分组函数,分组函数字段也需要取别人
    select pjgz.*, j.grade_level
    from 
        (select avg(salary) as g ,department_id 
        from employees 
        group by department_id) as pjgz
        inner join job_grades as j 
    on pjgz.g
    between j.lowest_sal and j.highest_sal;

四、exists后面的子查询

  1. 语法

    exists(完整的查询语句)
    结果:
    1或0
  2. 示例

    -- 使用exists示例
    select department_name 
    from departments  as d 
    where exists(
    select * from 
    employees as e  
    where  d.department_id=e.department_id
    );
    select boyName 
    from boys as m
    where NOT exists (
    select boyfriend_id
    from beauty as b 
    where b.boyfriend_id = m.id
    );
    -- 使用in示例
    select department_name 
    from departments as d  
    where d.department_id in (
    select department_id 
    from employees
    );
    
    select m.* 
    from boys as m
    where m.id  not in (
    select boyfriend_id 
    from beauty as g 
    );

分页查询

/*
语法:
select 查询列表
from 表
【join type join 表2
on 连接条件
where 筛选条件
group by 分组字段
having 分组后的筛选
order by 排序的字段】
limit offset,size ; 
limit 放在SQL语句的最后,offset要显示条目的起始索引(起始索引从0开始),size要显示的条目个数
*/
select  * 
from employees 
limit 0,5;

select * 
from employees 
limit 10,15;

联合查询

联合查询
UNION联合 合并:将多条查询语句的结果合并成一个结果
语法:
查询语句1
UNION
查询语句2
UNION
...

应用场景:
需要查询多个表,多个表之间没有直接的关联关系

特点:
1.要求多条语句的查询列数一致
2.要求多条查询语句的查询的每一类的类型和顺序最好一致
3.union关键字默认去重,如果使用union all 可以包含重复项

DML语言

/*
数据操作语言:
插入: insert 
修改:update 
删除:delete
*/

一、插入语句

/*
语法:
insert into 表名(列名,...) values(值1,...); 
*/
-- 单行插入
insert into test VALUES(13,'李小龙',1000);
-- 多行插入
insert into test values(14,'杜康',100),(15,'铜雀',50);
-- 从select语句中获取值插入
insert into test select id,name,boyfriend_id from beauty where id > 7;

二、修改语句

/*
语法:
update 表名 set 列名=值 where 筛选条件;
*/

三、删除语句

/*
语法:
delete from 表名 where 筛选条件;
delete 删除的数据自增长列从断点数继续
*/
/*
语法:
truncate table 表名;
*/

DDL

/*
数据定义语言
库和表的管理
一、库的管理
创建、修改、删除
一、库的管理
1.库的创建
语法:
-- create database 库名;
-- create database if not exists 库名;
2.库的修改
RENAME DATABASE books to 新库名;
更改库的字符集
alter database books character set  utf8; 
3.库的删除
drop database 库名;
drop database if exists 库名;

二、表的管理
创建、修改、删除
创建:create

-- 1.表的创建
/*
create table  表名(
    列名 列的类型(长度) 约束,
    列名 列的类型(长度) 约束,
    列名 列的类型(长度) 约束
)
*/
create table if not exists book(
    id int,
    bname VARCHAR(20),
    price  double,
    authorId INT,
    publishDate datetime
);

修改:alter
/*
alter table 表名 add |  drop | modify | change column 列名 列类型 约束;
1.修改列名
alter table book change column publishdate pubDate DATETIME;
2.修改列的类型或约束
alter table book modify column pubDate timestamp; 
3.添加新列
alter table author add column annual double; 
4.删除列
alter table author drop column annual ; 
5.修改表名
alter table author rename to book_author ; 
*/
删除:drop
/*
表的删除
drop table book_author; 
drop table if exists book_author; 
*/

常见的数据类型

/*
数值型:
            整型
            小数:
                        定点数
                        浮点数
字符型:
            较短的文本:char、 varchar 
            较长的文本:text、 blob(较长的二进制数据)
日期型:        
*/

一、整型

-- 1字节TINYINT、2字节SMALLINT、 3字节MEDIUMINT、4字节int | integer、8字节bigint
/*
如何设置无符号和有符号
create table tab_int(
    t1 int 
)
1.如果不设置无符号还是有符号,默认是有符号,如果想设置无符号,需要添加unsigned关键字
2.如果插入的数值超出了整型的范围,会报out of range 异常,并且插入临界值
3.如果不设置长度,会有默认的长度
长度代表了显示的最大宽度,如果不够用会用0在左边填充,但必须搭配zerofill使用!
drop table if exists tab_int;
create table   if not exists tab_int(
    t1 int(7) zerofill,
    t2 int(8)  ZEROFILL
);
*/

二、小数

/*
分类:
1.浮点型
float(M,D)
double(M,D)
2.定点型
dec(M,D)
decimal(M,D)
特点:
1.
M :整数部位+小数部位
D :小数部位
如果超过范围,则插入临界值,mysql5.7直接报错值超过临界值无法插入
2.
M和D都可以省略
如果是decimal,则M默认为10,D默认为0
如果是float和double,则会根据插入的数值的精度来决定精度
3.定点型的精确度较高,如果要求插入数值的精度较高如货币运算等则考虑使用
*/

create table if not exists tab_float (
    t1 float(5,2),
    t2 double(5,2),
    t3 decimal(5,2)
);

insert into tab_float values(123.45,123.45,123.45);
select * from tab_float;
insert into tab_float values(1111.45,11111.45,1111.45);

三、字符型

/*
较短的文本;
CHAR
VARCHAR
较长的文本:
text
blob(较大的二进制)
*/
其他:
binary和varbinary用于保存较短的二进制
enum用于保存枚举
set用于保存集合
create table if not exists tab_char(
    c1 char,
    c2 varchar(200)
);
写法 M的意思 特点 空间的耗费 效率
char char(M) 最大的字符数,可以省略,默认为1 固定长度的字符 比较耗费
varchar varchar(M) 最大的字符数,不可以省略 可变长度的字符 比较节省

四、日期型

/*
分类:
date 只保存日期
time 只保存时间
year 只保存年
datetime 保存日期+时间
timestamp 保存日期+时间
*/
CREATE TABLE `tab_date` (
  `d1` datetime DEFAULT NULL,
  `d2` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

常见约束

/*
含义:一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性
分类:六大约束
            NOT NULL:非空,用于保证该字段的值不能为比如姓名、学号等
            DEFAULT:默认,用于保证该字段有默认值
            PRIMARY KEY:主键,用于保证该字段的值具有唯一性,并且非空
            UNIQUE:唯一,用于保证该字段的值具有唯一性,可以为空
            CHECK:检车约束
            FOREIGN KEY:外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值,在从表添加外键约束,用于引用主表中某列的值
约束的添加分类:
            列级约束:
                六大约束语法上都支持,但外键约束没有效果
            表级约束:
                除了非空、默认其他的都支持
*/
-- 主要需要记住主键、默认、唯一、非空四个约束
 CREATE TABLE `major` (
  `id` int(11) NOT NULL,
  `majorName` varchar(20) DEFAULT NULL
);

create table stuinfo (
    id int primary key, -- 主键
    stuName varchar(20) not null ,-- 非空
    gender char(1) check(gender='男' or gender='女'),-- 检查
    seat int unique ,-- 唯一
    age int default 18, -- 默认约束
    majorId int references major(id) -- 外键
);
show index from stuinfo ; 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!