SQL篇

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: SQL

SQL

MySQL内置功能

  1. 连接数据库

    • -u
    • -p
    • -S
    • -h
    • -P
    • -e
    • <

    示例:

    1. mysql -u root -p -S /tmp/mysql.sock
    2. mysql -u root -p -h 10.0.0.51 -P3306
    3. -e 免交互执行 sql 语句

      [root@db01 ~]# mysql -uroot -p -e "show databases;"

    4. < 导入数据

      [root@db01 ~]# mysql -uroot -p123 /root/world.sql

  2. 内置命令

    • help 帮助
    • \c ctrl+c 结束上个命令运行
    • \q quit exit ctrl+d 退出
    • \G 竖行显示
    • source 恢复备份文件

SQL 基础应用

  1. 介绍

    结构化的查询语言

    关系型数据库通用的命令

    遵循SQL92标准(SQL_MODE)

  2. 常用种类

    DDL 数据定义语言

    DCL 数据控制语言

    DML 数据操作语言

    DQL 数据查询语言

  3. 数据库的逻辑结构

      • 库名
      • 库属性(字符集,排序规则)
      • 表名
      • 表属性(存储引擎类型,字符集,排序规则)
      • 列名
      • 列属性(数据类型,约束,其他属性)
      • 数据行
  4. 字符集(charset)

    查看支持字符集 show charset

    • utf8 三个字符
    • utfmb4 四个字符(支持emoji)
  5. 排序规则(collation)

    查看排序规则 show collation

    英文字符串的大小写不敏感

    • utf8mb4_general_ci 大小写不敏感
    • utf8mb4_bin 大小写敏感(存拼音,日文)
  6. 数据类型

    • 数字:tinyint int
    • 字符串:

      • char(100)

        定长字符串类型,不管字符串长度多长,都立即分配100个字符长度的存储空间,未占满的空间使用"空格"填充

      • varchar(100)

        变长字符串类型,每次存储数据之前,都要先判断一下长度,按需分配此盘空间.

        会单独申请一个字符长度的空间存储字符长度(少于255,如果超过255以上,会占用两个存储空间)

      如何选择这两个数据类型?

      1. 少于255个字符串长度,定长的列值,选择char
      2. 多于255字符长度,变长的字符串,可以选择varchar
    • 枚举

      • address enum('sz','sh','bj'.....)

        可能会影响到索引的性能

    • 时间

      • datetime

        范围为从 1000-01-01 00:00:00.000000 至 9999-12-31 23:59:59.999999

      • timestamp

        范围为从 1970-01-01 00:00:00.000000 至 2038-01-19 03:14:07.999999

    • 二进制

DDL

  1. 库的定义

    • 创建数据库

      CREATE DATABASE zabbix CHARSET utf8mb4 COLLATE utf8mb4_bin;

    • 查看库情况

      SHOW DATABASES;

      SHOW CREATE DATABASE zabbix;

    • 删除数据库(不代表生产操作)

      DROP DATABASE oldguo;

    • 修改数据库字符集

      注意: 一定是从小往大了改,比如utf8--->utf8mb4.

      目标字符集一定是源字符集的严格超级.

      CREATE DATABASE oldguo;

      SHOW CREATE DATABASE oldguo;

      ALTER DATABASE oldguo CHARSET utf8mb4;

  2. 库定义规范

    • 库名使用小写字符
    • 库名不能以数字开头
    • 不能为数据库内部关键字
    • 必须设置字符集
  3. 表的定义

    • 建表

      表名, 列名, 列属性, 表属性

    • 列属性

      • PRIMARY KEY : 主键约束,表中只能有一个,非空且唯一.
      • NOT NULL : 非空约束,不允许空值
      • UNIQUE KEY : 唯一键约束,不允许重复值
      • DEFAULT : 一般配合 NOT NULL 一起使用.
      • UNSIGNED : 无符号,一般是配合数字列,非负数
      • COMMENT : 注释
      • AUTO_INCREMENT : 自增长的列

    示例:

    CREATE TABLE stu (
    id INT PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '学号',
    sname VARCHAR(255) NOT NULL  COMMENT '姓名',
    age TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '年龄',
    gender ENUM('m','f','n') NOT NULL DEFAULT 'n' COMMENT '性别',
    intime DATETIME NOT NULL DEFAULT NOW() COMMENT '入学时间'
    )ENGINE INNODB CHARSET utf8mb4;
    
  4. 建表规范

    1. 表名小写字母,不能数字开头
    2. 不能是保留字符,使用和业务有关的表名
    3. 选择合适的数据类型及长度
    4. 每个列设置 NOT NULL + DEFAULT ;对于数据0填充,对于字符使用有效字符串填充
    5. 每个列设置注释
    6. 表必须设置存储引擎和字符集
    7. 主键列尽量是无关列数字列,最好是自增长
    8. enum类型不要保存数字,只能是字符串类型
  5. 查询表信息

    SHOW TABLES;
    SHOW CREATE TABLE stu;
    DESC stu;

  6. 创建一个表结构一样的表

    CREATE TABLE test LIKE stu;

  7. 删表(不代表生产操作)

    DROP TABLE test;

  8. 修改

    • 在stu表中添加qq列

      DESC stu;
      ALTER TABLE stu ADD qq VARCHAR(20) NOT NULL COMMENT 'qq号';
    • 在sname后加微信列

      ALTER TABLE stu ADD wechat VARCHAR(64) NOT NULL UNIQUE COMMENT '微信号' AFTER sname;
    • 在id列前加一个新列num

      ALTER TABLE stu ADD num INT NOT NULL UNIQUE COMMENT '身份证' FIRST ;
      DESC  stu;
    • 把刚才添加的列都删掉(危险,不代表生产操作

      ALTER TABLE stu DROP num;
      DESC stu;
      ALTER TABLE stu DROP qq;
      ALTER TABLE stu DROP wechat;
    • 修改sname数据类型的属性

      DESC stu;
      ALTER TABLE stu MODIFY sname VARCHAR(64) NOT NULL COMMENT '姓名';
    • 将gender 改为 sex 数据类型改为 CHAR 类型

      ALTER TABLE stu  CHANGE gender sex CHAR(4) NOT NULL COMMENT '性别';

DCL

grant

revoke

DML

插入数据(insert)

  • 简单

    INSERT stu VALUES(1,'zs',18,'m',NOW());
    SELECT * FROM stu;
  • 规范

    NSERT INTO stu(id,sname,age,sex,intime)
    VALUES (2,'ls',19,'f',NOW());
  • 录入多行

    INSERT INTO stu(sname,age,sex)
    VALUES 
    ('aa',11,'m'),
    ('bb',12,'f'),
    ('cc',13,'m');
  • update (一定加where条件)

    UPDATE stu SET sname='aaa';
    SELECT * FROM stu;
    UPDATE stu SET sname='bb' WHERE id=6;
  • delete (一定要加where条件)

    DELETE FROM stu;
    DELETE FROM stu WHERE id=9;
  • 生产中屏蔽delete功能,使用update替代delete

    ALTER TABLE stu ADD is_del TINYINT DEFAULT 0 ;
    UPDATE stu SET is_del=1 WHERE id=7;
    SELECT * FROM stu WHERE is_del=0;

DQL

  1. DQL介绍

    • SELECT
    • SHOW
  2. SELECT 语句的应用

    1. SELECT单独使用的情况

      mysql> select @@basedir;
      mysql> select @@port;
      mysql> select @@innodb_flush_log_at_trx_commit;
      mysql> show variables like 'innodb%';
      mysql> select database();
      mysql> select now();

    2. SELECT通用语法表(单表)

      select 列
      from 表
      where 条件
      group by 条件
      having 条件
      order by 条件
      limit

    3. 学习环境说明

      • world 数据库

        • city 城市表
        • country 国家表
        • countrylanguage 语言表
      • city表结构

        • ID 城市序号
        • name 城市名代号
        • countrycode 国家
        • district 区域
        • population 人口
    4. SELECT 配合 FROM 子句使用

      SELECT 列 from 表

      示例:

      • 查询表中所有的信息(生产中几乎是没有这种需求的)

        USE world ;
        SELECT  id,NAME ,countrycode ,district,population   FROM  city;
        
        或者
        
        SELECT  *   FROM city;
      • 查询表中 name 和population的值

        SELECT  NAME ,population   FROM  city;
    5. SELECT 配合 WHERE 子句使用

      select 列 from 表 where 过滤条件

      示例:

      • 等值条件查询

        查询中国所有的城市名和人口数

        SELECT  NAME,population FROM city 
        WHERE countrycode='CHN';
      • 比较判断查询

        世界上小于100人的城市名和人口数

        SELECT NAME,population FROM city 
        WHERE population<100;
      • 逻辑连接符

        查询中国人口数量大于1000w的城市名和人口

        SELECT NAME,population FROM city 
        WHERE countrycode='CHN' AND population>8000000;
        

        查询中国或美国的城市名和人口数

        SELECT NAME,population FROM city 
        WHERE countrycode='CHN' OR countrycode='USA';
        

        查询人口数量在500w到600w之间的城市名和人口数

        SELECT NAME,population FROM city 
        WHERE population>5000000 AND population<6000000;
        
        或者
        
        SELECT NAME,population FROM city 
        WHERE population BETWEEN 5000000 AND 6000000;
      • 模糊查询

        查询一下contrycode中带有CH开头,城市信息

        SELECT * FROM city  
        WHERE countrycode  LIKE 'CH%';

        TIP:不要出现类似于 %CH%,前后都有百分号的语句,因为不走索引,性能极差。如果业务中有大量需求,我们用"ES"来替代。

      • in 语句

        查询中国或美国的城市信息

        SELECT NAME,population FROM city 
        WHERE countrycode='CHN' OR countrycode='USA';
        
        或者
        
        SELECT NAME,population FROM city 
        WHERE countrycode IN ('CHN' ,'USA');
    6. GROUP BY

      将某列中有共同条件的数据行,分成一组,然后在进行聚合函数操作

      统计每个国家,城市的个数

      SELECT  countrycode ,COUNT(id) FROM city
      GROUP BY countrycode;

      统计每个国家的总人口数.

      SELECT countrycode,SUM(population) FROM city 
      GROUP BY countrycode;

      统计每个 国家 省 的个数

      SELECT  countrycode,COUNT(DISTINCT district)     FROM city
      GROUP BY countrycode;

      统计中国 每个省的总人口数

      SELECT district, SUM(population)     FROM  city 
      WHERE countrycode='CHN'
      GROUP BY district ;

      统计中国 每个省城市的个数

      SELECT district, COUNT(NAME)     FROM  city 
      WHERE countrycode='CHN'
      GROUP BY distric

      统计中国 每个省城市的名字列表GROUP_CONCAT()

      SELECT district, GROUP_CONCAT(NAME)     FROM  city 
      WHERE countrycode='CHN'
      GROUP BY district ;

      anhui : hefei,huaian ....

      SELECT CONCAT(district,":" ,GROUP_CONCAT(NAME))     FROM  city 
      WHERE countrycode='CHN'
      GROUP BY district ;
    7. ORDER BY

      统计所有国家的总人口数量,将总人口数大于5000w的过滤出来,并且按照从大到小顺序排列

      SELECT countrycode,SUM(population) FROM city
      GROUP BY countrycode
      HAVING SUM(population)>50000000
      ORDER BY SUM(population) DESC ;
    8. LIMIT

      统计所有国家的总人口数量,将总人口数大于5000w的过滤出来,并且按照从大到小顺序排列,只显示前三名

      SELECT countrycode,SUM(population) FROM city
      GROUP BY countrycode
      HAVING SUM(population)>50000000
      ORDER BY SUM(population) DESC 
      LIMIT 3 OFFSET 0;

      LIMIT M,N :跳过M行,显示一共N行
      LIMIT Y OFFSET X: 跳过X行,显示一共Y行

    9. 小结

      select disctrict , count(name) from    city  
      where countrycode='CHN'
      group by  district 
      having  count(name) >10
      order by  count(name) desc 
      limit 3;
    10. union 和 union all

      多个结果集合并查询的功能

      查询中或者美国的城市信息

      SELECT * FROM city WHERE countrycode='CHN' OR countrycode='USA';

      改写

      SELECT * FROM city WHERE countrycode='CHN'
      UNION ALL 
      SELECT * FROM city WHERE countrycode='USA';

      union 和 union all 的区别 ?

      union all 不做去重复
      union 会做去重操作

    11. 练习题

      1. 统计中国每个省的总人口数,只打印总人口数小于100w的

        SELECT   district ,SUM(population)  FROM  city 
        WHERE countrycode='CHN'
        GROUP BY district
        HAVING SUM(population)<1000000;
      2. 查看中国所有的城市,并按人口数进行排序(从大到小)

        SELECT * FROM city WHERE countrycode='CHN' 
        ORDER BY population DESC;
      3. 统计中国各个省的总人口数量,按照总人口从大到小排序

        SELECT   district ,SUM(population)  FROM  city 
        WHERE countrycode='CHN'
        GROUP BY district
        ORDER BY SUM(population) DESC ;
      4. 统计中国,每个省的总人口,找出总人口大于500w的,并按总人口从大到小排序,只显示前三名

        SELECT   district ,SUM(population)  FROM  city 
        WHERE countrycode='CHN'
        GROUP BY district
        HAVING SUM(population)>5000000
        ORDER BY SUM(population) DESC 
        LIMIT 3;
  3. 多表连接查询(内连接)

    1. 作用

      单表数据不能满足查询需求时

      查询世界上小于100人的城市,所在的国家名,国土面积,城市名,人口数

      SELECT  countrycode,NAME,population FROM city WHERE population<100;
      PCN     Adamstown   42 
      
      SELECT NAME ,SurfaceArea FROM country WHERE CODE='PCN';
    2. 多表连接基本语法

      student :学生表
      ===============
      sno:    学号
      sname:学生姓名
      sage: 学生年龄
      ssex: 学生性别
      
      teacher :教师表
      ================
      tno:     教师编号
      tname:教师名字
      
      course :课程表
      ===============
      cno:  课程编号
      cname:课程名字
      tno:  教师编号
      
      score  :成绩表
      ==============
      sno:  学号
      cno:  课程编号
      score:成绩
    3. 多表连接例子

      1. 统计zhang3,学习了几门课

        SELECT student.sname,COUNT(sc.cno)
        FROM student JOIN sc
        ON student.sno=sc.sno
        WHERE student.sname='zhang3';
      2. 查询zhang3,学习的课程名称有哪些?

        SELECT student.sname,GROUP_CONCAT(course.cname)
        FROM student
        JOIN sc
        ON student.sno=sc.sno 
        JOIN course
        ON sc.cno=course.cno
        WHERE student.sname='zhang3'
        GROUP BY student.sname;
      3. 查询oldguo老师教的学生名和个数.

        SELECT teacher.tname,GROUP_CONCAT(student.sname),COUNT(student.sname)
        FROM teacher 
        JOIN course 
        ON teacher.tno=course.tno
        JOIN sc
        ON course.cno=sc.cno
        JOIN student
        ON sc.sno=student.sno
        WHERE teacher.tname='oldguo'
        GROUP BY teacher.tname;
      4. 查询oldguo所教课程的平均分数

        SELECT teacher.tname,AVG(sc.score)
        FROM teacher
        JOIN course
        ON teacher.tno=course.tno
        JOIN sc
        ON course.cno=sc.cno
        WHERE teacher.tname='oldguo'
        GROUP BY sc.cno;
      5. 每位老师所教课程的平均分,并按平均分排序

        SELECT teacher.tname,course.cname,AVG(sc.score)
        FROM teacher 
        JOIN course
        ON teacher.tno=course.tno
        JOIN sc
        ON course.cno=sc.cno 
        GROUP BY teacher.tname,course.cname
        ORDER BY AVG(sc.score)
      6. 查询oldguo所教的不及格的学生姓名

        SELECT teacher.tname,student.sname,sc.score
        FROM teacher
        JOIN course
        ON teacher.tno=course.tno
        JOIN sc
        ON course.cno=sc.cno
        JOIN student
        ON sc.sno=student.sno
        WHERE teacher.tname='oldguo' AND sc.score<60
      7. 查询所有老师所教学生不及格的信息(扩展)

        SELECT teacher.tname,GROUP_CONCAT(CONCAT(student.sname,":",sc.score)) 
        FROM teacher
        JOIN course
        ON teacher.tno=course.tno
        JOIN sc
        ON course.cno=sc.cno
        JOIN student
        ON sc.sno=student.sno
        WHERE sc.score<60
        GROUP BY teacher.tno
      8. 别名应用

        表别名 (全局调用)

        SELECT t.tname,GROUP_CONCAT(CONCAT(st.sname,":",sc.score)) 
        FROM teacher as t
        JOIN course as c
        ON t.tno=c.tno
        JOIN sc 
        ON c.cno=sc.cno
        JOIN student as st
        ON sc.sno=st.sno
        WHERE sc.score<60
        GROUP BY t.tno

        列别名(having 和 order by 调用)

        SELECT t.tname as 讲师名 ,GROUP_CONCAT(CONCAT(st.sname,":",sc.score))  as 不及格的 
        FROM teacher as t
        JOIN course as c
        ON t.tno=c.tno
        JOIN sc 
        ON c.cno=sc.cno
        JOIN student as st
        ON sc.sno=st.sno
        WHERE sc.score<60
  4. 扩展类内容-元数据获取

    1. 元数据介绍及获取

      元数据是存储在"基表"中。

      通过专用的DDL语句,DCL语句进行修改

      通过专用视图和命令进行元数据的查询

      information_schema中保存了大量元数据查询的试图

      show 命令是封装好功能,提供元数据查询基础功能

    2. information_schema的基本应用

      tables 视图的应用

      use information_schema;
      mysql> desc tables;

      TABLE_SCHEMA 表所在的库名
      TABLE_NAME 表名
      ENGINE 存储引擎
      TABLE_ROWS 数据行
      AVG_ROW_LENGTH 平均行长度
      INDEX_LENGTH 索引长度

    3. 示例

      USE information_schema;
      DESC TABLES;
      • 显示所有的库和表的信息

        SELECT table_schema,table_name FROM information_schema.tables;
      • 以以下模式 显示所有的库和表的信息

        world city,country,countrylanguage

        SELECT table_schema,GROUP_CONCAT(table_name) 
        FROM information_schema.tables
        GROUP BY table_schema;
      • 查询所有innodb引擎的表

        SELECT table_schema,table_name ,ENGINE
        FROM information_schema.tables 
        WHERE ENGINE='innodb';
      • 统计world下的city表占用空间大小

        表的数据量=平均行长度*行数+索引长度

        AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH
        SELECT table_name,(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024
        FROM information_schema.TABLES
        WHERE table_schema='world' AND table_name='city';
      • 统计world库数据量总大小

        SELECT table_schema,SUM((AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH))/1024
        FROM information_schema.TABLES
        WHERE table_schema='world';
      • 统计每个库的数据量大小,并按数据量从大到小排序

        SELECT table_schema,SUM((AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH))/1024 AS total_KB
        FROM information_schema.TABLES
        GROUP BY table_schema
        ORDER BY total_KB DESC ;
    4. 配合concat()函数拼接语句或命令

      示例:

      • 模仿以下语句,进行数据库的分库分表备份。

        mysqldump -uroot -p123 world city >/bak/world_city.sql

        SELECT
        CONCAT("mysqldump -uroot -p123 ",table_schema," ",table_name
        ," >/bak/",table_schema,"_",table_name,".sql")
        FROM information_schema.tables;
      • 模仿以下语句,进行批量生成对world库下所有表进行操作

        ALTER TABLE world.city DISCARD TABLESPACE;

        SELECT 
        CONCAT("ALTER TABLE ",table_schema,".",table_name," DISCARD TABLESPACE;")
        FROM information_schema.tables
        WHERE table_schema='world';
    5. show介绍

      show databases; 查看数据库名
      show tables; 查看表名
      show create database xx; 查看建库语句
      show create table xx; 查看建表语句
      show processlist; 查看所有用户连接情况
      show charset; 查看支持的字符集
      show collation; 查看所有支持的校对规则
      show grants for xx; 查看用户的权限信息
      show variables like '%xx%' 查看参数信息
      show engines; 查看所有支持的存储引擎类型
      show index from xxx 查看表的索引信息
      show engine innodb status\G 查看innoDB引擎详细状态信息
      show binary logs 查看二进制日志的列表信息
      show binlog events in '' 查看二进制日志的事件信息
      show master status ; 查看mysql当前使用二进制日志信息
      show slave status\G 查看从库状态信息
      show relaylog events in '' 查看中继日志的事件信息
      show status like '' 查看数据库整体状态信息

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5月前
|
SQL Java 数据库连接
SQL中为什么不要使用1=1
本文探讨了在SQL查询中使用`1=1`的现象及其背后的原因与问题。开发人员有时使用`1=1`作为始终为真的条件来方便动态构建SQL语句,但这样做可能会带来性能问题,尽管现代数据库查询优化器可能能优化掉这种条件,但在复杂查询或特定系统中仍可能影响效率。此外,`1=1`还降低了代码的可读性和跨数据库的兼容性。建议使用更佳实践,如MyBatis的动态SQL标签或Entity Framework的函数式查询,以避免不必要的条件。代码质量的重要性在于每一行代码都应有其明确的目的,避免浪费计算资源。
|
6月前
|
SQL 数据库 索引
SQL常用知识
SQL常用知识
|
SQL 数据挖掘 Python
sql8&10&11&12,3+1
sql8&10&11&12,3+1
111 0
sql8&10&11&12,3+1
|
SQL
sql last
sql last
62 0
|
关系型数据库
|
SQL 程序员 数据库
SQL已经48年了,为何依然使用广泛?
对于复杂的数据,SQL能找到最有效的办法来完成任务。
2986 0
|
SQL
SQL|你用过NOT BETWEEN吗?
image.png 如需显示不在上面实例范围内的网站,请使用 NOT BETWEEN: SELECT * FROM Websites WHERE alexa NOT BETWEEN 1 AND 20; 结果 image.png BETWEEN 操作符 选取介于两个值之间的数据范围内的值。
989 0
|
存储 安全 算法