[数据库SQL实战] 基本语法记录

本文是个人在练习数据库相关习题所使用的SQL关键字函数简单使用样例,用以备忘。
本文内容主要是再加工,对大部分SQL关键字和函数都演示了简单的测试使用样例
通过举例的方式,粗略地介绍了其基本使用方法。


DATABASES 数据库

创建 CREATE

创建数据库

-- 如果不存在test数据库,就创建字符集为utf8的test数据库
CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8;

查看 SHOW/USE

查看数据库信息

-- 显示数据库列表
SHOW DATABASES;
-- 显示创建数据库信息 (\G表示竖着打印)
SHOW CREATE DATABASE test\G;

切换数据库(环境)

-- 切换到test数据库
USE test
-- 注1:分号可加可不加
-- 注2:可以直接切换,不管当前环境

查看数据库的数据表列表

-- 通过information_schema.TABLES获得所有数据库的表名,指定获取哪个数据库的表名
SELECT table_name 
FROM information_schema.TABLES 
WHERE TABLE_SCHEMA='employees';

-- 显示当前环境下数据表列表
SHOW TABLES;
-- 可以显示直接指定环境下表格列表
SHOW TABLES FROM DATABASES;

MySQL 中的 information_schema 数据库

删除 DROP

删除数据库

-- 删除数据库test
DROP DATABASES test;

TABLE 数据表 (重点)

创建 CREATE

创建数据表

-- 正常创建数据表
-- 学生表students 
CREATE TABLE IF NOT EXISTS students (
    stu_no char(10) NOT NULL,
    name varchar(10) NOT NULL,
    gender int(11) NOT NULL,
    PRIMARY KEY (stu_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- 复制已有表的结构建立新表
-- stu_test表与students表结构一样(主键和外键都有) 但是个空表
CREATE TABLE IF NOT EXISTS stu_test LIKE students;

-- 基于已有表的数据建立新表
-- stu_test2表与students表结构类似(字段和类型都一样,但主键和外键没有)
CREATE TABLE IF NOT EXISTS stu_test2 AS SELECT * FROM students;

查看 SHOW/DESC/SELECT

查看数据表信息

-- 显示创建数据表信息 (\G表示竖着打印)
SHOW CREATE TABLE students\G;

-- 显示数据表字段定义信息
DESC students;
-- 等同于
SHOW COLUMNS FROM students;

查看表格数据

-- 显示students表格所有数据
SELECT * FROM students;

修改 INSERT INTO/REPLACE/UPDATE/RENAME/ALTER

插入数据到表格

-- 正常插入数据到表格
INSERT INTO students(stu_no, name, gender, class_no) 
VALUES("10001", "张三", 1, "201603"), 
("10002", "王喜", 0, "201604");
-- 注意:如果某列关联了外键,那对应的外键必须有相应内容,否则会报以下错误
-- ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`students`, CONSTRAINT `students_ibfk_1` FOREIGN KEY (`class_no`) REFERENCES `classes` (`class_no`))
INSERT INTO classes(class_no, number)  
VALUES("201603", 46), ("201604", 44);

-- 直接从已有数据表插入数据到新表
-- 将students表stu_no大于10000的数据插入stu_test表
INSERT INTO stu_test AS SELECT * FROM students WHERE stu_no > 10000;

更新数据到表格

-- 更新stu_test表stu_no字段的值 将该字段的值+2(字符也适用)
UPDATE stu_test SET stu_no = stu_no + 2;

-- 将表students中stu_no='10002'的class_no改为'201605'
-- 使用REPLACE关键字更新数据 
REPLACE INTO students(stu_no, name, gender, class_no) VALUES('10002', '王喜', 0, '201605');
-- 使用REPLACE函数更新数据 直接选择字段更新
UPDATE students SET class_no=REPLACE(class_no, '201604', '201605') WHERE stu_no='10002';
-- 直接使用UPDATE关键字
UPDATE students SET class_no='201605' WHERE stu_no='10002';

更改数据表名称

-- 将表stu_test2改成stu_test3
RENAME stu_test2 TO stu_test3;
-- 以上语句,等同于
ALTER TABLE stu_test2 RENAME stu_test3;

删除 DROP/DELETE

删除表格数据

-- 删除表格数据
-- 清空students表数据
DELETE FROM students;

删除表格

-- 删除数据表students
DROP TABLES students;

关键字

ORDER BY [AES/DESC] 排序

-- 先进行逆序排序,然后只输出第一个 
-- 对hire_date字段排序降序,此时最晚的时间排在第一个,再用LIMIT取出
SELECT * FROM employees ORDER BY hire_date DESC LIMIT 1;

LIMIT m,n 限制输出

-- 入职时间hire_date 排名倒数order by ? desc 第三limit 2,1
SELECT * FROM employees ORDER BY hire_date DESC LIMIT 2,1;

DISTINCT 去重

-- 给入职时间排名(去重)
select distinct hire_date from employees order by hire_date desc;

GROUP BY ... HAVING 分组

-- 计数使用count 通过group by对每个员工编号分组 通过having进行条件筛选
SELECT emp_no, COUNT(emp_no) AS t FROM salaries GROUP BY emp_no HAVING t > 15;

LIKE 含有某字符串的信息

-- 找出描述信息description包含'robot'的电影分类 
SELECT f.category_id, f.description
FROM film AS f 
WHERE f.description LIKE '%robot%';

IN/NOT IN (不)从中选取

-- 从manager表中选出所有manager员工emp_no, 再从员工表反选
SELECT emp_no FROM employees WHERE emp_no NOT IN (SELECT emp_no FROM dept_manager);

EXISTS/NOT EXISTS (不)存在条件成立的值

-- exists()就类似一个函数 
-- 输入de.emp_no 输出是否存在'e.emp_no=de.emp_no'等式成立 返回T/F
SELECT *
FROM employees AS e
WHERE NOT EXISTS (
	SELECT * 
    FROM dept_emp AS de 
    WHERE e.emp_no=de.emp_no
);
  • 用 NOT EXISTS 关键字的方法如下:
    意在 employees 中挑选出令(SELECT * FROM dept_emp WHERE emp_no = employees.emp_no)不成立的记录

EXISTS对外表用loop逐条查询,每次查询都会查看EXISTS的条件语句,
当 EXISTS里的条件语句能够返回记录行时(无论记录行是的多少,只要能返回),条件就为真,返回当前loop到的这条记录;
反之如果EXISTS里的条 件语句不能返回记录行,则当前loop到的这条记录被丢弃,
EXISTS的条件就像一个bool条件,当能返回结果集则为true,不能返回结果集则为false。


VIEW 视图

创建 CREATE

建立视图

-- 创建视图stu_view 有字段name和sc(学号stu_no和班号class_no的组合)
CREATE VIEW stu_view AS SELECT name, CONCAT(stu_no, ' ', class_no) AS sc FROM students;

查看 SHOW/SELECT

-- 显示创建视图信息 (\G表示竖着打印)
SHOW CREATE VIEW stu_view \G;

-- 同数据表一样
-- 显示视图字段定义信息
DESC stu_view;
-- 等同于
SHOW COLUMNS FROM stu_view;

-- 查看视图内容
SELECT * FROM stu_view;

删除 DROP/DELETE

删除视图数据

-- 删除视图stu_view 字段sc = '10001 201603'的数据
DELETE FROM stu_view WHERE sc = '10001 201603';

删除视图

DROP VIEW stu_view;

INDEX 索引

创建 CREATE/ALTER

建立索引

-- 给students表的stu_no字段创建索引
CREATE INDEX idx_stu_no ON students(stu_no);
-- 给students表的name字段其中5个字节创建索引
CREATE INDEX idx_name ON students (name(5));

-- 给students表的stu_no字段添加索引
ALTER TABLE students ADD INDEX(stu_no);

查看 SHOW/FORCE INDEX

查看表格索引

-- 显示students表的索引列表(主键索引、外键索引、唯一索引、所添加的索引)
SHOW INDEX FROM students;

强制使用索引

-- 在查询students表stu_no字段大于"10001"的数据时,强制其使用所建立的索引
SELECT stu_no, name FROM students FORCE INDEX(idx_stu_no) WHERE stu_no > "10001";
  • 实例
-- MySQL中,使用 FORCE INDEX 函数进行强制索引查询
EXPLAIN SELECT * FROM salaries FORCE INDEX(idx_emp_no) WHERE emp_no=10005;
SELECT * FROM salaries WHERE emp_no=10005; -- 4ms (+5ms)
SELECT * FROM salaries FORCE INDEX(idx_emp_no) WHERE emp_no=10005; -- 2ms (+1ms)

MySQL force Index 强制索引概述
Mysql中的force index和ignore index

删除 DROP/ALTER

删除索引

-- 删除students表的idx_name索引
DROP INDEX idx_name ON students;

-- 删除students表的idx_name索引
ALTER TABLE students DROP INDEX idx_name;

TRIGGER 触发器

创建 CREATE

建立触发器

-- 创建触发器'stu_sync' 
-- 当students表插入数据后,将指定数据插入stu_test表内
DELIMITER $$
CREATE TRIGGER stu_sync 
AFTER INSERT ON students FOR EACH ROW  
BEGIN      
    INSERT INTO stu_test VALUES(NEW.stu_no, NEW.name, NEW.gender, NEW.class_no); 
END$$
DELIMITER ;

MySQL官方文档:触发器实例

查看 SHOW/SELECT

显示所创建的触发器

-- 显示创建触发器的信息 (\G表示竖着打印)
SHOW CREATE TRIGGER stu_sync\G;

-- 所有创建的触发器都存放在INFORMATION_SCHEMA数据库的TRIGGERS表格
SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='stu_sync';

-- 显示本环境(数据库)下的触发器
SHOW TRIGGERS;

删除 DROP

删除触发器

-- 删除触发器stu_sync
DROP TRIGGER stu_sync;

COLUMNS 字段(列)

查看 SHOW

显示表格字段

-- 显示数据表students的索引字段信息
SHOW COLUMNS FROM students;

添加 ALTER ... ADD

添加字段/主键/外键

-- 给students表添加字段class_no
ALTER TABLE students ADD class_no varchar(10) NOT NULL;
-- 添加多个字段
ALTER TABLE students ADD a INT,ADD b INT,ADD c INT;

-- 给classes表添加主键class_no
ALTER TABLE classes ADD PRIMARY KEY(class_no);

-- 给students表添加外键class_no 关联classes表
ALTER TABLE students ADD FOREIGN KEY (class_no) REFERENCES classes(class_no);
-- 注意:如果关联表没有主键,或所管理列不是主键,会出现以下报错。
-- ERROR 1215 (HY000): Cannot add foreign key constraint

查看 SELECT

查看表格的所有外键

-- 查看数据库test的students表所有字段所关联的外键
SELECT TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, 
    REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE CONSTRAINT_SCHEMA ='test' AND
REFERENCED_TABLE_NAME = 'students';
-- 特别在想要删除该表,但因为其他表关联它作为外键而无法删除的时候
-- Cannot delete or update a parent row: a foreign key constraint fails

修改 ALTER ... MODIFY/CHANGE

修改字段/主键/外键

-- 给students表的字段修改类型
ALTER TABLE students MODIFY b tinyint NOT NULL DEFAULT 1;
ALTER TABLE students MODIFY a varchar(10);

-- 给students表已经填入数据的字段 缩小数据类型
ALTER TABLE students MODIFY stu_no char(6);

-- 给students表的字段修改名称和类型
ALTER TABLE students CHANGE b c CHAR(20);

删除 ALTER ... DROP

删除字段/主键/外键

-- 删除字段c
ALTER TABLE students DROP COLUMN c;

-- 给students表删除外键'students_ibfk_1'
ALTER TABLE students DROP FOREIGN KEY students_ibfk_1;

FUNCTION 函数

常用函数

EXPLAIN 查看执行计划

-- 执行计划 EXPLAIN
EXPLAIN SELECT * FROM employees;
  • EXPLAIN 介绍

EXPLAIN是一个执行SQL语句的模拟优化器,可以通过EXPALIN来查看增删查改操作的执行计划,即MySQL是如何处理sql语句,分析查询语句或者表结构的性能。
作用 通过查看EXPALIN结果,可以知道
1、表的读取顺序
2、数据读取操作的操作类型
3、哪些索引可以使用
4、哪些索引被实际使用
5、表之间的引用
6、每张表有多少行被优化器查询

CONCAT/CONCAT_WS/GROUP_CONCAT 字符串拼接函数

-- 取巧 直接手动加空格作为分隔符 
SELECT CONCAT(last_name, ' ' ,first_name) AS Name 
FROM employees;

-- 使用CONCAT_WS()函数  
SELECT CONCAT_WS(' ', last_name, first_name) AS Name
FROM employees;

-- GROUP_CONCAT()函数的基本使用
SELECT dept_no, group_concat(emp_no) AS employees
FROM dept_emp
GROUP BY dept_no
  • CONCAT()函数用法 简述

CONCAT(str1,str2,…)
返回结果为连接参数产生的字符串。如有任何一个参数为NULL,则返回值为NULL。
CONCAT_WS(separator,str1,str2,...)
CONCAT()的特殊形式。第一个参数是其它参数的分隔符。分隔符的位置放在要连接的两个字符串之间。
分隔符可以是一个字符串,也可以是其它参数。

mysql多个字段拼接
concat、concat_ws、group_concat函数用法

CURRENT_TIMESTAMP 获取时间

  • MySQL 获取当前时间函数:

current_timestamp() localtime() localtimestamp() sysdate()

  • MySQL 获取当前日期:

curdate() = current_date()

SUBSTR/RIGHT/LENGTH 字符串切割相关函数

  • RIGHT(s,n)

返回字符串 s 的后 n 个字符

  • SUBSTR(s,start,len)

从字符串 s 的 start 位置截取长度为 len 的子字符串

  • LENGTH(s)/CHAR_LENGTH(s)

返回字符串 s 的字符数

MySQL 函数

创建函数

样例

-- 创建一个输入字符串s 返回'Hello, $s!'
CREATE FUNCTION `hello`(s CHAR(20)) RETURNS char(50) 
RETURN CONCAT('Hello, ', s, '!')

-- 查看函数信息
SHOW CREATE FUNCTION hello\G;

-- 使用函数hello
SELECT hello('world') AS `result`;

MySQL官方文档:创建函数

  • 实例:leetcode 数据库 176、第二高的薪水
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
    -- 在limit中参数不可以有运算。如果想要运算,则需要用set语句定义好变量
    SET N = N - 1;
    RETURN (
        SELECT IFNULL((
            SELECT DISTINCT Salary
            FROM Employee
            ORDER BY Salary DESC
            LIMIT N,1), null
        ) AS getNthHighestSalary
    );
END
posted @ 2019-07-28 00:54  slowbird  阅读(286)  评论(0编辑  收藏  举报