好久没用 sql ,都忘得干干净净,翻阅以前的学习笔记,觉得有些可记录的点,放在这里以便备用查阅
mac 安装 MySQL
brew install mysql

# 启动
mysql.server start
#登录
mysql -uroot
# 例子
mysql -u root -p 123456 -h 127.0.0.1
命令后面加上分号
show tables;
desc tableName;
show create table tableName;
create table tbName (
列名称 1 列类型 [列参数] [not null default ],
列名称 N 列类型 [列参数] [not null default ]
) engine myisam/innodb charset utf8/gbk
例子
create table user (
id int auto_increment,
name varchar(20) not null default '',
age tinyint unsigned not null default 0,
index id (id)
)engine=innodb charset=utf8;
# 注:innodb 是表引擎,也可以是 myisam 或其他,但最常用的是 myisam 和 innodb,
# charset 常用的有 utf8,gbk;
3.5.1 修改表之增加列
alter table tbName add 列名称1 列类型 [列参数] [not null default ]
#(add 之后的旧列名之后的语法和创建表时的列声明一样)
3.5.2 修改表之修改列
alter table tbName change 旧列名 新列名 列类型 [列参数] [not null default ]
# (注:旧列名之后的语法和创建表时的列声明一样)
3.5.3 修改表之减少列
alter table tbName drop 列名称;
3.5.4 修改表之增加主键
alter table tbName add primary key(主键所在列名);
例: alter table goods add primary key(id) 该例是把主键建立在 id 列上
3.5.5 修改表之删除主键
alter table tbName drop primary key;
3.5.6 修改表之增加索引
alter table tbName add [unique|fulltext] index 索引名(列名);
3.5.7 修改表之删除索引
alter table tbName drop index 索引名;
3.5.8 清空表的数据
truncate tableName;
参数解释
unsigned 无符号(不能为负) zerofill 0 填充 M 填充后的宽度
tinyint unsigned;
tinyint(6) zerofill;
| 列 | 实存字符 i | 实占空间 | 利用率 |
|---|---|---|---|
| char(M) | 0<=i<=M | M | i/m<=100% |
| varchar(M) | 0<=i<=M | i+1,2 | i/i+1/2<100% |
特性:不用赋值,该列会为自己赋当前的具体时间
insert into 表名(col1,col2,……) values(val1,val2……); # -- 插入指定列
insert into 表名 values (,,,,); # -- 插入所有列
insert into 表名 values# -- 一次插入多行
(val1,val2……),
(val1,val2……),
(val1,val2……);
update tablename
set
col1=newval1,
col2=newval2,
...
...
colN=newvalN
where 条件;
delete from tablenaeme where 条件;
.. left join .. on
table A left join table B on tableA.col1 = tableB.col2 ;
例句:
select 列名 from table A left join table B on tableA.col1 = tableB.col2
right join
inner join
where 型子查询:内层 sql 的返回值在 where 后作为条件表达式的一部分
# 例句: select * from tableA where colA = (select colB from tableB where ...);
from 型子查询:内层 sql 查询结果,作为一张表,供外层的 sql 语句再次查询
例句:select * from (select * from ...) as tableName where ....
存储引擎 engine=1\2
事务
触发器
创建触发器语法
create trigger tgName
after/before insert/delete/update
on tableName
for each row
sql; # -- 触发语句
drop trigger tgName;
索引
索引类型
综合练习:
商品表:goods
栏目表:category
建表完成后,作以下操作:
对 goods 表插入以下数据:
+----------+------------------------------+--------+----------+-----------+--------------+------------+-------------+
| goods_id | goods_name | cat_id | brand_id | goods_sn | goods_number | shop_price | click_count |
+----------+------------------------------+--------+----------+-----------+--------------+------------+-------------+
| 1 | KD876 | 4 | 8 | ECS000000 | 10 | 1388.00 | 7 |
| 4 | 诺基亚 N85 原装充电器 | 8 | 1 | ECS000004 | 17 | 58.00 | 0 |
| 3 | 诺基亚原装 5800 耳机 | 8 | 1 | ECS000002 | 24 | 68.00 | 3 |
| 5 | 索爱原装 M2 卡读卡器 | 11 | 7 | ECS000005 | 8 | 20.00 | 3 |
| 6 | 胜创 KINGMAX 内存卡 | 11 | 0 | ECS000006 | 15 | 42.00 | 0 |
| 7 | 诺基亚 N85 原装立体声耳机 HS-82 | 8 | 1 | ECS000007 | 20 | 100.00 | 0 |
| 8 | 飞利浦 9@9v | 3 | 4 | ECS000008 | 17 | 399.00 | 9 |
| 9 | 诺基亚 E66 | 3 | 1 | ECS000009 | 13 | 2298.00 | 20 |
| 10 | 索爱 C702c | 3 | 7 | ECS000010 | 7 | 1328.00 | 11 |
| 11 | 索爱 C702c | 3 | 7 | ECS000011 | 1 | 1300.00 | 0 |
| 12 | 摩托罗拉 A810 | 3 | 2 | ECS000012 | 8 | 983.00 | 14 |
| 13 | 诺基亚 5320 XpressMusic | 3 | 1 | ECS000013 | 8 | 1311.00 | 13 |
| 14 | 诺基亚 5800XM | 4 | 1 | ECS000014 | 4 | 2625.00 | 6 |
| 15 | 摩托罗拉 A810 | 3 | 2 | ECS000015 | 3 | 788.00 | 8 |
| 16 | 恒基伟业 G101 | 2 | 11 | ECS000016 | 0 | 823.33 | 3 |
| 17 | 夏新 N7 | 3 | 5 | ECS000017 | 1 | 2300.00 | 2 |
| 18 | 夏新 T5 | 4 | 5 | ECS000018 | 1 | 2878.00 | 0 |
| 19 | 三星 SGH-F258 | 3 | 6 | ECS000019 | 0 | 858.00 | 7 |
| 20 | 三星 BC01 | 3 | 6 | ECS000020 | 13 | 280.00 | 14 |
| 21 | 金立 A30 | 3 | 10 | ECS000021 | 40 | 2000.00 | 4 |
| 22 | 多普达 Touch HD | 3 | 3 | ECS000022 | 0 | 5999.00 | 15 |
| 23 | 诺基亚 N96 | 5 | 1 | ECS000023 | 8 | 3700.00 | 17 |
| 24 | P806 | 3 | 9 | ECS000024 | 148 | 2000.00 | 36 |
| 25 | 小灵通/固话 50 元充值卡 | 13 | 0 | ECS000025 | 2 | 48.00 | 0 |
| 26 | 小灵通/固话 20 元充值卡 | 13 | 0 | ECS000026 | 2 | 19.00 | 0 |
| 27 | 联通 100 元充值卡 | 15 | 0 | ECS000027 | 2 | 95.00 | 0 |
| 28 | 联通 50 元充值卡 | 15 | 0 | ECS000028 | 0 | 45.00 | 0 |
| 29 | 移动 100 元充值卡 | 14 | 0 | ECS000029 | 0 | 90.00 | 0 |
| 30 | 移动 20 元充值卡 | 14 | 0 | ECS000030 | 9 | 18.00 | 1 |
| 31 | 摩托罗拉 E8 | 3 | 2 | ECS000031 | 1 | 1337.00 | 5 |
| 32 | 诺基亚 N85 | 3 | 1 | ECS000032 | 1 | 3010.00 | 9 |
+----------+------------------------------+--------+----------+-----------+--------------+------------+-------------+
注:以下查询基于 ecshop 网站的商品表( ecs_goods )
在练习时可以只取部分列,方便查看.
查出满足以下条件的商品
select goods_id,goods_name,shop_price
from ecs_goods
where goods_id=32;
select goods_id,cat_id,goods_name,shop_price from ecs_goods
where cat_id!=3;
select goods_id,cat_id,goods_name,shop_price from ecs_goods
where shop_price >3000;
select goods_id,cat_id,goods_name,shop_price from ecs_goods where shop_price <=100;
select goods_id,cat_id,goods_name,shop_price from ecs_goods
where cat_id in (4,11);
select goods_id,cat_id,goods_name,shop_price from ecs_goods
where shop_price between 100 and 500;
select goods_id,cat_id,goods_name,shop_price from ecs_goods where cat_id!=3 and cat_id!=11;
select goods_id,cat_id,goods_name,shop_price from ecs_goods where cat_id not in (3,11);
select goods_id,cat_id,goods_name,shop_price from ecs_goods where shop_price>100 and shop_price <300 or shop_price >4000 and shop_price <5000;
select goods_id,cat_id,goods_name,shop_price,click_count from ecs_goods where
cat_id=3 and (shop_price <1000 or shop_price>3000) and click_count>5;
select goods_id,cat_id,goods_name,shop_price,click_count from ecs_goods
where cat_id in (2,3,4,5);
select goods_id,cat_id,goods_name,shop_price from ecs_goods where goods_name like '诺基亚%';
select goods_id,cat_id,goods_name,shop_price from ecs_goods
where goods_name like '诺基亚 N__';
select goods_id,cat_id,goods_name,shop_price from ecs_goos
where goods_name not like '诺基亚%';
select goods_id,cat_id,goods_name,shop_price from ecs_goods where
cat_id=3 and shop_price>1000 and shop_price <3000 and click_count>5 and goods_name like '诺基亚%';
select goods_id,cat_id,goods_name,shop_price from ecs_goods where
shop_price between 1000 and 3000 and cat_id=3 and click_count>5 and goods_name like '诺基亚%';
有如下表和数组
+------+
| num |
+------+
| 3 |
| 12 |
| 15 |
| 25 |
| 23 |
| 29 |
| 34 |
| 37 |
| 32 |
| 45 |
| 48 |
| 52 |
+------+
把 good 表中商品名为’诺基亚 xxxx’的商品,改为’HTCxxxx’,
select max(shop_price) from ecs_goods;
select max(goods_id) from ecs_goods;
select min(shop_price) from ecs_goods;
select min(goods_id) from ecs_goods;
select sum(goods_number) from ecs_goods;
select avg(shop_price) from ecs_goods;
select count(*) from ecs_goods;
提示:( 5 个聚合函数, sum , avg , max , min , count 与 group 综合运用)
select cat_id,max(shop_price) from ecs_goods group by cat_id;
select goods_id,goods_name,market_price-shop_price as j
from ecs_goods ;
select goods_id,goods_name,goods_number*shop_price from ecs_goods
select sum(goods_number*shop_price) from ecs_goods;
select cat_id,sum(goods_number*shop_price) as k from ecs_goods group by cat_id;
select goods_id,goods_name,market_price-shop_price as k from ecs_goods
where market_price-shop_price >200;
select goods_id,goods_name,market_price-shop_price as k from ecs_goods
having k >200;
select cat_id,sum(goods_number*shop_price) as k from ecs_goods group by cat_id
having k>20000
有如下表及数据
+------+---------+-------+
| name | subject | score |
+------+---------+-------+
| 张三 | 数学 | 90 |
| 张三 | 语文 | 50 |
| 张三 | 地理 | 40 |
| 李四 | 语文 | 55 |
| 李四 | 政治 | 45 |
| 王五 | 政治 | 30 |
+------+---------+-------+
要求:查询出 2 门及 2 门以上不及格者的平均成绩
先查看每个人的平均成绩
mysql> select name,avg(score) from stu group by name;
+------+------------+
| name | avg(score) |
+------+------------+
| 张三 | 60.0000 |
| 李四 | 50.0000 |
| 王五 | 30.0000 |
| 赵六 | 99.0000 |
+------+------------+
4 rows in set (0.00 sec)
看每个人挂科情况
mysql> select name,score < 60 from stu;
+------+------------+
| name | score < 60 |
+------+------------+
| 张三 | 0 |
| 张三 | 1 |
| 张三 | 1 |
| 李四 | 1 |
| 李四 | 1 |
| 王五 | 1 |
| 赵六 | 0 |
| 赵六 | 0 |
| 赵六 | 0 |
+------+------------+
9 rows in set (0.00 sec)
计算每个人的挂科科目
mysql> select name,sum(score < 60) from stu group by name;
+------+-----------------+
| name | sum(score < 60) |
+------+-----------------+
| 张三 | 2 |
| 李四 | 2 |
| 王五 | 1 |
| 赵六 | 0 |
+------+-----------------+
4 rows in set (0.00 sec)
同时计算每人的平均分
mysql> select name,sum(score < 60),avg(score) as pj from stu group by name;
+------+-----------------+---------+
| name | sum(score < 60) | pj |
+------+-----------------+---------+
| 张三 | 2 | 60.0000 |
| 李四 | 2 | 50.0000 |
| 王五 | 1 | 30.0000 |
| 赵六 | 0 | 99.0000 |
+------+-----------------+---------+
4 rows in set (0.00 sec)
利用 having 筛选挂科 2 门以上的.
mysql> select name,sum(score < 60) as gk ,avg(score) as pj from stu group by name having gk >=2;
+------+------+---------+
| name | gk | pj |
+------+------+---------+
| 张三 | 2 | 60.0000 |
| 李四 | 2 | 50.0000 |
+------+------+---------+
2 rows in set (0.00 sec)
select goods_id,goods_name,shop_price from ecs_goods order by shop_price desc;
select goods_id,goods_name,add_time from ecs_goods order by add_time;
select goods_id,cat_id,goods_name,shop_price from ecs_goods
order by cat_id ,shop_price desc;
select goods_id,goods_name,shop_price from ecs_goods order by shop_price desc limit 3;
select goods_id,goods_name,click_count from ecs_goods order by click_count desc limit 2,3;
select goods_name,cat_name,shop_price from
ecs_goods left join ecs_category
on ecs_goods.cat_id=ecs_category.cat_id;
select goods_name,cat_name,shop_price from
ecs_goods left join ecs_category
on ecs_goods.cat_id=ecs_category.cat_id
where ecs_goods.cat_id = 4;
select goods_name,cat_name,brand_name from
ecs_goods left join ecs_category
on ecs_goods.cat_id=ecs_category.cat_id
left join ecs_brand
on ecs_goods.brand_id=ecs_brand.brand_id
where ecs_goods.cat_id = 4;
根据给出的表结构按要求写出 SQL 语句。
Match 赛程表
| 字段名称 | 字段类型 | 描述 |
|---|---|---|
| matchID | int | 主键 |
| hostTeamID | int | 主队的 ID |
| guestTeamID | int | 客队的 ID |
| matchResult | varchar(20) | 比赛结果,如( 2:0 ) |
| matchTime | date | 比赛开始时间 |
Team 参赛队伍表
| 字段名称 | 字段类型 | 描述 |
|---|---|---|
| teamID | int | 主键 |
| teamName | varchar(20) | 队伍名称 |
mysql> select * from m;
+-----+------+------+------+------------+
| mid | hid | gid | mres | matime |
+-----+------+------+------+------------+
| 1 | 1 | 2 | 2:0 | 2006-05-21 |
| 2 | 2 | 3 | 1:2 | 2006-06-21 |
| 3 | 3 | 1 | 2:5 | 2006-06-25 |
| 4 | 2 | 1 | 3:2 | 2006-07-21 |
+-----+------+------+------+------------+
4 rows in set (0.00 sec)
mysql> select * from t;
+------+----------+
| tid | tname |
+------+----------+
| 1 | 国安 |
| 2 | 申花 |
| 3 | 公益联队 |
+------+----------+
3 rows in set (0.00 sec)
mysql> select hid,t1.tname as hname ,mres,gid,t2.tname as gname,matime
-> from
-> m left join t as t1
-> on m.hid = t1.tid
-> left join t as t2
-> on m.gid = t2.tid;
+------+----------+------+------+----------+------------+
| hid | hname | mres | gid | gname | matime |
+------+----------+------+------+----------+------------+
| 1 | 国安 | 2:0 | 2 | 申花 | 2006-05-21 |
| 2 | 申花 | 1:2 | 3 | 公益联队 | 2006-06-21 |
| 3 | 公益联队 | 2:5 | 1 | 国安 | 2006-06-25 |
| 2 | 申花 | 3:2 | 1 | 国安 | 2006-07-21 |
+------+----------+------+------+----------+------------+
4 rows in set (0.00 sec)
A 表:
+------+------+
| id | num |
+------+------+
| a | 5 |
| b | 10 |
| c | 15 |
| d | 10 |
+------+------+
B 表:
+------+------+
| id | num |
+------+------+
| b | 5 |
| c | 15 |
| d | 20 |
| e | 99 |
+------+------+
要求查询出以下效果:
+------+----------+
| id | num |
+------+----------+
| a | 5 |
| b | 15 |
| c | 30 |
| d | 30 |
| e | 99 |
+------+----------+
create table a (
id char(1),
num int
) engine myisam charset utf8;
insert into a values ('a',5),('b',10),('c',15),('d',10);
create table b (
id char(1),
num int
) engine myisam charset utf8;
insert into b values ('b',5),('c',15),('d',20),('e',99);
mysql> # 合并 ,注意 all 的作用
mysql> select * from ta
-> union all
-> select * from tb;
+------+------+
| id | num |
+------+------+
| a | 5 |
| b | 10 |
| c | 15 |
| d | 10 |
| b | 5 |
| c | 15 |
| d | 20 |
| e | 99 |
+------+------+
参考答案:
mysql> # sum,group 求和
mysql> select id,sum(num) from (select * from ta union all select * from tb) as tmp group by id;
+------+----------+
| id | sum(num) |
+------+----------+
| a | 5 |
| b | 15 |
| c | 30 |
| d | 30 |
| e | 99 |
+------+----------+
5 rows in set (0.00 sec)
查询出最新一行商品(以商品编号最大为最新,用子查询实现)
select goods_id,goods_name from
ecs_goods where goods_id =(select max(goods_id) from ecs_goods);
select goods_id,goods_name,cat_id from ecs_goods where goods_id in (select max(goods_id) from ecs_goods group by cat_id);
用 from 型子查询把 ecs_goods 表中的每个栏目下面最新的商品取出来
select * from (select goods_id,cat_id,goods_name from ecs_goods order by goods_id desc) as t group by cat_id;
用 exists 型子查询,查出所有有商品的栏目
select * from category
where exists (select * from goods where goods.cat_id=category.cat_id);
创建触发器:
CREATE trigger tg2
after insert on ord
for each row
update goods set goods_number=goods_number-new.num where id=new.gid
CREATE trigger tg3
after delete on ord
for each row
update goods set goods_number=good_number+old.num where id=old.gid
CREATE trigger tg4
after update on ord
for each row
update goods set goods_number=goods_number+old.num-new.num where id=old.gid
// 例子:
update user set age=8 where name=lianying;
//(注意 where 条件不加会影响所有行,需要小心)
注意: NULL :查询方法: select * from test where name is (not)null
限制取出条目(limit 有两个参数 :偏移量 取出的条目)
select goods_id,goods_name,shop_price
-> from goods
-> order by shop_price desc
-> limit 0,3;
5 种语句有严格的顺序, where , group by , having , order by , limit
不能颠倒顺序
# 例子:语句有严格的顺序
mysql> select id,sum(num)
-> from
-> (select * from a union select * from b) as temp
-> group by id
-> having sum(num)>10
-> order by sum(num) desc
-> limit 0,1;
where 字查询:(内层的查询结果作为外层的比较条件)
#取出每个栏目下最新的商品:
select goods_id,cat_id,goods_name from goods where goods_id in (select max(goods_id) from goods group by cat_id);
#每个栏目下最新的商品:
mysql> select goods_id,goods_name from (select * from goods where 1 order by cat_id desc) as tmp
-> group by cat_id;
#查询栏目下是否有商品
mysql> select * from category
-> where exists(select * from goods where goods.cat_id=category.cat_id)
内连接是左右连接结果的交集
select xxx from
table1 inner jion table2 on table1.xx=table2.xx
mysql> select boy.hid,boy.bname,girl.hid,girl.gname
-> from
-> boy inner join girl on boy.hid=girl.hid;
以左表的数据为标准,去找右表的数据,查不到的为 NULL
#左连接
mysql> select boy.hid,boy.bname,girl.hid,girl.gname
-> from
-> boy left join girl on boy.hid=girl.hid;
#右连接
mysql> select boy.hid,boy.bname,girl.hid,girl.gname
-> from
-> boy right join girl on boy.hid=girl.hid;
mysql> select goods_id,cat_name,goods_name,shop_price
-> from
-> goods left join category on goods.cat_id= category.cat_id
-> where goods.cat_id=4;
把 2 条或多条的额查询结果,合并成 1 个结果集
mysql> select * from a
-> union all #union all 可以避免重复语句合并
-> select * from b;
mysql> select goods_id,cat_id,goods_name,shop_price from goods where cat_id=2
-> union
-> select goods_id,cat_id,goods_name,shop_price from goods where cat_id=4;
```
## 六、建表总结
```bash
create table 表名 (
列 1 列类型 [列属性 默认值]
列 2 列类型 [列属性 默认值]
...
);
engine = 存储引擎
chartset = 字符集
建表过程:声明表头的过程,也就是声明列的过程
| 类型: | 字节: | 最小值: | 最大值: |
|---|---|---|---|
| bigint | 8 字节 | -9223372036854775808 | 18446744073709551615 |
| int | 4 字节 | -2147483648 | 4294967295 |
| mediunint | 3 字节 | -8388608 | 8388607 |
| smallint | `2 字节 | -32768 | 3276 7 |
| tinyint | 1 字节 | -128 | 127 |
整型列的可选参数
mysql> create table t8(
-> ya year,
-> dt date,
-> tm time,
-> dttm datetime);
-> insert into t8 (ya,dt,tm) values(2015,'2015-12-18','18:28:36');
如何避免:声明列 NOT NULL default 默认值
mysql> create table t10(
-> id int not null default 0,
-> name char(10) not null default ''
-> );
view 被称为虚拟表,view 是 sql 语句的查询结果(物理表的一个映射结果,物理表一改变,视图表也改变)
1. view 好处
2. 视图的 algorithm
myisam 和 innDB 引擎区别
| mysiam | innDB | |
|---|---|---|
| 批量插入的速度: | 高 | 低 |
| 存储限制: | 没有 | 64TB |
一些示例
select from_unixtime(unix_timestamp());
select extract(year_month from current_date);
select extract(day_second from current_date);
select extract(hour_minute from current_date);
select period_diff(200302,199802);
select date_format(from_days(to_days(now())-to_days(birthday)),'%y')+0 as age from employee;
这样,如果 brithday 是未来的年月日的话,计算结果为 0 。
下面的 sql 语句计算员工的绝对年龄,即当 birthday 是未来的日期时,将得到负值
select date_format(now(), '%y') - date_format(birthday, '%y') -(date_format(now(), '00-%m-%d') <date_format(birthday, '00-%m-%d')) as age from employee
# 示例:
select encrypt('root','salt');
select encode('xufeng','key');
select decode(encode('xufeng','key'),'key');#加解密放在一起
select aes_encrypt('root','key');
select aes_decrypt(aes_encrypt('root','key'),'key');
select md5('123456');
select sha('123456');
# 示例:
select format(34234.34323432,3);
select date_format(now(),'%w,%d %m %y %r');
select date_format(now(),'%y-%m-%d');
select date_format(19990330,'%y-%m-%d');
select date_format(now(),'%h:%i %p');
select inet_aton('10.122.89.47');
select inet_ntoa(175790383);
为了进行数据类型转化, mysql 提供了 cast() 函数,它可以把一个值转化为指定的数据类型。类型有: binary , char , date , time , datetime , igned , unsigned
# 示例:
select cast(now() as signed integer),curdate()+0;
select 'f'=binary 'f','f'=cast('f' as binary);
# 示例:
select database(),version(),user();
#该例中,mysql 计算 log(rand()*pi()) 表达式 9999999 次。
selectbenchmark(9999999,log(rand()*pi()));
1. 链接到数据库服务器
mysql -h 地址 -u root -p 密码
2. 查看所有库
show databases;
3. 选库
use 库名
4. 查看库下面的表
show tables;
5. 建表
create table msg{
id int auto_increment primary key,
content varcha(200),
pubtime int
}charset utf8;
6. 告诉服务器你的字符集:set names gbk/utg8;
7. 添加数据
insert into msg(id,content,pubtime) values(1,'哈哈哈哈',13445);
8. 查询所有数据
select * from msg;
9. 按 id 查询
select * from where id = 2...
10. 快速清空表
truncate 表名
一般为了方便管理数据,我们都需要用到可视化工具,navicat-for-mysql

