SHOW DATABASES; ## 当前主机数据库列表 DROP DATABASE IF EXISTS db; ## 删除数据库[如果存在] CREATEDATABASEIFNOTEXISTS db CHARACTER SET UTF8; ## 创建数据库[如果不存在] USE db; ## 切换db为默认数据库
2.2 Table
1 2 3 4 5 6 7 8 9 10 11 12 13
SHOW TABLES; ## 当前数据库中数据表
TRUNCATE TABLE db.users; ## 彻底清空数据表(清除碎片) DROP TABLE IF EXISTS db.users; ## 删除数据表[如果存在] CREATETABLEIFNOTEXISTS db.users( ## 新建数据表[如果不存在] idINT AUTO_INCREMENT COMMENT'用户ID', nameVARCHAR(32) NOTNULLCOMMENT'用户名', city VARCHAR(16) NOTNULLCOMMENT'城市', birthday DATEDEFAULT'2000-01-01'COMMENT'生日', created TIMESTAMPDEFAULTCURRENT_TIMESTAMPCOMMENT'生成时间', updatedTIMESTAMPDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT'更新时间', PRIMARY KEY(id), UNIQUE uni_users_name(name), INDEX idx_users_city(city), INDEX idx_users_birthday(birthday) ) ENGINE=INNODBDEFAULTCHARSET UTF8 COMMENT'用户表';
SELECTid, name, city, YEAR(CURDATE())-YEAR(birthday) AS age FROM db.users WHERE (nameLIKE'张%'AND city IN ('北京', '上海')) OR birthday BETWEEN'1990-01-01'AND'2009-12-31' ORDERBYidDESC LIMIT 0,3; ## [m,]n
3.1.2 统计
1 2 3 4 5 6
SELECTMIN(birthday), MAX(birthday), COUNT(*) ## AVG(), SUM() FROM db.users WHERE city IN ('北京', '上海') ## 分组前筛选 GROUPBY city ## 分组依据 HAVINGCOUNT(*)>0 ## 分组后筛选 ORDERBYidDESCLIMIT0,3;
3.1.3 子表
1 2 3 4
SELECT t.*, (SELECT birthday FROM db.users WHERENAME='李四') AS birthday4 FROM (SELECTid, NAME, city, birthday FROM db.users WHEREid>1) AS t WHERE t.birthday>(SELECT birthday FROM db.users WHERENAME='张三') ANDEXISTS(SELECT1FROM db.orders AS o WHERE o.uid=t.id);
3.1.4 JOIN(难点中的难点)
3.1.4.1 常规关联
左右表严格关联上的记录才返回。 特别注意:无关联条件时,结果为m*n条记录,切记不要漏写关联条件。
1 2
SELECT u.name, o.id ASoid, o.amount FROM db.users AS u, db.orders AS o WHERE u.id=o.uid;
oid
amount
name
city
birthday
1
100.00
张三
北京
2000-01-01
2
200.00
张三
北京
2000-01-01
3
400.00
李四
上海
2003-01-01
3.1.4.2 左连接
除了严格关联上的记录,“左表”存在而右表不存在的记录也返回。
1 2 3
SELECT o.id ASoid, o.amount, u.name, u.city, u.birthday FROM db.users AS u LEFTJOIN db.orders AS o ON u.id=o.uid; ## WHERE o.id > 2;
oid
amount
name
city
birthday
1
100.00
张三
北京
2000-01-01
2
200.00
张三
北京
2000-01-01
3
400.00
李四
上海
2003-01-01
NULL
NULL
王五
广州
2006-01-01
3.1.4.3 右连接
除了严格关联上的记录,“右表”存在而左表不存在的记录也返回。
1 2
SELECT o.id ASoid, o.amount, u.name, u.city, u.birthday FROM db.users AS u RIGHTJOIN db.orders AS o ON u.id=o.uid;
oid
amount
name
city
birthday
1
100.00
张三
北京
2000-01-01
2
200.00
张三
北京
2000-01-01
3
400.00
李四
上海
2003-01-01
4
500.00
NULL
NULL
NULL
左关联的实际应用:统计每个用户的订单个数和总金额。 如果用普通连接,则无订单用户将不用列出。
1 2 3
SELECT u.id, u.name, COUNT(o.id) AS order_number, IFNULL(SUM(o.amount),0) AS total_amoumt FROM db.users AS u LEFTJOIN db.orders AS o ON u.id=o.uid GROUPBY u.id;
id
name
order_number
total_amoumt
1
张三
2
300.00
2
李四
1
400.00
3
王五
0
0.00
3.1.5 UNION [ALL]
各个子查询的字段的个数和类型必须一致;
UNION 自动去重,UNION ALL 不去重。
1 2 3
SELECT * FROM db.users WHERE city='北京'UNION SELECT * FROM db.users_bak1 WHERE city='上海'UNION SELECT * FROM db.users_bak2 WHERE city='广州';
3.1.6 索引
索引缺点: 占空间;INSERT/DELETE/UPDATE 时慢(要更新索引区)。 有用子句: WHERE, ORDER BY, GROUP BY, JOIN 索引禁忌: YEAR(birthday)=2016, INSTR(city,'上')>0, name LIKE '%ABC%' 注意: 每次执行新写的SELECT语句,务必考虑相关数据表的数据量、是否能用到索引,可考查WHERE, ORDER BY, GROUP BY, JOIN等子句,或者使用EXPLAIN查看执行计划。
3.2 INSERT
1 2 3 4 5 6
INSERTINTOusers(nick,city) VALUES ('张三', '北京'), ('李四', '上海'), ('王五', '广州'); ## 没指定的列,取值为默认值 INSERTINTO tmp_users(nick,city) SELECT nick, city FROM tmp_users;
唯一索引重复时的处理方法
1 2 3 4 5
INSERT INTO users(nick,city) VALUES('张三', '上海'); ## 默认用法,会报错 INSERT IGNORE INTO users(nick,city) VALUES('张三', '上海'); ## 冲突时忽略新记录 INSERTINTOusers(nick,city) VALUES('张三', '上海') ON DUPLICATE KEY UPDATE city=VALUES(city); ## 覆盖原记录,未涉及列保持原值 REPLACE INTO users(nick,city) VALUES('张三', '上海'); ## 覆盖原记录,未涉及列全部更新为默认值
OPEN cur_users; STARTTRANSACTION; REPEAT FETCH cur_users INTO v_id, v_name; IF !done THEN SET v_logs = CONCAT(v_logs, v_id, ','); UPDATE db.users SETupdated=NOW() WHEREid=v_id; ENDIF; UNTIL done ENDREPEAT; COMMIT; ## ROLLBACK; CLOSE cur_users;
CREATETABLE tmp_scores_extra AS SELECT s.* FROM scores s WHEREEXISTS ( SELECT1 FROM tmp_scores_stat t WHERE t.sid=s.sid AND t.cid=s.cid AND t.id_min!=s.id); ## 每个组合中,保留id最小的那条记录
5.3 删除原表的多余记录
1 2 3 4 5
DELETEFROM scores WHEREEXISTS ( SELECT1 FROM tmp_scores_extra t WHERE t.id=scores.id);