CREATE
,DROP
,ALTER
等。INSERT
,DELETE
,UPDATE
,SELECT
等。GRANT
,REVOKE
,COMMIT
,ROLLBACK
,SAVEPOINT
等。基本使用
SELECT id,name,email FROM employees;
# *号代表全部字段 SELECT * FROM employees;
列的别名
# AS : Alias的缩写 # 可以使用一对双引号给字段起别名 # 当使用双引号时,调用别名时也需要加上双引号 SELECT id employee_id,name AS employee_name,email "employee_email" FROM employees;
去除重复行
# 去除表中id重复的数据 # 通常只针对一个字段进行操作 SELECT DISTINCT id FROM employees;
空值问题
# 空值表示没有赋值,null # 空值参与运算:结果也为null SELECT id,commission_pct,salary,salary * (1 + commission_pct) AS "salary_sum" FROM employees; # 应该写成 SELECT id,commission_pct,salary,salary * (1 + IFNULL(commission_pct,0)) AS "salary_sum" FROM employees;
显示表结构
DESC employees; DESCRIBE employees;
不能在过滤条件中使用别名
where
# 查询id=100的员工 SELECT id,name,email FROM employees WHERE id = 100;
between … and …
# 查询id在 [0,100] 的员工 SELECT id,name,email FROM employees WHERE id BETWEEN 0 AND 100;
in(set)
# 查询id是10,20,30的员工 SELECT id,name,email FROM employees WHERE id IN (10,20,30);
like
# 查询姓名中包含字符'a'的员工 # '%'表示0个,1个或多个字符 SELECT id,name,email FROM employees WHERE name LIKE '%a%'; # 查询姓名中包含字符'a'和'e'的员工 SELECT id,name,email FROM employees WHERE name LIKE '%a%' AND name LIKE '%e%'; # 查询姓名中第二个字符为'a'的员工 # '_'表示一个字符 SELECT id,name,email FROM employees WHERE name LIKE '_a%'; # 查询姓名中第二个字符为'_',第三个字符为'a'的员工 # '\'表示转义字符 SELECT id,name,email FROM employees WHERE name LIKE '_\_a%';
is null
# 查询id为null的员工 SELECT id,name,email FROM employees WHERE id IS NULL; # 查询id为不为null的员工 SELECT id,name,email FROM employees WHERE id IS NOT NULL;
升序降序
# 按照员工的工资从高到低排序 # DESC-降序,ASC-升序 SELECT id,salary FROM employees ORDER BY salary DESC; SELECT id,salary FROM employees WHERE salary > 1000 ORDER BY salary DESC;
二级排序
# 先按照工资降序排列,再按照姓名升序排列 SELECT id,name,salary FROM employees ORDER BY salary DESC,name ASC;
# 每页显示20条记录,先显示第1页 SELECT id,name FROM employees LIMIT 0,20; # 显示第2页 SELECT id,name FROM employees LIMIT 20,20; # (pageNo - 1) * pageSize,pageSize # 查询工资最高的10名员工 SELECT id,salary FROM employees ORDER BY salary DESC LIMIT 0,20;
分类:
# 笛卡尔积错误 # 每一个员工都和每一个部门匹配 SELECT id,name,department_name FROM employees,departments; # 正确写法 # 如果查询的字段在多个表中出现,则一定要指明来自于哪个表 # 可以使用表的别名 SELECT e.id,e.name,d.department_name FROM employees e,departments d WHERE e.`department_id` = d.`department_id`;
# 不等值连接 # 根据员工的工资划分等级 SELECT employee_id,salary,grade_level FROM employee e,job_grade j WHERE e.`salary` BETWEEN j.`lowest_level` AND j.`highest_level`;
# 自连接 # 查询员工的id,name和其管理者的id,name SELECT emp.id,emp.name,mgr.id,mgr.name FROM employees emp,employees mgr WHERE emp.`manager_id` = mgr.`employee_id`
# 外连接 # 员工表中有一个员工没有部门,查询出来的数据少一条,这就是内连接 # 使用外连接,需要使用sql-99的相关结构 # 左外连接 SELECT e.id,e.name,d.department_name FROM employees e LEFT OUTER JOIN departments d ON e.`department_id` = d.`department_id`; # 右外连接 # RIGHT OUTER JOIN # 满外连接,但是MySQL不支持 # FULL JOIN # 左外连接去重 + 右外连接 使用UNION ALL(UNION会去重,效率低) SELECT e.id,e.name,d.department_name FROM employees e LEFT OUTER JOIN departments d ON e.`department_id` = d.`department_id` WHERE d.`department_id` IS NULL UNION ALL SELECT e.id,e.name,d.department_name FROM employees e RIGHT OUTER JOIN departments d ON e.`department_id` = d.`department_id`;
函数:
//连接str1,str2...为一个字符串 CONCAT(str1,str2...) //同CONCAT函数,但是每个字符之间要加上s CONCAT_WS(s,str1,str2...) //字符长度 CHAR_LENGTH(s) //字符长度,和字符集有关(utf-8中,每个汉字占三个字节) LENGTH(s) //将字符串str从第index个开始,len长度换成instr //sql中索引从1开始 INSERT(str,index,len,instr) //转换大小写 UPPER(s) LOWER(s) //返回字符串最左(右)边n个字符 LEFT(s,n) RIGHT(s,n) //左边补齐,用字符串pad填充,直到长度为len LPAD(str,len,pad) //右边补齐 RPAD(str,len,pad) //去空格 LTRIM(s) RTRIM(s) TRIM(s) //去字符 TRIM(s1 FROM s)//开头和结尾 TRIM(LEADING s1 FROM s)//开头 TRIM(TRAILING s1 FROM s)//结尾 //返回str重复n次 REPEAT(str,n) //用字符串b替换字符串str中出现的字符串a PEPLACE(str,a,b) //比较大小 STRCMP(s1,s2) //返回从字符串s的index位置长度为len的字符 SUBSTRING(s,index,len)
//绝对值 ABS() //大于x的最小整数 CEIL(x) //小于x的最大整数 FLOOR(x) //返回x/y模,符号和被模数一致 MOD(x,y) //随机值 RAND() //四舍五入,返回参数x的四舍五入的y位小数的值 ROUND(x,y) //返回数字x截断为y位小数的结果 TRUNCATE(x,y) //平方根 SQRT(x) //x的y次方 POW(x,y)
//返回当前日期 CURDATE() //返回当前时间 CURTIME() //返回当前日期时间 NOW() //返回具体的时间值 YEAR(date) MONTH(date) DAY(date) HOUR(time) MINUTE(time) SECOND(time) //一年中的第几周 WEEKOFYEAR(date) //第几周,周日是1 DAYOFWEEK(date) //第几周,周日是0 WEEKDAY(date) //返回星期名:MONDAY,TUESDAY... DAYNAME(date) //格式化 DATE_FORMAT(datetime,fmt) //解析 STR_TO_DATE(str,fmt)
SELECT DATE_FORMAT(NOW(),'%Y/%m/%d %H:%i:%s') FROM DUAL; SELECT STR_TO_DATE('2021/03/03 09:34:34','%Y/%m/%d %H:%i:%s') FROM DUAL;
if
SELECT id,name,salary, IF(salary > 1000,'高工资','低工资') AS salary_details, IF(commission_pct IS NOT NULL,commission_pct,0) AS commission_details FROM employees;
ifnull
SELECT id,name,salary, IF(salary > 1000,'高工资','低工资') AS salary_details, IFNULL(commission_pct,0) AS commission_details FROM employees;
case when … then … when … then … (else) … end
SELECT id,name,salary,CASE WHEN salary > 10000 THEN '第一等级' WHEN salary > 5000 THEN '第二等级' WHEN salary > 1000 THEN '第三等级' ELSE '底层' END AS details FROM employees;
case … when … then … when … then … else … end
SELECT id,name,salary,CASE name WHEN 'tom' THEN '帅哥' WHEN 'jerry' THEN '还行' END AS details FROM employees;
//返回当前数据库名 database() //返回数据库版本 version() //返回当前登陆的用户名 user() //返回字符串str的加密版本,41位长的字符串 password(str) //返回字符串str的md5值 md5(str)
avg() / sum()
# 只适用于数值类型的字段 SELECT AVG(salary),SUM(salary) FROM employees;
min() / max()
# 适用于数值类型,字符串类型,日期时间的字段 SELECT MIN(salary),MAX(salary),MIN(name),MAX(hire_date) FROM employees;
count()
# 适用于数值类型,字符串类型,日期时间的字段 # 计算个数时,null值不考虑在内,比如commission_pct字段 SELECT COUNT(salary),COUNT(name),COUNT(commission_pct) FROM employees; # 可以使用COUNT(1),COUNT(2),COUNT(*) # 表示遍历时取的值是1或2或*,只要非空就加1,直到遍历完整张表
avg = sum / count
avg 和 sum 在运算的时候,null值都不参与运算
group by
# 查询公司的平均工资 SELECT AVG(salary) FROM employees; # 查询各部门的平均工资 SELECT department_id,AVG(salary) FROM employees GROUP BY department_id; #查询各部门的各工种的平均工资 SELECT department_id,job_id,AVG(salary) FROM employees GROUP BY department_id,job_id;
having
# 如果过滤条件出现了组函数,则需要使用having替换where实现过滤 # 如果过滤条件中没有组函数,推荐放在where中,因为效率高 SELECT department_id,MAX(salary) FROM employees WHERE department_id IN (10,20,30) GROUP BY department_id HAVING MAX(salary) > 10000
FROM <left_table> ON <join_condition> <join_type> JOIN <right_table> WHERE <where_condition> GROUP BY <group_by_list> HAVING <having_condition> SELECT DISTINCT <select_list> ORDER BY <order_by_condition> LIMIT <limit_number>
# 问题:谁的工资比Allen高 # 自连接 SELECT e1.name,e1.salary FROM employees e1 JOIN employees e2 ON e1.`salary` > e2.`salary` WHERE e2.name = 'Allen'; # 子查询 SELECT name,salary FROM employees WHERE salary >( SELECT salary FROM employees WHERE name = 'Allen' );
# 练习:返回job_id与140号员工相同,salary比141号员工多的员工的name,job_id,salary SELECT name,job_id,salary FROM employees WHERE job_id = ( SELECT job_id FROM employees WHERE id = 140 ); AND salary > ( SELECT salary FROM employees WHERE id = 141 );
in:等于列表中的任意一个
SELECT id,name FROM employees WHERE salary in ( SELECT MIN (salary) FROM employees GROUP BY department_id );
any:和子查询返回的某一个值比较
# 返回其他job_id中比job_id等于'IT_PROG'部门任一工资低的员工id,name,job_id以及salary SELECT id,name,job_id,salary FROM employees WHERE job_id <> 'IT_PROG' AND salary < ANY ( SELECT salary FROM employees WHERE job_id = 'IT_PROG' );
all:和子查询返回的所有值比较
# 返回其他job_id中比job_id等于'IT_PROG'部门的所有工资都低的员工id,name,job_id以及salary SELECT id,name,job_id,salary FROM employees WHERE job_id <> 'IT_PROG' AND salary < ALL ( SELECT salary FROM employees WHERE job_id = 'IT_PROG' );
# 不相关子查询 # 查询员工中工资大于公司平均公司的员工的name,salary和department_id SELECT name,salary,department_id FROM employees WHERE salary > ( SELECT AVG(salary) FROM employees ); # 相关子查询 # 查询员工中工资大于本部门平均公司的员工的name,salary和department_id SELECT name,salary,department_id FROM employees e1 WHERE salary > ( SELECT AVG(salary) FROM employees e2 WHERE e2.department_id = e1.department_id ); # 查询员工的id,name,要求按照department_name从小到大排序 SELECT id,name FROM employees e ORDER BY ( SELECT department_name FROM departments d WHERE e.department_id = d.department_id ) DESC;
# 查询公司管理者的id,name,job_id,department_id # 方式一: SELECT id,name,job_id,department_id FROM employees WHERE id IN ( SELECT DISTINCT manager_id FROM employees ); # 方式二: SELECT id,name,job_id,department_id FROM employees e1 WHERE EXISTS ( # 找到就返回true SELECT '*' FROM employees e2 WHERE e1.id = e2.manager_id );
数据库对象:表、视图、函数、触发器、存储过程等
# 创建库 CREATE DATABASE mydatabase; # 使用库 USE mydatabase; # 删除库 DROP DATABASE mydatabase;
# 方式一: CREATE TABLE mytable( id INT, name VARCHAR(15), email VARCHAR(20), salary DOUBLE(10,2), birthday DATE ); # 方式二:基于现有的表创建新表 CREATE TABLE mytable2 AS SELECT id,name,salary FROM employees;
# 增加一个字段 ALTER TABLE mytable ADD age INT; # 删除一个字段 ALTER TABLE mytable DROP age; # 修改字段 ALTER TABLE mytable MODIFY name VARCHAR(10); # 重命名字段 ALTER TABLE mytable CHANGE birthday birth DATE;
RENAME TABLE mytable2 TO mytable3;
DROP TABLE mytable3;
# 清空表中的数据,但是表结构保留 # 会自动commit,一旦操作,就不可以回滚数据 TRUNCATE TABLE mytable;
# 根据已有的表 CREATE TABLE mytable( id INT, name VARCHAR(15), email VARCHAR(20), birthday DATE );
# 添加数据 INSERT INTO mytable(id,name,email,birthday) VALUES (1,'tom','tom@qq.com','2000-02-03') # 基于现有的表 INSERT INTO mytable(id,name) SELECT id,name FROM employees WHERE department_id IN (10,20,30);
# 支持回滚 DELETE FROM mytable WHERE id = 1;
UPDATE mytable SET name = 'jerry',email = 'jerry@126.com' WHERE id = 1;
# 创建表的时候添加约束 CREATE TABLE mytable( id INT NOT NULL, name VARCHAR(15) NOT NULL, email VARCHAR(20), birthday DATE ); # 修改表的时候删除约束 ALTER TABLE mytable MODIFY name VARCHAR(15) NULL;
# 创建表的时候添加约束 CREATE TABLE mytable( # 列级约束 id INT UNIQUE, name VARCHAR(15), email VARCHAR(20), birthday DATE, # 表级约束 CONSTRAINT mytable_email_uni UNIQUE (email) ); # 修改表的时候删除约束 # 删除索引 ALTER TABLE mytable DROP INDEX mytable_email_uni; ALTER TABLE mytable DROP INDEX id;
主键约束,既满足唯一性,也满足非空性。一个表中只能声明一个主键约束
# 通常在创建表的时候添加约束 # 列级约束 CREATE TABLE mytable( id INT PRIMARY KEY AUTO_INCREMENT,# 自增长 name VARCHAR(15), email VARCHAR(20), birthday DATE ); # 表级约束 CREATE TABLE mytable( id INT AUTO_INCREMENT, name VARCHAR(15), email VARCHAR(20), birthday DATE, CONSTRAINT mytable_id_pri PRIMARY KEY (id) ); # 删除主键 # 如果设置了自动增长,则会删除失败 # 删除主键之后,字段还会保留not null的约束 ALTER TABLE mytable DROP PRIMARY KEY; # 添加主键 ALTER TABLE mytable ADD CONSTRAINT mytable_id_pri PRIMARY KEY (id);
外键约束:在表1的字段a声明有一个外键约束,与表2的字段b相关联,则字段a在操作数据时,其数据一定是字段b中出现的数据
要求:要想关联成功,必须要求字段b声明有主键约束或者唯一性约束。
CREATE TABLE dept( dept_id INT PRIMARY KEY, dept_name VARCHAR(10) ); CREATE TABLE emp( emp_id INT, emp_name VARCHAR(15), dept_id INT, # 声明外键 CONSTRAINT emp_dept_id_for FOREIGN KEY (dept_id) REFERENCES dept (dept_id) );
# 对MySQL失效 CREATE TABLE mytable( id INT, name VARCHAR(15), salary DOUBLE(10,2) CHECK (salary > 3000) # 添加的工资要大于3000 );
CREATE TABLE mytable( id INT, name VARCHAR(15), salary DOUBLE(10,2) DEFAULT 2500 # 提供默认值 );