mysql学习笔记(1)
MySQL初识
安装Mysql
- 1.本次安装的版本是Mysql5.6绿色免安装版,下载的百度云地址,提取码 【 2yrr 】
- 2.解压到指定的文件目录下(不含中文和空格目录)
- 3.把MySQL\bin目录添加到环境变量path中
- 3.管理员权限打开CMD命令行工具,切换目录到MySQL的Bin目录下
- 4.CMD执行 mysqld install ,安装Mysql服务
- 5.CMD执行 net start mysql,启动MySQL服务。
- 如果遇到MySQL服务1067错误解决措施:
- a) 定位到安装好的Mysql根目录,复制 my.ini 到 C盘 windows文件夹
- b) 记事本打开my-default.ini,把里面 #注释去掉(说明不用去)
- c) 重启电脑,CMD执行 net start mysql,启动MySQL服务。
- 6.CMD执行 mysql -u root -p root 进入mysql编辑器
Mysql的命令行语句
- mysql -u root -p 后换行输入密码,不让别人知道密码
- mysql -h IP地址 -P 访问主机的Mysql端口 -u 用户名 -p 密码
- mysql -h localhost -p3306 -u root -p root
- exit 或 quit 退出mysql
- 导入外部表 source 路径+文件
- 更改字符集,默认是拉丁文,中文输入会乱码;一般选择UTF-8
- 1.查看当前数据库字符集
- show VARIABLES like 'character%';
- 2.修改数据库字符集
- alter database 数据库名 character set utf8;
- (或)修改表字符集
- ALTER TABLE 表名 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
- 3.重启mysql服务即可
- cmd执行
- 停止服务: net stop mysql
- 启动服务: net start mysql
- cmd执行
- 1.查看当前数据库字符集
- 查询时解决显示乱码(不是修改数据库字符集,只是用指定字符集显示,退出数据库后失效)
* set character_set_results = 字符集;
基础SQL语句
SQL操作
DQL | (date query language,数据检索语言),有:SELECT |
DML | (date manipulation language,数据操纵语言),有:INSERT、UPDATE、DELETE |
DDL | (data definition language,数据定义语言),有:CREATE、ALTER、DROP、TRUNCATE |
DCL | (data controlLanguage,数据控制语言),有:GRANT、REVOKE、DENY |
增删查数据库&表
- 查询所有数据库:SHOW DATABASES;
- 创建数据库:CREATE DATABASE databasename;
- 选择某个数据库 use databasename;
- 例如 USE mysql;
- 删除数据库
- DROP DATABASE databasename;
- 查询所有表
- SHOW TABLES;
- 创建表 (if not exists:如果不存在就创建)
- CREATE TABLE [ IF NOT EXISTS ] tablename;
- 选择表
- SELECT * FROM tablename;
- 删除表
- DROP TABLE tablename;
- DROP TABLE tablename;
插入数据&查询数据
-
插入数据库
- INSERT INTO tablename (columname1,...,columnnamen) VALUES (columnvalue1,...,columnvaluen),[(columnvalue1,...,columnvaluen)],...
-
查询数据
- 查询所有: SELECT * FROM tablename
- 查询单列: SELECT columnname FROM tablename;
- 查询多列: SELECT columnname1,columnname2,...,columnnameN FROM tablename;
-
去重 distinct
- 单条件去重:
- SELECT DISTINCT vend_id FROM products;
- 多条件去重:
- SELECT DISTINCT vend_id , prod_price FROM products;
- 单条件去重:
-
排序 order by
- 默认情况升序(asc)
- 多条件升序
- SELECT vend_id,prod_price FROM products ORDER BY vend_id ASC,prod_price ASC;
- 降序(desc)
- SELECT vend_id,prod_price FROM products ORDER BY prod_price DESC,vend_id ASC;
- 默认情况升序(asc)
-
限制结果 limit
- 表示前n行 limit n
- SELECT * FROM products LIMIT 5;
- 表示显示从(第n+1行)开始的n行 limit m,n
- SELECT * FROM products LIMIT(0,5);
- limit 和 order by 连用可以查询最高、最低的n条记录
- SELECT prod_price FROM products ORDER BY prod_price asc LIMIT 3;
- SELECT prod_price FROM products ORDER BY prod_price desc LIMIT 3;
- 表示前n行 limit n
-
过滤条件:where
- 操作符: = ,> , < , >= ,<= ,!= , <> 不等于
- SELECT * FROM products WHERE prod_price <> 10;
- 等于
- SELECT * FROM products WHERE prod_price != 10;
- 等于
- SELECT * FROM products WHERE prod_price > 10 OR prod_price < 10;
-
SQL语句的顺序
- SELECT * FROM products WHERE prod_price>10 ORDER BY prod_price DESC LIMIT 3;
- 自己确定优先级加括号()
- SELECT * FROM products WHERE (prod_price>10 AND prod_price<20) AND vend_id=1001;
-
两者之间,包含边界
- SELECT * FROM products WHERE prod_price BETWEEN 10 AND 20 ;
- 等于
- SELECT * FROM products WHERE prod_price >=10 AND prod_price <= 20;
- SELECT * FROM products WHERE prod_price NOT BETWEEN 10 AND 20;
-
空值查询: is null ; 非空查询: is not null
- SELECT * FROM vendors WHERE vend_id IS NULL;
- SELECT * FROM vendors WHERE vend_id IS NOT NULL;
-
集合查询IN(n1,n2,...,n) ; NOT IN(n1,n2,...,n)
- SELECT * FROM products WHERE vend_id IN (1001,1002,1003);
- SELECT * FROM products WHERE vend_id NOT IN (1001,1002,1003);
-
模糊查询
- % : 代替一个或多个字符
- : 代替一个字符,替代几个字符就需要几个""
- SELECT * FROM products WHERE prod_name LIKE '%a%'; 产品名包含字母a
- SELECT * FROM products WHERE prod_name LIKE 'a%'; 产品名以a开头
- SELECT * FROM products WHERE prod_name LIKE '_a%'; 产品名第二个字母是a
- 【例】:产品名同时含有a和o两个字符但不知道其先后顺序
- SELECT * FROM products WHERE prod_name LIKE "%a%" AND prod_name LIKE "%o%";
- 等于
- SELECT * FROM products WHERE prod_name LIKE "%a%o%" OR prod_name LIKE "%o%a%";
-
正则匹配 REGEXP
- SELECT * FROM PRODUCTS WHERE prod_name REGEXP 'o'; 产品名中包含字母'o'
- "." 点表示代替一个字符
- SELECT * FROM products where prod_name REGEXP '.o'; 点表示代替一个字符,选择从第二位往后匹配‘o’
- " ^ " 表示开头
- SELECT * FROM products where prod_name REGEXP '^o';
- " $ " 表示结尾
- SELECT * FROM products where prod_name REGEXP '$o';
- " | " 表示或者
- 【例】:选出产品名字包含01,或02或03
- SELECT * FROM products where vend_id REGEXP '01|02|03';
- 等于
- SELECT * FROM products where prod_id REGEXP '0[1|2|3]';
- 等于
- SELECT * FROM products where prod_id REGEXP '0[123]';
- 等于
- SELECT * FROM products where prod_id REGEXP '0[1-3]';
- ' * ' 表示匹配前面字符任意字符 (0-N)次
- ' + ' 表示匹配前面字符至少一次 (1-N)次
- ' ? ' 表示匹配前面字符至多一次 (0或1)次
- ' {n} ' 表示匹配前面字符N次
- ' {n,} ' 表示匹配前面字符至少N次
- ' {n,m} ' 表示配置前面的字符(n~m)次,m最大次数为255
- ' [0-9] ' 表示(0~9)任意一位数字
- ' [A-Z] ' 或' [a-z] ' 表示任意字母
- ' \ ' 转义符,表示把字符转为普通字符串
- ' dual ' 表示mysql的虚表
- ' ^ ' 表示开头
- ' $ ' 表示结尾
- ' [^] ' 表示取反
*1.以1开头,后10位任意数字
* ^1[0-9]<10>$
* SELECT 1 FROM DUAL WHERE '13333333333' REGEXP '^1[0-9]<10>$';
*2.邮箱格式
* ^[0-9a-zA-Z]+@[0-9a-z]<2,>\\.[a-z]+$
* SELECT 1 FROM DUAL WHERE '133@sina.com' REGEXP '^[0-9a-zA-Z]+@[0-9a-zA-Z]{2,}\\.[a-zA-Z]+$';
*3.取不是(0-8)之案件数字
* ^[^0-8]$
* SELECT 1 FROM DUAL WHERE '1' REGEXP '^[^0-8]';
- 字符处理函数
- 拼接字符串 CONCAT
SELECT CONCAT(prod_id,'的价格为',prod_price) from products;
- 拼接字符串 CONCAT
- 取别名(AS可省略) AS
SELECT prod_id AS 编号,prod_price AS 价格 from products; - 列全名&表全名
- SELECT ceshi80.products.prod_id,products.prod_name FROM ceshi80.products;
SQL数值计算
- *,+,/
- SELECT prod_name 商品名,prod_price 进价,prod_price*1.1 售价 FROM products;
- 取余函数 mod(n,m)
- SELECT MOD(4,3),MOD(1,3),MOD(4,0) FROM DUAL;
- SELECT MOD(4,3),MOD(1,3),MOD(4,0) FROM DUAL;
+----------+----------+----------+
| MOD(4,3) | MOD(1,3) | MOD(4,0) |
+----------+----------+----------+
| 1 | 1 | NULL |
+----------+----------+----------+
- 取绝对值函数 ABS(n)
- SELECT ABS(3.14),ABS(0),ABS(-3.14) FROM DUAL;
- SELECT ABS(3.14),ABS(0),ABS(-3.14) FROM DUAL;
+-----------+--------+------------+
| ABS(3.14) | ABS(0) | ABS(-3.14) |
+-----------+--------+------------+
| 3.14 | 0 | 3.14 |
+-----------+--------+------------+
- 向上取整 ceil(n)
- SELECT CEIL(1.2),CEIL(1.9),CEIL(-1.2),CEIL(-1.9) FROM dual;
+-----------+-----------+------------+------------+
| CEIL(1.2) | CEIL(1.9) | CEIL(-1.2) | CEIL(-1.9) |
+-----------+-----------+------------+------------+
| 2 | 2 | -1 | -1 |
+-----------+-----------+------------+------------+
- 向下取整 floor(n)
- SELECT FLOOR(1.2),FLOOR(1.9),FLOOR(-1.2),FLOOR(-1.9) FROM DUAL;
- SELECT FLOOR(1.2),FLOOR(1.9),FLOOR(-1.2),FLOOR(-1.9) FROM DUAL;
+------------+------------+-------------+-------------+
| FLOOR(1.2) | FLOOR(1.9) | FLOOR(-1.2) | FLOOR(-1.9) |
+------------+------------+-------------+-------------+
| 1 | 1 | -2 | -2 |
+------------+------------+-------------+-------------+
- 四舍五入 round(n)
- SELECT ROUND(1.4),ROUND(1.5),ROUND(-1.4),ROUND(-1.5) FROM DUAL;
- SELECT ROUND(1.4),ROUND(1.5),ROUND(-1.4),ROUND(-1.5) FROM DUAL;
+------------+------------+-------------+-------------+
| ROUND(1.4) | ROUND(1.5) | ROUND(-1.4) | ROUND(-1.5) |
+------------+------------+-------------+-------------+
| 1 | 2 | -1 | -2 |
+------------+------------+-------------+-------------+
- 截断函数 truncate(m,n) (去尾,n为负数往前截取数,n为正网后截取数)
- SELECT TRUNCATE(1.23456,3),TRUNCATE(1.23456,8),TRUNCATE(333.23456,-2),TRUNCATE(1.23,-5),TRUNCATE(-1.23456,3),TRUNCATE(1.23934,2) FROM DUAL;
- SELECT TRUNCATE(1.23456,3),TRUNCATE(1.23456,8),TRUNCATE(333.23456,-2),TRUNCATE(1.23,-5),TRUNCATE(-1.23456,3),TRUNCATE(1.23934,2) FROM DUAL;
+---------------------+---------------------+------------------------+-------------------+----------------------+---------------------+
| TRUNCATE(1.23456,3) | TRUNCATE(1.23456,8) | TRUNCATE(333.23456,-2) | TRUNCATE(1.23,-5) | TRUNCATE(-1.23456,3) | TRUNCATE(1.23934,2) |
+---------------------+---------------------+------------------------+-------------------+----------------------+---------------------+
| 1.234 | 1.23456000 | 300 | 0 | -1.234 | 1.23 |
+---------------------+---------------------+------------------------+-------------------+----------------------+---------------------+
- 开根号函数 sqrt(n)
- SELECT SQRT(3),SQRT(-3),SQRT(0) FROM dual;
- SELECT SQRT(3),SQRT(-3),SQRT(0) FROM dual;
+--------------------+----------+---------+
| SQRT(3) | SQRT(-3) | SQRT(0) |
+--------------------+----------+---------+
| 1.7320508075688772 | NULL | 0 |
+--------------------+----------+---------+
- 圆周率 pi() (默认精确到后6位,最大精度后16位)
- SELECT PI(),TRUNCATE(PI(),8),TRUNCATE(PI(),20) FROM dual;
- SELECT PI(),TRUNCATE(PI(),8),TRUNCATE(PI(),20) FROM dual;
+----------+------------------+------------------------+
| PI() | TRUNCATE(PI(),8) | TRUNCATE(PI(),20) |
+----------+------------------+------------------------+
| 3.141593 | 3.14159265 | 3.14159265358979360000 |
+----------+------------------+------------------------+
- 随机数 rand() (随机数和rand括号里数字无关)
- SELECT RAND(10),RAND(),RAND()*10 FROM dual;
- SELECT RAND(10),RAND(),RAND()*10 FROM dual;
+--------------------+--------------------+-------------------+
| RAND(10) | RAND() | RAND()*10 |
+--------------------+--------------------+-------------------+
| 0.6570515219653505 | 0.3438523061050589 | 9.198721627889872 |
+--------------------+--------------------+-------------------+
字符处理函数
- 拼接字符串 concat(str1,str2,str3)
- 返回字符串字符数 char_length()
- length() 返回字符串的长度(注:因版本不同中文占2或3个)
- 字符串大写 upper()
- 字符串小写 lower()
- 返回字符串s前n个字符 left(s,n)
- 返回字符串s后n个字符 right(s,n)
- 字符串左填充 lpad(s1,len,s2) (以s2左填充S1,使得s1的总长为len)(注:如果len长度少于s1长度,后面字符串会被截取)
- 字符串右填充 lpad(s1,len,s2) (以s2右填充S1,使得s1的总长为len)(注:如果len长度少于s1长度,后面字符串会被截取)
- 去左空格 ltrim(s) (去掉字符串左边的空格)
- SELECT LTRIM(' df '),LENGTH(LTRIM(' df ')) FROM DUAL;
- SELECT LTRIM(' df '),LENGTH(LTRIM(' df ')) FROM DUAL;
+-----------------+------------------------+
| LTRIM(' df ') | LENGTH(LTRIM(' df ')) |
+-----------------+------------------------+
| df | 4 |
+-----------------+------------------------+
- 去右空格 rtrim(s) (去掉字符串右边的空格)
- SELECT RTRIM(' df '),LENGTH(LTRIM(' df ')) FROM DUAL;
- SELECT RTRIM(' df '),LENGTH(LTRIM(' df ')) FROM DUAL;
+-----------------+-------------------------+
| RTRIM(' df ') | LENGTH(LTRIM(' df ')) |
+-----------------+-------------------------+
| df | 4 |
+-----------------+-------------------------+
- 去两边空格 trim(s)
- SELECT TRIM(' df '),LENGTH(TRIM(' df ')) FROM DUAL;
- SELECT TRIM(' df '),LENGTH(TRIM(' df ')) FROM DUAL;
+----------------+------------------------+
| TRIM(' df ') | LENGTH(TRIM(' df ')) |
+----------------+------------------------+
| df | 2 |
+----------------+------------------------+
- 去左右两端的字符 trim (str1 from str2)
- SELECT TRIM('aa' FROM 'aaabfaabfaa') FROM DUAL;
- SELECT TRIM('aa' FROM 'aaabfaabfaa') FROM DUAL;
+-------------------------------+
| TRIM('aa' FROM 'aaabfaabfaa') |
+-------------------------------+
| abfaabf |
+-------------------------------+
- 替换字符 INSERT(str1,n,m,str2) 用str2替换str1第n个字符开始的后m个字符
- SELECT INSERT('aaaaaaaa',3,2,'hhhh') FROM DUAL;
- SELECT INSERT('aaaaaaaa',3,2,'hhhh') FROM DUAL;
+-------------------------------+
| INSERT('aaaaaaaa',3,2,'hhhh') |
+-------------------------------+
| aahhhhaaaa |
+-------------------------------+
- 查找和替换 replace(str1,str2,str3),用str3替换str1中的str2
- SELECT REPLACE('aabbdddff','bb','cc') FROM DUAL;
- SELECT REPLACE('aabbdddff','bb','cc') FROM DUAL;
+--------------------------------+
| REPLACE('aabbdddff','bb','cc') |
+--------------------------------+
| aaccdddff |
+--------------------------------+
- 截取字符串 substring(str,n,len) 返回字符串str中第n个字符开始的len长度
- SELECT SUBSTRING('123456',3,2),SUBSTRING('123456',3,6) FROM DUAL;
+-------------------------+-------------------------+
| SUBSTRING('123456',3,2) | SUBSTRING('123456',3,6) |
+-------------------------+-------------------------+
| 34 | 3456 |
+-------------------------+-------------------------+
- 字符串比较函数 strcmp
- SELECT STRCMP('AB','AB'),STRCMP('AB','ab') FROM DUAL;
+-------------------+-------------------+
| STRCMP('AB','AB') | STRCMP('AB','ab') |
+-------------------+-------------------+
| 0 | 0 |
+-------------------+-------------------+
- SELECT STRCMP('AB','ab'),STRCMP('abcd','abc') FROM DUAL;
+-------------------+----------------------+ | STRCMP('AB','ab') | STRCMP('abcd','abc') | +-------------------+----------------------+ | 0 | 1 | +-------------------+----------------------+
- 查找字符串位置(1) instr(str1,str2) str2在str1中位置,返回字符串中第一次出现位置
- SELECT instr ('chaina','a') FROM DUAL;
+----------------------+
| instr ('chaina','a') |
+----------------------+
| 3 |
+----------------------+
- 查找字符串位置(2) locate(s1,s2) 返回s1在s2位置
- SELECT LOCATE('a','chaina') FROM DUAL;
+----------------------+
| LOCATE('a','chaina') |
+----------------------+
| 3 |
+----------------------+
- 查找字符串位置(3) position(s1 in s2)返回s1在s2位置
- SELECT POSITION('h' in 'chinahis') FROM DUAL;
+-----------------------------+
| POSITION('h' in 'chinahis') |
+-----------------------------+
| 2 |
+-----------------------------+
-
查找字符串位置(3) substring_index(s1,s2,n) 返s1开始的,以s2作为分割符第n个前面的字符。
- SELECT SUBSTRING_INDEX('ni nihao ma, wo hen hao',' ',3) FROM DUAL;
+--------------------------------------------------+ | SUBSTRING_INDEX('ni nihao ma, wo hen hao',' ',3) | +--------------------------------------------------+ | ni nihao ma, | +--------------------------------------------------+
-
查找字符串位置(4) ELT(n,str1,str2,str3...)返回第n个字符串
- SELECT ELT(3,'ZHANG3','LI4','WANGWU'),ELT(4,'ZHANG3','LI4','WANGWU') FROM DUAL;
+--------------------------------+--------------------------------+
| ELT(3,'ZHANG3','LI4','WANGWU') | ELT(4,'ZHANG3','LI4','WANGWU') |
+--------------------------------+--------------------------------+
| WANGWU | NULL |
+--------------------------------+--------------------------------+
日期函数
- 返回当前的日期 curdate()(注意只有一个r),current_date()
- SELECT CURDATE(),CURRENT_DATE() FROM DUAL;
+------------+----------------+
| CURDATE() | CuRRENT_DATE() |
+------------+----------------+
| 2018-10-12 | 2018-10-12 |
+------------+----------------+
- 返回当前的时间 curtime(),current_time()
- SELECT CURTIME(),CURRENT_TIME() FROM DUAL;
+-----------+----------------+
| CURTIME() | CURRENT_TIME() |
+-----------+----------------+
| 11:18:49 | 11:18:49 |
+-----------+----------------+
- 返回当前的日期和时间 now(),current_timestamp(),sysdate(),localtime(),localtimestamp()
- SELECT NOW(),CURRENT_TIMESTAMP(),SYSDATE(),LOCALTIME(),LOCALTIMESTAMP() FROM DUAL;
+---------------------+---------------------+---------------------+---------------------+---------------------+
| NOW() | CURRENT_TIMESTAMP() | SYSDATE() | LOCALTIME() | LOCALTIMESTAMP() |
+---------------------+---------------------+---------------------+---------------------+---------------------+
| 2018-10-12 11:19:15 | 2018-10-12 11:19:15 | 2018-10-12 11:19:15 | 2018-10-12 11:19:15 | 2018-10-12 11:19:15 |
+---------------------+---------------------+---------------------+---------------------+---------------------+
- 返回日期date中的年 YEAR(date)
- 返回日期date中的月 month(date) 返回阿拉伯数字; monthname(date) 返回英文月份
- SELECT YEAR('2018-09-03'),MONTH('2018-10-9'),MONTHNAME('2018-10-9') FROM DUAL;
+--------------------+--------------------+------------------------+
| YEAR('2018-09-03') | MONTH('2018-10-9') | MONTHNAME('2018-10-9') |
+--------------------+--------------------+------------------------+
| 2018 | 10 | October |
+--------------------+--------------------+------------------------+
- SELECT YEAR(now()),YEAR(CURTIME()) FROM DUAL;
+-------------+-----------------+ | YEAR(now()) | YEAR(CURTIME()) | +-------------+-----------------+ | 2018 | 2018 | +-------------+-----------------+
- 返回日期date中月份的第几天 dayofmonth(date)
- SELECT DAYOFMONTH(CURTIME()) FROM DUAL;
+-----------------------+
| DAYOFMONTH(CURTIME()) |
+-----------------------+
| 12 |
+-----------------------+
- 返回日期date中年的第几天 dayofyear(date)
- SELECT DAYOFYEAR(NOW()),DAYOFYEAR('2008-12-30'),DAYOFYEAR('2018-12-30') FROM DUAL;
+------------------+-------------------------+-------------------------+ | DAYOFYEAR(NOW()) | DAYOFYEAR('2008-12-30') | DAYOFYEAR('2018-12-30') | +------------------+-------------------------+-------------------------+ | 285 | 365 | 364 | +------------------+-------------------------+-------------------------+
- hour(time) 返回时间time中的时
- minute(time) 返回时间time中的分
- second(time) 返回时间time中的秒
- SELECT CURTIME(), HOUR(CURTIME()),MINUTE(NOW()),SECOND(NOW()) FROM DUAL;
+-----------+-----------------+---------------+---------------+
| CURTIME() | HOUR(CURTIME()) | MINUTE(NOW()) | SECOND(NOW()) |
+-----------+-----------------+---------------+---------------+
| 11:24:28 | 11 | 24 | 28 |
+-----------+-----------------+---------------+---------------+
-
extract(type) 从日期date中返回指定type的值
- SELECT
EXTRACT(YEAR FROM NOW()) 年,EXTRACT(MONTH FROM NOW()) 月,
EXTRACT(DAY FROM NOW()) 日,EXTRACT(HOUR FROM NOW()) 时,
EXTRACT(MINUTE FROM NOW()) 分,EXTRACT(SECOND FROM NOW()) 秒
FROM DUAL;
+------+------+------+------+------+------+ | 年 | 月 | 日 | 时 | 分 | 秒 | +------+------+------+------+------+------+ | 2018 | 10 | 12 | 11 | 30 | 59 | +------+------+------+------+------+------+
- SELECT
-
adddate(date,n) 返回前面日期加上多少天;可用于计算产假,入职多少天等
- SELECT ADDDATE(NOW(),50);
+---------------------+ | ADDDATE(NOW(),50) | +---------------------+ | 2018-12-01 11:31:27 | +---------------------+
-
addtime(date,n) 返回前面日期加上多少秒,n最大59
- SELECT NOW(),ADDTIME(NOW(),59),ADDTIME(NOW(),60) FROM DUAL;
+---------------------+---------------------+-------------------+
| NOW() | ADDTIME(NOW(),59) | ADDTIME(NOW(),60) |
+---------------------+---------------------+-------------------+
| 2018-10-12 11:31:52 | 2018-10-12 11:32:51 | NULL |
+---------------------+---------------------+-------------------+
-
datediff(date1,date2) 返回 date1 - date2 的值,有绝对值
- SELECT DATEDIFF(NOW(),'1993-05-07'),DATEDIFF('1993-05-07',NOW()) FROM DUAL; #计算从出生到现在有多少天
+------------------------------+------------------------------+ | DATEDIFF(NOW(),'1993-05-07') | DATEDIFF('1993-05-07',NOW()) | +------------------------------+------------------------------+ | 9289 | -9289 | +------------------------------+------------------------------+
-
格式化日期 date_format(date,str) str 有【 %Y%M%D】、【 %y%m%d 】、【 %y/%m/%d 】、【 %Y/%M/%D 】
-
SELECT DATE_FORMAT('2018-08-11','%Y%M%D') FROM DUAL;
+------------------------------------+ | DATE_FORMAT('2018-08-11','%Y%M%D') | +------------------------------------+ | 2018August11th | +------------------------------------+
-
SELECT DATE_FORMAT('2018-08-11','%y%m%d') FROM DUAL;
+------------------------------------+ | DATE_FORMAT('2018-08-11','%y%m%d') | +------------------------------------+ | 180811 | +------------------------------------+
-
SELECT DATE_FORMAT('2018-08-11','%Y/%M/%D') FROM DUAL;
+--------------------------------------+ | DATE_FORMAT('2018-08-11','%Y/%M/%D') | +--------------------------------------+ | 2018/August/11th | +--------------------------------------+
-
SELECT DATE_FORMAT('2018-08-11','%y/%m/%d') FROM DUAL;
+--------------------------------------+ | DATE_FORMAT('2018-08-11','%y/%m/%d') | +--------------------------------------+ | 18/08/11 | +--------------------------------------+
-
判断空否 ifnull(v1,v2) 如果v1值不为null,则返回v1,否则返回v2
- SELECT vend_state,IFNULL(VEND_STATE,'SZ') AS 城市 FROM vendors;
+------------+--------+
| vend_state | 城市 |
+------------+--------+
| MI | MI |
| OH | OH |
| CA | CA |
| NY | NY |
| NULL | SZ |
| NULL | SZ |
+------------+--------+
- if(exp,v1,v2) 如果表达式exp成立,返回v1,否则返回v2
- SELECT vend_state,IF(VEND_STATE IS NULL,'SZ',VEND_STATE) AS 城市 FROM vendors; #(等同与上者)
+------------+--------+
| vend_state | 城市 |
+------------+--------+
| MI | MI |
| OH | OH |
| CA | CA |
| NY | NY |
| NULL | SZ |
| NULL | SZ |
+------------+--------+
- SELECT prod_name,prod_price,IF(prod_price > 5,'贵','便宜') AS 评价 FROM products;
+----------------+------------+--------+ | prod_name | prod_price | 评价 | +----------------+------------+--------+ | .5 ton anvil | 5.99 | 贵 | | 1 ton anvil | 9.99 | 贵 | | 2 ton anvil | 14.99 | 贵 | | Detonator | 13.00 | 贵 | | Bird seed | 10.00 | 贵 | | Carrots | 2.50 | 便宜 | | Fuses | 3.42 | 便宜 | | JetPack 1000 | 35.00 | 贵 | | TNT (5 sticks) | 10.00 | 贵 | +----------------+------------+--------+
- 多重判断 case when exp1 than '别名' [when exp2 than '别名'] [...] end 列别名
SELECT vend_id,prod_name,prod_price, case when prod_price <= 10 then '便宜' when prod_price>10 && prod_price <= 20 then '比较贵' when prod_price>20 then '贵' end 评价 FROM products; 运行结果: +---------+----------------+------------+-----------+ | vend_id | prod_name | prod_price | 评价 | +---------+----------------+------------+-----------+ | 1001 | .5 ton anvil | 5.99 | 便宜 | | 1001 | 1 ton anvil | 9.99 | 便宜 | | 1001 | 2 ton anvil | 14.99 | 比较贵 | | 1003 | Detonator | 13.00 | 比较贵 | | 1003 | Bird seed | 10.00 | 便宜 | | 1005 | JetPack 1000 | 35.00 | 贵 | | 1005 | JetPack 2000 | 55.00 | 贵 | | 1002 | Oil can | 8.99 | 便宜 | | 1003 | Safe | 50.00 | 贵 | +---------+----------------+------------+-----------+
系统信息函数
- 返回数据库的版本号: version()
- 返回服务器的链接数: connection_id()
- 返回当前的数据库名: database(),schema()
- 返回当前用户: user(),system_user(),current_user()
- 加密函数: password(str),md5(str)
+-------------------------------------------+----------------------------------+ | password('root') | md5('root') | +-------------------------------------------+----------------------------------+ | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B | 63a9f0ea7bb98050796b649e85481845 | +-------------------------------------------+----------------------------------+
格式化函数
- 将数字进行格式格式化:format(x,n) (n数字,n截取的小数位)
- SELECT FORMAT(1234.1234,2) FROM DUAL;
+---------------------+
| FORMAT(1234.1234,2) |
+---------------------+
| 1,234.12 |
+---------------------+
- ascll(str) 返回字符串第一个字符的ASCII值
- bin(str) 十进制转二进制
数值函数
- 最大值 max() 空值不会参与计算
- 最小值 min() 空值不会参与计算
- 总计 sum() 空值不会参与计算
- 平均数 avg() 空值不会参与计算
- SELECT MAX(prod_price)最大值,min(prod_price) 最小值,AVG(prod_price) 总计,AVG(prod_price)平均数 FROM products;
+-----------+-----------+-----------+-----------+
| 最大值 | 最小值 | 总计 | 平均数 |
+-----------+-----------+-----------+-----------+
| 55.00 | 2.50 | 16.133571 | 16.133571 |
+-----------+-----------+-----------+-----------+
- 计数 count()
- count(*) 会统计非空; count(column) 空值不会参与计算
- SELECT COUNT(*),COUNT(VEND_STATE) FROM VENDORS;
+----------+-------------------+
| COUNT(*) | COUNT(VEND_STATE) |
+----------+-------------------+
| 6 | 4 |
+----------+-------------------+
聚合函数与分组 GROUP BY (后面一列,以这列作为分组;如果多列,以多列会不相同作为分组)
- 本SQL语句数据下载地址:百度云,提取码【6gin】
1.测试的表数据
- 订单号表数据
- SELECT * FROM orderitems;
+-----------+------------+---------+----------+------------+ | order_num | order_item | prod_id | quantity | item_price | +-----------+------------+---------+----------+------------+ | 20005 | 1 | ANV01 | 10 | 5.99 | | 20005 | 2 | ANV02 | 3 | 9.99 | | 20005 | 3 | TNT2 | 5 | 10.00 | | 20005 | 4 | FB | 1 | 10.00 | | 20006 | 1 | JP2000 | 1 | 55.00 | | 20007 | 1 | TNT2 | 100 | 10.00 | | 20008 | 1 | FC | 50 | 2.50 | | 20009 | 1 | FB | 1 | 10.00 | | 20009 | 2 | OL1 | 1 | 8.99 | | 20009 | 3 | SLING | 1 | 4.49 | | 20009 | 4 | ANV03 | 1 | 14.99 | +-----------+------------+---------+----------+------------+
2.练习
- 分组函数 GROUP BY
- select order_num,sum(quantity*item_price)应付款 from orderitems group by order_num;
- 选择商品号作为分组条件的商品号与应付款
+-----------+-----------+ | order_num | 应付款 | +-----------+-----------+ | 20005 | 149.87 | | 20006 | 55.00 | | 20007 | 1000.00 | | 20008 | 125.00 | | 20009 | 38.47 | +-----------+-----------+
- 选择以商品号和应付款分组条件的商品号和应付款
- select order_num,sum(quantity*item_price)应付款 from orderitems group by order_num,prod_id;
+-----------+-----------+ | order_num | 应付款 | +-----------+-----------+ | 20005 | 59.90 | | 20005 | 29.97 | | 20005 | 10.00 | | 20005 | 50.00 | | 20006 | 55.00 | | 20007 | 1000.00 | | 20008 | 125.00 | | 20009 | 14.99 | | 20009 | 10.00 | | 20009 | 8.99 | | 20009 | 4.49 | +-----------+-----------+
- 总和 ROLLUP
- 选择 商品号和应付款,以及所有商品号应付款的总额
- select order_num,sum(quantity*item_price)应付款 from orderitems group by order_num WITH ROLLUP;
+-----------+-----------+
| order_num | 应付款 |
+-----------+-----------+
| 20005 | 149.87 |
| 20006 | 55.00 |
| 20007 | 1000.00 |
| 20008 | 125.00 |
| 20009 | 38.47 |
| NULL | 1368.34 |
+-----------+-----------+
- 过滤分组条件 HAVING (在GROUP BY后面)
- 选择应付款大于100的商品号和应付款
- select order_num,sum(quantity*item_price)应付款 from orderitems group by order_num HAVING 应付款>100;
+-----------+-----------+
| order_num | 应付款 |
+-----------+-----------+
| 20005 | 149.87 |
| 20007 | 1000.00 |
| 20008 | 125.00 |
+-----------+-----------+
- 分组条件的综合利用(注意语法的先后顺序)
- 选择订单号在(20005,20006,20007)内,以订单号作为分组,应付款大于100并以应付款作为降序条件,筛选出前一个的订单号与应付款.
代码: SELECT ORDER_NUM,SUM(quantity*item_price) 应付款 FROM orderitems WHERE order_num in(20005,20006,20007) GROUP BY order_num HAVING 应付款>100 ORDER BY 应付款 desc LIMIT 1; 显示结果: +-----------+-----------+ | ORDER_NUM | 应付款 | +-----------+-----------+ | 20007 | 1000.00 | +-----------+-----------+
子查询
-
【例1】查看提供FB产品的供应商还提供哪些产品
--代码 SELECT vend_id,prod_id FROM products WHERE vend_id IN ( SELECT vend_id FROM products WHERE prod_id='FB' ); -- 显示的结果 +---------+---------+ | vend_id | prod_id | +---------+---------+ | 1003 | DTNTR | | 1003 | FB | | 1003 | FC | | 1003 | SAFE | | 1003 | SLING | | 1003 | TNT1 | | 1003 | TNT2 | +---------+---------+
-
【例2】查看提供FB产品的供应商名字
--代码 SELECT vend_name FROM vendors WHERE vend_id IN ( SELECT vend_id FROM products WHERE prod_id='FB' ); --显示的结果 +-----------+ | vend_name | +-----------+ | ACME | +-----------+
-
【例3】列出订购物品TNT2的所有客户
--代码: *step1:根据TNT2查出ordernum SELECT order_num FROM orderitems WHERE prod_id='TNT2'; *step2:根据ordernum查询出cust_id SELECT cust_id FROM orders WHERE order_num in ( SELECT order_num FROM orderitems WHERE prod_id='TNT2' ); *step3:根据cust_id查询出cust_name SELECT cust_id,cust_name FROM customers WHERE cust_id in ( SELECT cust_id FROM orders WHERE order_num in ( SELECT order_num FROM orderitems WHERE prod_id='TNT2' ) ); --显示的结果: +---------+----------------+ | cust_id | cust_name | +---------+----------------+ | 10001 | Coyote Inc. | | 10004 | Yosemite Place | +---------+----------------+
-
【例4】查询产品价格大于平均数的产品信息
--代码 SELECT * FROM products where prod_price > ( SELECT AVG(prod_price) FROM products ); --显示的结果 +---------+---------+--------------+------------+---------------------------------------+ | prod_id | vend_id | prod_name | prod_price | prod_desc | +---------+---------+--------------+------------+---------------------------------------+ | JP1000 | 1005 | JetPack 1000 | 35.00 | JetPack 1000, intended for single use | | JP2000 | 1005 | JetPack 2000 | 55.00 | JetPack 2000, multi-use | | SAFE | 1003 | Safe | 50.00 | Safe with combination lock | +---------+---------+--------------+------------+---------------------------------------+
自然连接
- 表名可以取别名
- 【例1】:显示商品id为'FC'的供应商名称
--代码 SELECT p.prod_id,v.vend_name FROM products p,vendors v WHERE p.vend_id = v.vend_id AND prod_id='FC'; --显示的结果 +---------+-----------+ | prod_id | vend_name | +---------+-----------+ | FC | ACME | +---------+-----------+
- 【例2】显示用户id为'10001',购买所有商品名,单价
--代码 SELECT c.cust_id,c.cust_name,p.prod_name,p.prod_price 单价,oi.order_item,(prod_price*order_item)单个商品总价 FROM customers c,orders o,orderitems oi,products p WHERE c.cust_id=o.cust_id AND o.order_num = oi.order_num AND oi.prod_id = p.prod_id HAVING c.cust_id=10001; --显示结果 +---------+-------------+----------------+--------+------------+--------------------+ | cust_id | cust_name | prod_name | 单价 | order_item | 单个商品总价 | +---------+-------------+----------------+--------+------------+--------------------+ | 10001 | Coyote Inc. | .5 ton anvil | 5.99 | 1 | 5.99 | | 10001 | Coyote Inc. | 1 ton anvil | 9.99 | 2 | 19.98 | | 10001 | Coyote Inc. | TNT (5 sticks) | 10.00 | 3 | 30.00 | | 10001 | Coyote Inc. | Bird seed | 10.00 | 4 | 40.00 | | 10001 | Coyote Inc. | Bird seed | 10.00 | 1 | 10.00 | | 10001 | Coyote Inc. | Oil can | 8.99 | 2 | 17.98 | | 10001 | Coyote Inc. | Sling | 4.49 | 3 | 13.47 | | 10001 | Coyote Inc. | 2 ton anvil | 14.99 | 4 | 59.96 | +---------+-------------+----------------+--------+------------+--------------------+
左连接&右外连接&内连接
- 左外连接(left join .. AND)&右外连接(right join .. AND)&内连接(inner join .. ON)
- 左外连接:左边的都显示,右边没有则显示NULL
- 右外连接(左外连接相反):右边都显示,左边没有则显示NULL
- 【例1】左连接:查询orderitems与items这两张表
--代码 SELECT orders.*,orderitems.* FROM orders LEFT JOIN orderitems ON orders.order_num = orderitems.order_num; --显示结果 +-----------+---------------------+---------+-----------+------------+---------+----------+------------+ | order_num | order_date | cust_id | order_num | order_item | prod_id | quantity | item_price | +-----------+---------------------+---------+-----------+------------+---------+----------+------------+ | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 1 | ANV01 | 10 | 5.99 | | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 2 | ANV02 | 3 | 9.99 | | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 3 | TNT2 | 5 | 10.00 | | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 4 | FB | 1 | 10.00 | | 20006 | 2005-09-12 00:00:00 | 10003 | 20006 | 1 | JP2000 | 1 | 55.00 | | 20007 | 2005-09-30 00:00:00 | 10004 | 20007 | 1 | TNT2 | 100 | 10.00 | | 20008 | 2005-10-03 00:00:00 | 10005 | 20008 | 1 | FC | 50 | 2.50 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 1 | FB | 1 | 10.00 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 2 | OL1 | 1 | 8.99 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 3 | SLING | 1 | 4.49 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 4 | ANV03 | 1 | 14.99 | +-----------+---------------------+---------+-----------+------------+---------+----------+------------+
- 【例2】内连接:查询orderitems与items这两张表
--代码 SELECT orders.*,orderitems.* FROM orders INNER JOIN orderitems ON orders.order_num = orderitems.order_num; --显示结果 +-----------+---------------------+---------+-----------+------------+---------+----------+------------+ | order_num | order_date | cust_id | order_num | order_item | prod_id | quantity | item_price | +-----------+---------------------+---------+-----------+------------+---------+----------+------------+ | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 1 | ANV01 | 10 | 5.99 | | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 2 | ANV02 | 3 | 9.99 | | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 3 | TNT2 | 5 | 10.00 | | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 4 | FB | 1 | 10.00 | | 20006 | 2005-09-12 00:00:00 | 10003 | 20006 | 1 | JP2000 | 1 | 55.00 | | 20007 | 2005-09-30 00:00:00 | 10004 | 20007 | 1 | TNT2 | 100 | 10.00 | | 20008 | 2005-10-03 00:00:00 | 10005 | 20008 | 1 | FC | 50 | 2.50 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 1 | FB | 1 | 10.00 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 2 | OL1 | 1 | 8.99 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 3 | SLING | 1 | 4.49 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 4 | ANV03 | 1 | 14.99 | +-----------+---------------------+---------+-----------+------------+---------+----------+------------+
- 【例3】右连接:查询orderitems与items这两张表
--代码 SELECT orders.*,orderitems.* FROM orders RIGHT JOIN orderitems ON orders.order_num = orderitems.order_num; --显示结果 +-----------+---------------------+---------+-----------+------------+---------+----------+------------+ | order_num | order_date | cust_id | order_num | order_item | prod_id | quantity | item_price | +-----------+---------------------+---------+-----------+------------+---------+----------+------------+ | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 1 | ANV01 | 10 | 5.99 | | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 2 | ANV02 | 3 | 9.99 | | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 3 | TNT2 | 5 | 10.00 | | 20005 | 2005-09-01 00:00:00 | 10001 | 20005 | 4 | FB | 1 | 10.00 | | 20006 | 2005-09-12 00:00:00 | 10003 | 20006 | 1 | JP2000 | 1 | 55.00 | | 20007 | 2005-09-30 00:00:00 | 10004 | 20007 | 1 | TNT2 | 100 | 10.00 | | 20008 | 2005-10-03 00:00:00 | 10005 | 20008 | 1 | FC | 50 | 2.50 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 1 | FB | 1 | 10.00 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 2 | OL1 | 1 | 8.99 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 3 | SLING | 1 | 4.49 | | 20009 | 2005-10-08 00:00:00 | 10001 | 20009 | 4 | ANV03 | 1 | 14.99 | +-----------+---------------------+---------+-----------+------------+---------+----------+------------+
自连接
- 自连接比子查询快得多
- 【例1】查询生产'OL1'的厂家还生产哪些商品
--代码 SELECT p1.vend_id,p1.prod_id FROM products p1,products p2 WHERE p1.vend_id = p2.vend_id AND p2.prod_id = 'OL1'; --显示结果 +---------+---------+ | vend_id | prod_id | +---------+---------+ | 1002 | FU1 | | 1002 | OL1 | +---------+---------+
组合查询 union [all] (行拼接)
- 只要数据类型一样即可,表名不同也可以;4
- 默认以第一条数据的列名为组合查询的列名
- union 默认自动去重复; union all 显示所有数据
--代码 SELECT * FROM products WHERE vend_id = 10001 UNION SELECT * FROM products WHERE prod_price >10; --显示的结果 +---------+---------+--------------+------------+----------------------------------------------------------------+ | prod_id | vend_id | prod_name | prod_price | prod_desc | +---------+---------+--------------+------------+----------------------------------------------------------------+ | ANV03 | 1001 | 2 ton anvil | 14.99 | 2 ton anvil, black, complete with handy hook and carrying case | | DTNTR | 1003 | Detonator | 13.00 | Detonator (plunger powered), fuses not included | | JP1000 | 1005 | JetPack 1000 | 35.00 | JetPack 1000, intended for single use | | JP2000 | 1005 | JetPack 2000 | 55.00 | JetPack 2000, multi-use | | SAFE | 1003 | Safe | 50.00 | Safe with combination lock | +---------+---------+--------------+------------+----------------------------------------------------------------+
SQL语句结构
DML语句(增删改查w)
-
查询
- SELECT *|column(s)|exp
FROM tablename
WHERER exp
GROUP BY ...
HAVING ...
ORDER BY ...
LIMIT m,n
- SELECT *|column(s)|exp
-
插入
- INSERT INTO tablename (columnname1,...,columnnameN) values (columnvalue1,...,columnvalueN),...
- (columnname1,...,columnname2)可以省略,但是建议写
-
删除(一):DELECT是要逐行删除表中数据.它只删除表内容,但不删除表本身.
- DELECT FROM tablename [ WHERE columnname=coluumnvalue ];
-
删除(二):TRUNCATE是删除整张表,重新创建一张新表.速度更快
- TRUNCATE tablename;
-
更新:
- UPDATE tablename SET (columnname1=value1,columnname2=value2,...) WHERE columnname=value;
-
查询结果插入到表中(插入查询的数据和表列名一致)
-
INSERT INTO tablename1 (SELECT column(s) FROM tablename2) WHERE exp;
- 【例】:
- CREATE TABLE vendors1 (vend_id int primary key,vend_name char(50),vend_address char(50));
--vendors1表结构 +--------------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------+----------+------+-----+---------+-------+ | vend_id | int(11) | NO | PRI | NULL | | | vend_name | char(50) | YES | | NULL | | | vend_address | char(50) | YES | | NULL | | +--------------+----------+------+-----+---------+-------+
- INSERT INTO vendors1(SELECT vend_id,vend_name,vend_address FROM vendors WHERE vend_id in (1001,1002));
+---------+-------------+-----------------+ | vend_id | vend_name | vend_address | +---------+-------------+-----------------+ | 1001 | Anvils R Us | 123 Main Street | | 1002 | LT Supplies | 500 Park Street | +---------+-------------+-----------------+
创建表和操纵管理
- comment 给表添加申明
- CREATE TABLE tablename (columnname1 columntype1 COMMENT alias,...) ;
- PRIMARY KEY 主键
- CREATE TABLE tablename (columnname1 columntype1 PRIMARY KEY ,...) ;
- NOT NULL 不为空
- CREATE TABLE tablename (columnname1 columntype1 NOT NULL ,...) ;
- AUTO_INCREMENT 自增
- CREATE TABLE tablename (columnname1 columntype1 AUTO_INCREMENT ,...) ;
- DEFAULT 默认值
- CREATE TABLE tablename (columnname1 columntype1 DEFAULT defaultValues ,...) ;
- ENUM 枚举类型
- CREATE TABLE tablename(columname1 ENUM('str1','str2'),...)
修改表 alter
- ADD 增加列
- ALTER TABLE tablename ADD(columnname1 columntype1 [COMMENT/PRIMARY KEY/NOT NULL/AUTO_INCREMENT/DEFAULT..],...)
--代码: ALTER TABLE vendors1 ADD tell int(20) DEFAULT 0000; --显示的结果: +--------------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------+----------+------+-----+---------+-------+ | vend_id | int(11) | NO | PRI | NULL | | | vend_name | char(50) | YES | | NULL | | | vend_address | char(50) | YES | | NULL | | | tell | int(20) | YES | | 0 | | +--------------+----------+------+-----+---------+-------+
* **modify 可以修改列的类型** 不会改变原来的值,只会改变修改后的值. * ALTER TABLE tablename **MODIFY**(columnname1 columntype1 [COMMENT/PRIMARY KEY/NOT NULL/AUTO_INCREMENT/DEFAULT..],...)
* **CHANGE 可以用来修改列名和类型** 不会改变原来的值,只会改变修改后的值. * change需要两个列名,后面的列名替换前面的列名 * ALTER TABLE tablename columname old-columnname new-columnname newtype;
删除列
- 删除某一列
- ALTER TABLE tablename DROP columnname;
添加列的限制
- 如果是单列直接在列后面添加限制
- CREATE TABLE tablename (columnname1 columntype1 PRIMARY KEY ,...) ;
- 如果是多列,例如增加主键
- PK_SC 主键
- CREATE TABLE tablename(columnname1 columntype1,..,PRIMARY KEY(columnname1 columntype1));
- 等于
- ALTER TABLE tablename ADD CONSTRAINT pk_sc PRIMARY KEY(columnname1,..);
- 添加外键
- FK_SC_表名 外键
- ALTER TABLE tablename1 ADD CONSTRAINT fk_sc_tablename2 FORGIN KEY(columnname) REFERENCES tablename2(tablename2);
- 添加唯一约束 UNIQUE
修改表名 rename
- 语法:
- RENAME TABLE old-tablename TO new-tablename;
DCL 给用户添加权限
创建新用户
- 创建连接数据库的权限
- CREATE USER '用户名' @'localhost'/IP地址 IDENTIFIED BY '密码'
销毁用户
- DROP USER '用户名'@'localhost'/IP地址
修改用户名密码
- SET PASSWORD FOR '用户名'@'localhost'/IP地址 = password('新密码');
授权
- 给用户授权
- GRANT [SELECT],[INSERT],[UPDATE],[DELETE],[CREATE],[ALTER],[DROP] ON [数据库名.表名]/[数据库名.*] to '用户名'@'localhost'/IP地址
- GRANT GRANT OPTION ON [数据库名.表名]/[数据库名.*] to '用户名'@'localhost'/IP地址
- 设置权限有效期
- GRANT ALL ON [数据库名.表名]/[数据库名.*] to '用户名'@'localhost'/IP地址
- 赋与全部权限
- 回收用户授权
- REVOKE [SELECT],[INSERT],[UPDATE],[DELETE],[CREATE],[ALTER],[DROP] ON [数据库名.表名]/[数据库名.*] FROM '用户名'@'localhost'/IP地址
- REVOKE ALL ON [数据库名.表名]/[数据库名.*] FROM '用户名'@'localhost'/IP地址
存储过程(存储过程是函数,存储过程名后需要有'()',括号里可以传递参数 )
- 概念:
- 存储过程是为了以后的使用而保存的一条或多条的MYSQL语句的结合
- 优点:
- 可以作为批文件,用于批处理。
- 通过复杂的SQL语句封装起来,方便使用.
- 统一使用统一存储过程,保证数据完整性和一致性.
- 为了安全性.如果表名、列名或业务逻辑等,只需要修改存储过程,而外部不知道里面变化。
- 存储过程比单个SQL语句要快。
- 可以用存储过程编写更强大,更灵活的SQL语句。
1.创建没有参数存储过程 PROCEDURE
- DELIMITER 把结束符';'转义
- DELIMITER $
CREATE PROCEDURE name() BEGIN SQL语句 END;
DELIMITER ;--代码 DELIMITER $ CREATE PROCEDURE product_sql() BEGIN SELECT prod_id,prod_name FROM products; END $ DELIMITER ;
2.调用过程 CALL
- 调用存储过程可以显示结果,也可以不显示结果
- CALL name (..)
--代码 CALL product_sql(); --显示的结果 +---------+----------------+ | prod_id | prod_name | +---------+----------------+ | ANV01 | .5 ton anvil | | ANV02 | 1 ton anvil | | ANV03 | 2 ton anvil | | DTNTR | Detonator | | FB | Bird seed | | FC | Carrots | | FU1 | Fuses | | JP1000 | JetPack 1000 | | JP2000 | JetPack 2000 | | OL1 | Oil can | | SAFE | Safe | | SLING | Sling | | TNT1 | TNT (1 stick) | | TNT2 | TNT (5 sticks) | +---------+----------------+
3.删除存储过程
- DROP PROCEDURE [IF EXISTS] name
--代码 DROP PROCEDURE IF EXISTS product_sql ;
有参数的存储过程 PROCEDURE
-
1.创建存储过程函数
- 创建最低价格,最高价格,平均价格的存储函数
--代码 DELIMITER $ CREATE PROCEDURE products_sql ( OUT min_prod DECIMAL(8,2), OUT max_prod DECIMAL(8,2), OUT avg_prod DECIMAL(8,2) ) BEGIN SELECT MIN(prod_price) INTO min_prod FROM products; SELECT MAX(prod_price) INTO max_prod FROM products; SELECT AVG(prod_price) INTO avg_prod FROM products; END $ DELIMITER ;
-
2.调用存储过程 CALL(@param1,@param2,..)
-
存储过程中调用的变量必须与创建时的变量一致,变量顺序可以不同
--代码 CALL products_sql(@max_prod,@avg_prod,@min_prod);
-
3.使用存储过程函数
--代码 SELECT @min_prod,@max_prod,@avg_prod ; --显示的结果 +-----------+-----------+-----------+ | @min_prod | @max_prod | @avg_prod | +-----------+-----------+-----------+ | 16.13 | 2.50 | 55.00 | +-----------+-----------+-----------+
存储过程中IN 和 OUT
- INTO的位置既可以在 SELECT exp之后,也可以是在WHERE之后
- 【例】:传入订单号并返回该订单总金额
- 1.创建存储过程函数
--代码: DELIMITER $ CREATE PROCEDURE order_sql ( IN ordernum INT, OUT sum_order DECIMAL(8,2) ) BEGIN SELECT SUM(item_price*quantity) FROM orderitems WHERE order_num = ordernum INTO sum_order; END $ DELIMITER ;
- 2.调用存储过程函数
- 注意此处ordernum需要传入值,而不是变量@param
--代码: CALL order_sql(20005,@sum_order);
- 3.使用存储过程函数
--代码: SELECT @sum_order; --显示的结果 +------------+ | @sum_order | +------------+ | 149.87 | +------------+
显示存储过程结构
- 显示某个存储过程详细信息
- SHOW CREATE PROCEDURE 存储过程名;
--代码 SHOW CREATE PROCEDURE order_sql; --显示的结果 --------------------------------------------------------+----------------------+----------------------+--------------------+ | Procedure | sql_mode | Create Procedure | character_set_client | collation_connection | Database Collation |
获得详细信息的存储过程
- SHOW PROCEDURE STATUS
--显示的结果
+---------+----------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------
| Db | Name | Type | Definer | Modified | Created | Security_type | Comment | character_set_client | collation_connection |
+---------+----------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------
| ceshi80 | ordertotal | PROCEDURE | root@localhost | 2018-10-17 11:45:00 | 2018-10-17 11:45:00 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci |
| ceshi80 | order_sql | PROCEDURE | root@localhost | 2018-10-16 17:03:53 | 2018-10-16 17:03:53 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci |
| ceshi80 | order_sql1 | PROCEDURE | root@localhost | 2018-10-16 16:52:50 | 2018-10-16 16:52:50 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci |
| ceshi80 | proceorders | PROCEDURE | root@localhost | 2018-10-17 09:40:56 | 2018-10-17 09:40:56 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci |
| ceshi80 | proceorders2 | PROCEDURE | root@localhost | 2018-10-17 10:36:11 | 2018-10-17 10:36:11 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci |
| ceshi80 | processorders3 | PROCEDURE | root@localhost | 2018-10-17 11:58:00 | 2018-10-17 11:58:00 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci |
| ceshi80 | products_sql | PROCEDURE | root@localhost | 2018-10-16 16:08:10 | 2018-10-16 16:08:10 | DEFINER | | utf8 | utf8_general_ci | utf8_general_ci |
+---------+----------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------
- 可以加'like',限制输出结果
游标
- 概念:
- 游标:是一个存储在MYSQL服务器上的数据库查询,它不是一条SELECT语句,而是被该语句检索出来的结果集.在存储游标以后,可以滚动和浏览其中的数据.
- 【TIPS】:游标只能用于存储过程
游标的过程
-
游标关闭后可以重新打开;如果不手动关闭,SQL语句遇到END会自动关闭.
-
步骤
-
1.创建游标 + 打开游标
- a.创建游标
- CREATE PROCEDURE 存储过程名()
BEGIN
DECLARE 游标名 CURSOR
FOR
SQL语句
END;
- CREATE PROCEDURE 存储过程名()
- b.打开和关闭游标
- OPEN/CLOSE 游标名
-- 代码 DELIMITER $ CREATE PROCEDURE proceorders() BEGIN -- 创建游标 DECLARE ordernum CURSOR FOR SELECT order_num FROM orders; -- 打开游标 OPEN ordernum; -- 关闭游标 CLOSE ordernum; END $ DELIMITER ;
- a.创建游标
-
2.用游标把数据检索出来
- FETCH: 用于检索数据并存储起来
- REPEAT: 对游标进行循环
- FETCH如果在REPEAT内,FETCH会反复执行直到done为真
REPEAT FETCH ... UTIL done END REPEAT
-
2.1 如何使done设置为真?
- 当SQLSTATE 'xxx'出现时,done设置为1;
- 当SQLSTATE 'xxx'没有出现时,当REPEAT循环结束后退出.
DECLARE CONTINUE HANDLER FOR SQLSTATE 'XXX' set done=1;
* DECLARE语句时有先后顺序 * 局部变量 --> 游标 --> 句柄 * CONTINUE HANDLER:是指条件出现时被执行的代码 * 【例】:循环检索直至最后一行 ``` -- 步骤: -- 1.首先定义变量和CONTINUE HANDLER 2.然后定义并打开游标,重复读取所有行 3.最后关闭游标 --代码 DELIMITER $ CREATE PROCEDURE proceorders2() BEGIN -- 申明变量 DECLARE done BOOLEAN DEFAULT 0; DECLARE o INT;
-- 创建游标
DECLARE ordernumbers CURSOR
FOR
SELECT order_num FROM orders;
-- 限制条件
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
-- 打开光标
OPEN ordernumbers;
-- 循环语句
REPEAT
-- 检索的数据并存储起来
FETCH ordernumbers INTO o;
UNTIL done END REPEAT;
-- 关闭光标
CLOSE ordernumbers;
END $
DELIMITER ;
```
游标的综合示例:
- 下面的例子包含:存储过程 + 游标 + 逐行处理 + 存储过程调用其他存储过程
--代码 -- 1.创建存储过程函数 DELIMITER $ CREATE PROCEDURE ordertotal ( IN ordernum INT, OUT sum_order DECIMAL(8,2) ) BEGIN SELECT SUM(item_price*quantity) FROM orderitems WHERE order_num = ordernum INTO sum_order; END $ -- 2.把游标数据存储在新建表中 CREATE PROCEDURE processorders3() BEGIN -- 申明变量$ DECLARE done BOOLEAN DEFAULT 0; DECLARE o INT; DECLARE t DECIMAL(8,2); -- 创建游标 DECLARE ordernumbers CURSOR FOR SELECT order_num FROM orders; -- 限制条件 DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; -- 创建存储的表 CREATE TABLE IF NOT EXISTS order_total (order_num INT,total DECIMAL(8,2)); -- 打开光标 OPEN ordernumbers; -- 循环语句 REPEAT -- 检索数据并存储起来 FETCH ordernumbers INTO o; -- 调用存储过程 CALL ordertotal(o,t); -- 在创建的表插入数据 INSERT INTO order_total (order_num,total) VALUES(o,t); UNTIL done END REPEAT; -- 关闭光标 CLOSE ordernumbers; END $ DELIMITER ; -- 3.调用存储过程函数 CALL processorders3(); -- 4.查询创建的存储表 SELECT * FROM order_total; -- 显示的结果 +-----------+---------+ | order_num | total | +-----------+---------+ | 20005 | 149.87 | | 20009 | 38.47 | | 20006 | 55.00 | | 20007 | 1000.00 | | 20008 | 125.00 | | 20008 | 125.00 | +-----------+---------+
事务管理
- 当SAVEPOINT、COMMIT或ROOLBACK执行之后,事务自动关闭.
- 【tips】:每种数据库引擎对事物支持的都不一样,InnoDB支持明确的事物处理引擎.
- 事务管理的目的:
- 可以用来维护数据库的完整性.
- 事务关键字:
- START TRANSACTION 开启事务
- ROLLBACK 回滚
- COMMIT 提交
- SAVEPOINT 保存点.回退部分事物处理.
ROLLBACK
- 格式:
START TRANSACTION;
...
ROLLBACK;
COMMIT
- 事物代码块语句都执行成功,才执行commit操作
- 格式:
START TARANSACTION;
...
COMMIT;
SAVEPOINT
- savepoint越多越好,因为可以灵活的回退
-- 创建保留点
SAVEPOINT '保留点名称';
-- 事物回滚到保留点
ROLLBACK TO '保留点名称';
-- 事物处理完,保留点会被自动释放.也可以手动释放,如下:
RELEASE SAVEPOINT
SQL阶段学习的练习集
- 习题+答案 的下载地址,【提取码:fk83】