
select name from student; //检索单个列
select * from student; //检索整个表格
select name, id from student; //选择多行
select distinct city from student; //只返回city中不同的行
select name from student limit 5; //返回从头开始的5行
select name from student limit 5,3;//返回从第5行开始的3行
select student.name from student; //使用完全限定的表名
select name from student order by name; //以name列的字母排序
select id, name from student order by name, id desc; //选择多列,首先按照name,再按照id排序
select name from student order by name desc; //以name列的字母降序排列
select id, name from student order by name desc, id; // 对name列降序,id升序
select id, name from student order by name desc, id
limit 1;//配合limit筛选最大值和最小值
降序 desc,升序asc。
order by一般是最后的,除了limit
select * from student where city = "杭州"; //注意杭州是字符串需要加引号
select * from student where id > 5; //检测多个值
select * from student where city != '杭州';
select * from student where city is NULL;
Where子句的位置应该在order之前,否则会出错。
select * from student where city != '河南' and city != '安徽';
select * from student where city = '河南' or city = '安徽';
select * from student where city in ('河南','安徽'); # 列表的值统一或者兼容
select * from student where city not in ('河南','安徽');
select * from student where id between 100 and 200;
select * from student where city like '杭%'; #匹配前面
select * from student where address like '%隔壁'; #匹配后面
select * from student where address like '___隔壁';
select * from student where address like '_\__隔壁';
%
匹配不限字符数,通过_
匹配,限定单个字符数。escape $
或者\$
转义符号。NULL
匹配。select last_name from employee where commission_pct IS / IS NOT NULL;
IS
只能判断NULL
IFNULL(commission, 0)
如果奖金为NULL,用0替代expression IS NULL
expression IS NOT NULL
select concat(city,' ',address) from student;
RTrim
和LTrim
处理所选列的左右空格。
ISNULL(exp1,exp2)
。select concat(city,' ',RTrim(address)) as newtitle from student;
as
给拼接字段的列起一个新的名字。
LIMIT row_count OFFSET offset;
SELECT DISTINCT department_id FROM employees;
DISTINCT
遇到 NULL
值时,只保留一个 NULL
值。因为 DISTINCT
认为所有的 NULL
值都是相同的,这与字段的类型无关。正则表达式是用来匹配文本的特殊的串(字符集合) ,用正则表达式语言来建立。
所有种类的程序设计语言、文本编辑器、操作系统等都支持正则表达式。
MySQL仅支持多数正则表达式实现的一个很小的子集。
select * from student where city regexp '州';
select * from student where city like '州';
# 对比like和正则表达式,regexp匹配的是包含关系
select * from student where city regexp '10|20';
select * from student where city regexp '河|安|州';
select * from student where city regexp [123]; # '1|2|3'
select * from student where city regexp '[1-5] Ton'; # 匹配 1 Ton, 2 Ton,3 Ton...
select * from student where city regexp '[a-c] Ton'; # 匹配 a Ton, b Ton,c Ton...
select * from student where city regexp '\\.'
select * from student where city regexp '\\f'
\\f 换页
\\n 换行
\\r 回车
\\t 制表
\\v 纵向制表
\\ 转义符号
[:alnum:] 任意字母和数字(同[a-zA-Z0-9])
[:alpha:] 任意字符(同[a-zA-Z])
[:blank:] 空格和制表(同[\\t])
[:cntr1:] ASCII控制字符(ASCII到31和127)
[:digit:] 任意数字(同[0-9])
[:graph:] 与[:print:]相同,但不包括空格
[:lower: 任意小写字母(同[a-z])
[:print:] 任意可打印字符
[:punct:] 既不在[:alnum:]又不在[:cntr1:]中的任意字符
[:space:] 包括空格在内的任意空白字符(同[\\fl\nl\rlltllv])
[:upper:] 任意大写字母(同[A-Z])
[:xdigit:] 任意十六进制数字(同[a-fA-F0-9])
等值查询,必须满足关键字相同
用于将数据库中的两个表或者多个表组合起来。
一般用左连接,显示一些右表NULL值的情况
两端查询中间加一个UNION
关键词,合并两次结果值。
UNION
运算包括 UNION DISTINCT
和 UNION ALL
两种算法,其中 UNION DISTINCT
可以简写为 UNION
。UNION
运算的结果进行排序时,最需要在 SQL 语句的最后添加 ORDER BY
子句。UNION
运算的结果集只要列数一样就可以。返回结果集的列名采用第一个结果集的列名。INSERT
语句用于将一行或者多行数据插入到数据表中。
INSERT INTO table_name (column_1, column_2, ...)
VALUES (value_1, value_2, ...);
INSERT INTO table_name (column_1, column_2, ...)
VALUES (value_11, value_12, ...),
(value_21, value_22, ...)
...;
IGNORE
标识符。insert into invoices_archive
select *
from invoices
where payment_date IS NOT NULL;
# 直接筛选好合适的数据后,新建表格
create table invoices_archive as
select
c.name,
ia.payment_date
from invoices_archive ia
join clients c
using (client_id)
update invoices
set payment_total = 10, payment_date = '2019-03-01'
where invoice_id = 1
update customers
set points = points + 50
where birth_date < '1990-01-01'
# 更新多行数据,需要关闭安全模式
# 使用子查询
update orders
set comments = '金牌客户'
where customer_id IN (
select customer_id
from customers
where points > 3000
)
delete from orders # 删除全部
where invoice_id = 1
LIMIT
子句和 ORDER BY
子句select
customer_id,
first_name,
last_name
from customers
where customer_id IN(
select o.customer_id
from order_items oi
JOIN orders o using(order_id)
where product_id = 3
);
select
DISTINCT customer_id,
first_name,
last_name
from customers c
join orders o
using (customer_id)
join order_items oi
using (order_id)
where oi.product_id = 3
使用ALL关键字,比较子查询返回的多个值
select *
from invoices i
where invoice_total > (
select AVG(invoice_total)
from invoices
where client_id = i.client_id
)
如果IN运算符后写的子查询生成了大量的结果集,EXISTS效率更高,他没有生成大量的结果集。
select *
from products p
where not EXISTS(
select product_id
from order_items o
where p.product_id = o.product_id
)
select *
from products
where product_id NOT IN(
select product_id
from order_items
)
select
client_id,
name,
(select sum(invoice_total)
from invoices i
where c.client_id = i.client_id) as total_sales,
(select AVG(invoice_total) from invoices) as avg,
(select total_sales - avg) as difference
from clients c
select *
from(
select
client_id,
name,
(select sum(invoice_total)
from invoices i
where c.client_id = i.client_id) as total_sales,
(select AVG(invoice_total) from invoices) as avg,
(select total_sales - avg) as difference
from clients c
) as sales
where total_sales IS NOT NULL
create view sales_by_client as
select
concat(first_name, ' ',last_name) as name,
points,
case
when points > 3000 then 'gold'
when points < 3000 and points > 2000 then 'silver'
else 'bronze'
end as member
from customers
drop view clients_balance
存储过程的主要作用如下:
delimiter $$
create procedure get_invpoces(id int)
begin
select * from invoices as i
where i.client_id = id;
end $$
call get_clients_by_state('CA')
DELIMITER $$
CREATE TRIGGER payments_after_delete
AFTER DELETE ON payments
FOR EACH ROW
BEGIN
UPDATE invoices SET payment_total = payment_total - old.amount
WHERE invoice_id = old.invoice_id;
END $$
DELIMITER ;
show triggers
show triggers like 'payments%'
-- 一般的命名方式:table_after_insert
-- delete
drop triggers if exists table_after_insert
show variables
set global event_scheduler = OFF
DELIMITER $$
create event yearly_delete_stale_audit_rows
on schedule
-- AT '2019-05-01'
every 1 year starts '2019-01-01' ENDs '2029-01-01'
DO begin
delete from payments_audit
where action_date < now - INTERVAL 1 YEAR;
END $$
DELIMITER ;
show events;
show events like 'yearly%';
drop event if exists ___;
-- modifiy
alter event year_delete_stale_audit_row enable;
START TRANSACTION;
insert into orders (customers_id, order_date, status)
values(1, '2019-01-01',1);
INSERT INTO order_items
VALUES(last_insert_id(), 1, 1, 1);
COMMIT;
-- rollback;
SHOW VARIABLES LIKE 'transaction_isolation';
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
USE sql_store;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT points
FROM customers
WHERE customer_id = 1;
USE sql_store;
START TRANSACTION;
UPDATE customers
SET points = 20
WHERE customer_id = 1;
COMMIT;
USE sql_store;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT points FROM customers WHERE customer_id = 1;
SELECT points FROM customers WHERE customer_id = 1;
COMMIT;
USE sql_store;
START TRANSACTION;
UPDATE customers
SET points 30
WHERE customer id 1;
COMMIT
USE sql_store;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT points FROM customers WHERE customer_id = 1;
SELECT points FROM customers WHERE customer_id = 1;
COMMIT;
USE sql_store;
START TRANSACTION;
UPDATE customers
SET points = 30
WHERE customer_id = 1;
COMMIT;
USE sql_store;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
SELECT * FROM customers WHERE state = 'VA';
COMMIT;
USE sql_store;
START TRANSACTION;
UPDATE customers
SET state = 'VA'
WHERE customer_id = 4;
COMMIT
CHAR(X) | fixed-length |
---|---|
VARCHAR(X) | max:65535 |
MEDIUMTEXT | max:16MB |
LONGTEXT | max:4GB |
CHAR
数据类型采用固定的长度进行存储,因此 CHAR
的性能要比 VARCHAR
更好TINYINT | [-128,127] |
---|---|
UNSIGNED TINYINT | [0, 255] |
ZEROFILL | INT(4), 1 -> 0001 |
AUTO_INCREMENT
作为主键列。DECIMAL(p, s)
ENUM
它不是 SQL 标准的,因此,移植到其他 RDBMS 可能是一个问题。orders
表中的状态枚举值,不能重用到新建的其他表上。DATE_FORMAT()
函数DATEDIFF()
按如下方式使用该函数DATE_ADD()
函数用于将天数、周数、月数、年数等添加到给定的日期值DATE_SUB()
被用于从日期中减去一个时间间隔BIT(M)
允许存储 M
位值。 M
的取值范围是 1
到 64
。M
,那么它的默认值为 1
。 BIT
等效于 BIT(1)
。BIT
列非常适合用来存储状态值。b'01'
B'01'
0b01
TINYBLOB | 255b |
---|---|
BLOB | 65KB |
MEDIUMBLOB | 16MB |
LONGBLOB | 4GB |
-- 添加JSON
UPDATE products
SET properties = '
{
"dimensions": [1, 2, 3],
"weight": 10,
"manufacturer": {"name": "sony"}
}
'
where product_id = 1
SET properties = JSON_OBJECT(
'weight', 10,
'dimensions', JSON_ARRAY(1,2,3),
'manufacturer', JSON_OBJECT('name', 'sony')
)
-- 查询JSON
SELECT product_id, JSON_EXTRACT(properties, '$.weight') AS weight
FROM products
WHERE product_id = 1;
SELECT product_id, properties -> '$.weight'
-- 更新JSON属性,或者添加新的属性
UPDATE products
SET properties = JSON_SET(
properties,
'$.weight', 20
'$.age', 10
)
WHERE product_id = 1;
-- 删除JSON
UPDATE products
SET properties = JSON_REMOVE(
properties,
'$.age'
)
WHERE product_id = 1;
fk_子表_父表
的方式命名,名称后可能有数字,是MySQL为了防止外键与其他外键重名自动添加的,这里没必要,可去掉。使用索引来加快检索速度,索引就像是字典中的目录。
索引是一种数据结构,例如、B-Tree,它提高了从表中检索数据行的速度,但需要额外的写入和存储来维护它。
当使用主键 或唯一键创建表时,MySQL 会自动创建一个名为 PRIMARY 的索引。 该索引称为聚集索引。
PRIMARY
索引是特殊的,因为索引本身与数据一起存储在同一个表中。聚集索引强制执行表中行的顺序。PRIMARY
索引以外的其他索引称为二级索引或非聚集索引。聚簇索引和非聚簇索引
create index idx_state on customers (state);
explain select customer_id from customers where state = 'CA'
show indexes in customers;
analyze table customers;
drop index index_name on table_name
USE INDEX
,建议优化器去使用指定的命名索引。FORCE INDEX
。MySQL SHOW INDEXES
语句返回的 Cardinality
列中值是索引基数。索引基数是 MySQL 查询优化器决定是否使用索引的一个重要依据。
每一个索引都有对应的索引基础,决定了优化器使用这个索引的优先级。
比如每个表中自动创建的PRIMARY索引,可以加快从表中检索数据的速度,还可以防止在指定的一个或者多个列中出现重复值。
create unique index on table_name(index_)//创建唯一索引
create index idx_lastname on customers (last_name(20))
SELECT
COUNT (DISTINCT LEFT (Last name,1)),
COUNT(DISTINCT LEFT(last_name,5)),
COUNT(DISTINCT LEFT (Last_name,10))
FROM customers;
确定前缀长度时, 应该尽量让字符串前缀保持唯一性。 唯一性越强,则索引的效率越高。
使用前缀索引,可以减少内存的消耗。
CREATE FULLTEXT INDEX idx_title_body ON posts (title,body);
CREATE FULLTEXT INDEX idx_title_body ON posts (title,body);
create index idx_state_points on customers (state, points)
设计好的索引,可以用于筛选数据和排序数据。
select concat(city,' ',RTrim(address)) as newtitle from student;
# RTrim() / LTrim() 去除左边右边空格
select trim('a' from 'aaabbaa') as out put;
# 去除前后的字符
select city, upper(address) as newaddress from student;
# Upper() / Lower()文本大小写转换
Left() / Right()
# 返回串左边 / 右边的字符
Length()
# 返回串的字节个数,需要考虑不同的字符集
Locate()
# 找出串的一个字串
Soundex()
# 返回串的SOUNDEX值
# 将任何文本串转换为描述其语音表示的字母数字模式的算法
SubString() / substr()
# 返回子串的字符
concat(str1, str2,str3)
# 拼接字符串
instr()
# 返回子串第一次出现的位置
lpad() / rpad()
# 用指定的字符,左填充到指定数量的字符数
replace()
# 字符串替换
AddDate() 增加一个日期(天、周等)
AddTime() 增加一个时间(时、分等)
CurDate() 返回当前日期
CurTime() 返回当前时间
Date() 返回日期时间的日期部分
DateDiff() 计算两个日期之差
Date_Add() 高度灵活的日期运算函数
Date_Format() 返回一个格式化的日期或时间串
Day() 返回一个日期的天数部分
Dayofweek() 对于一个日期,返回对应的星期几
Hour() 返回一个时间的小时部分
Minute() 返回一个时间的分钟部分
Month() 返回一个日期的月份部分
NowC() 返回当前日期和时间
Second() 返回一个时间的秒部分
Time() 返回一个日期时间的时间部分
Year() 返回一个日期的年份部分
str_to_date 将日期格式的字符转换成指定格式的日期
str_to_date('9-13-1999','%m-%d-%Y')
date_format 将日期转换为字符
date_format(now(), '%y年%m月%d日') as out_put
对于datatime的数据类型存储日期以及时间值,样例表中的值全具有时间值
00::00::00
,当我们直接使用where order_date = '2005-09-01';
,与实际存储的where order_data = '2005-09-01 11::30::14
冲突,应该用where date(order_date) = '2005-09-01'
。
where date(order_date) between '2005-09-01' and '2005-10-01';
round(X,2) 四舍五入
ceil() 向上取整
floor()向下取整
truncate() 截断
mod() 取余 a -a/b*b
Abs() 返回一个数的绝对值
Cos() 返回一个角度的余弦
Exp() 返回一个数的指数值
Mod() 返回除操作的余数
Pi() 返回圆周率
Rand() 返回一个随机数
Sin() 返回一个角度的正弦
Sqrt() 返回一个数的平方根
Tan() 返回一个角度的正切
运行在行组上,计算和返回单个值得函数。
select AVG(id) as avg_id from student;
select AVG(id) as avg_id from student where city = '杭州';
select count(*) as count_id from student;
select count(city) from student;
select max(id) from student;
select min(id) from student;
如果有多行结果时,MAX返回最后一行的,MIN返回最前面的行。
select sum(id) from student;
IF(expression, first, second)
select
concat(first_name, ' ',last_name) as name,
points,
case
when points > 3000 then 'gold'
when points < 3000 and points > 2000 then 'silver'
else 'bronze'
end as member
from customers
select version();
select datebase();
select user();