一些基本的操作
[Mysql官方文档] (https://dev.mysql.com/doc/refman/5.7/en/select.html “Mysql官方文档”)
创建和删除
//创建表
mysql> create table <table_name>(field[,field2,...]) comment='';
//eg:
mysql> create table user(
> id int(4) not null primary key auto_increment,
> name varchar(20) not null,
> sex int(1) not null default '0',
> weight double(10,2)) comment='用户表';
//删除表
mysql> drop table <table_name>;
//修改表名
mysql> rename table <old_table_name> to <new_table_name>;
查看表
SHOW DATABASES //列出 MySQL Server 数据库。
SHOW TABLES [FROM db_name] //列出数据库数据表。
SHOW TABLE STATUS [FROM db_name] //列出数据表及表状态信息。
SHOW COLUMNS FROM tbl_name [FROM db_name] //列出资料表字段
SHOW FIELDS FROM tbl_name [FROM db_name]
DESCRIBE tbl_name [col_name] //可以简写为: DESC tbl_name [col_name]
SHOW FULL COLUMNS FROM tbl_name [FROM db_name]//列出字段及详情
SHOW FULL FIELDS FROM tbl_name [FROM db_name] //列出字段完整属性
SHOW INDEX FROM tbl_name [FROM db_name] //列出表索引。
SHOW STATUS //列出 DB Server 状态。
SHOW VARIABLES //列出 MySQL 系统环境变量。
SHOW PROCESSLIST //列出执行命令。
SHOW GRANTS FOR user //列出某用户权限
表字段
常用字段属性:
属性 | 含义 |
---|---|
auto_increment | 为新插入的行赋一个唯一的整数标识符,自动递增,作为主键列,每个表只允许有一个自动递增列 |
binary | 区分大小写的方式排序 |
default | 属性确保在没有任何值可用的情况下,赋予某个常量值,这个值必须是常量,因为MySQL不允许插入函数或表达式值。此外,此属性无法用于BLOB或TEXT列。如果已经为此列指定了NULL属性,没有指定默认值时默认值将为NULL,否则默认值将依赖于字段的数据类型 |
index | 如果所有其他因素都相同,要加速数据库查询,使用索引通常是最重要的一个步骤。索引一个列会为该列创建一个有序的键数组,每个键指向其相应的表行。以后针对输入条件可以搜索这个有序的键数组,与搜索整个未索引的表相比,这将在性能方面得到极大的提升。在实践中尽量使用小的索引。 |
not null | 如果将一个列定义为not null,将不允许向该列插入null值。建议在重要情况下始终使用not null属性,因为它提供了一个基本验证,确保已经向查询传递了所有必要的值。 |
null | 为列指定null属性时,该列可以保持为空,而不论行中其它列是否已经被填充。记住,null精确的说法是“无”,而不是空字符串或0。 |
primary key | 用于确保指定行的唯一性。指定为主键的列中,值不能重复,也不能为空。为指定为主键的列赋予auto_increment属性是很常见的,因为此列不必与行数据有任何关系,而只是作为一个唯一标识符。作为主键又分两种:(1) 单字段主键 如果输入到数据库中的每行都已经有不可修改的唯一标识符,一般会使用单字段主键。注意,此主键一旦设置就不能再修改。(2) 多字段主键如果记录中任何一个字段都不可能保证唯一性,就可以使用多字段主键。这时,多个字段联合起来确保唯一性。如果出现这种情况,指定一个auto_increment整数作为主键是更好的办法。 |
unique | 被赋予unique属性的列将确保所有值都有不同的值,只是null值可以重复。一般会指定一个列为unique,以确保该列的所有值都不同。 |
zerofill | 可用于任何数值类型,用0填充所有剩余字段空间。例如,无符号int的默认宽度是10;因此,当“零填充”的int值为4时,将表示它为0000000004。 |
character set | 指定一个字符集 |
添加字段
mysql> alter table <table_name> add <field_name> <field_type> comment "备注";
//eg:在表user添加了一个字段update_time,类型为timestamp,设置创建时间和默认时间
mysql> alter table user add update_time timestamp default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment='更新时间';
// 在log表中 添加一个state字段并且放在current_count后
mysql> ALTER TABLE log ADD `state` TINYINT (1) UNSIGNED NOT NULL DEFAULT 0 COMMENT "状态,0 待审核,1已审核,2拒绝" AFTER current_count;
修改字段
mysql> alter table <table_name> change <old_table> <new_table> <field_type>;
//eg:
mysql> alter table user change weight height double(8,2);
删除字段
删除字段:
mysql> alter table <table_name> drop <field_name>;
添加索引
//一般索引
mysql> alter table <table_name> add index <index_name> (field_name[,field_name2,...]);
//eg:
mysql> alter table user add index u_name (name,sex);
//加主关键字的索引
mysql> alter table <table_name> add primary key <field_name>;
//eg:
mysql> alter table user add primary key(id);
//加唯一限制条件的索引
mysql> alter table <table_name> add unique <index_name> (field_name);
//eg:
mysql> alter table user add unique u_name(cardnumber);
删除索引
mysql> alter table <table_name> drop index <index_name>;
//eg:
mysql> alter table user drop index u_name;
insert语法
INSERT [ LOW_PRIORITY | DELAYED | HIGH_PRIORITY ] [ IGNORE ] [ INTO ] tbl_name [ PARTITION (
partition_name ,...) ] [ (
col_name ,...) ] {
VALUES
|
VALUE
} ({ expr | DEFAULT },...),(...) ,...[ ON DUPLICATE KEY UPDATE col_name = expr [, col_name = expr ]...]
//eg1 单条插入:
mysql> INSERT INTO user(name, age) VALUE ("张三",18);
//eg2 多条插入:
mysql> INSERT INTO user(name, age) VALUES ("张三",18),("李四",19),("王五",20);
or
//只能插入一条
INSERT [ LOW_PRIORITY | DELAYED | HIGH_PRIORITY ] [ IGNORE ] [ INTO ] tbl_name [ PARTITION (
partition_name ,...) ]
SET col_name ={ expr | DEFAULT },...[ ON DUPLICATE KEY UPDATE col_name = expr [, col_name = expr ]...]
//eg:
mysql> INSERT INTO user set name="张三", age=18;
or
//用于表复制
INSERT [ LOW_PRIORITY | HIGH_PRIORITY ] [ IGNORE ] [ INTO ] tbl_name [ PARTITION (
partition_name ,...) ] [ (
col_name ,...) ] SELECT
...[ ON DUPLICATE KEY UPDATE col_name = expr [, col_name = expr ]...]
//eg1 两个表数据互通:
mysql> INSERT INTO a(a_field1,a_field2) SELECT b_field1,b_field2 FROM b;
//eg2 多张表进行复制,需要先使用关联查询查出数据后再插入,嵌套部分需要设置别名!!:
mysql> INSERT INTO a(a_field1,a_field2) SELECT * FROM(SELECT f1,f2 FROM b JOIN c) AS tb;
update语法
单条更新:
UPDATE [ LOW_PRIORITY ] [ IGNORE ] table_reference
SET col_name1 ={ expr1 | DEFAULT } [, col_name2 ={ expr2 | DEFAULT }]...[
WHERE
where_condition ] [
ORDER BY
...] [
LIMIT row_count ]
# eg1 单表更新:
UPDATE user SET name="李四",age=19 WHERE id=1;
# eg2 多表更新:
UPDATE USER u
INNER JOIN user_info ui ON u.user_id = ui_user_id
SET ui_age = 20
WHERE
u.sex = 1;
多条更新:
由于mysql并没有提供多条更新语句,所以进行批量更新网上有三种方法:
-
在程序中批量update,一条记录update一次,性能很差
-
使用replace into 或者insert into …on duplicate key update,性能较好
//eg1:replace into (操作本质是对重复的记录先delete后insert,如果更新的字段不全会将缺失的字段置为缺省值) mysql> replace into user (name,age) values ("张三",15),("李四",20),("王五",17); //eg2:insert into (操作本质是只update重复记录,不会改变其它字段。) mysql> insert into user (id, name, age) values (1,"张三",15),(2,"李四",20),(3,"王五",17) on duplicate key update name=values(name), age=values(age);
两者异同 相同之处:
(1) 没有key的时候,replace与insert .. on deplicate udpate相同。 (2) 有key的时候,都保留主键值,并且auto_increment自动+1
不同之处:
有key的时候,replace是delete老记录,而录入新的记录,所以原有的所有记录会被清除,这个时候,如果replace语句的字段不全的话,有些原有的字段的值会被自动填充为默认值。 而insert .. duplicate update则只执行update标记之后的sql,从表象上来看相当于一个简单的update语句。所以两者的区别只有一个,insert .. on duplicate udpate保留了所有字段的旧值,再覆盖然后一起insert进去,而replace没有保留旧值,直接删除再insert新值。
从底层执行效率上来讲,replace要比insert .. on duplicate update效率要高,但是在写replace的时候,字段要写全,防止老的字段数据被删除。
-
创建临时表,先更新临时表,然后从临时表中update,性能最好
//注意:这种方法需要用户有temporary 表的create 权限。 mysql> create temporary table tmp(id int(4) primary key,name varchar(50), age int(4)); mysql> insert into tmp values (1,"张三",15),(2,"李四",20),(3,"王五",17); mysql> update user, tmp set user.name=tmp.name, user.age=tmp.age where user.id=tmp.id;
补充:
// 批量替换字段内容的一部分
mysql> UPDATE article SET content = REPLACE(content, 'abc', '123');
//效果: "AabcB" =》"A123B"
delete语法
普通删除:
DELETE [ LOW_PRIORITY ] [ QUICK ] [ IGNORE ]
FROM
tbl_name [ PARTITION (
partition_name ,...) ] [
WHERE
where_condition ] [
ORDER BY
...] [
LIMIT row_count ]
//eg1 删除单条:
mysql> DELETE FROM user where user_id = 1;
//eg2 删除多条:
mysql> DELETE FROM user where user_id in (1,2,3,4);
多表删除:
DELETE [ LOW_PRIORITY ] [ QUICK ] [ IGNORE ] tbl_name [.*] [, tbl_name [.*]]...
FROM
table_references [
WHERE
where_condition ]
//eg:
DELETE t1,t2
FROM t1
INNER JOIN t2
INNER JOIN t3
WHERE
t1.id = t2.id
AND t2.id = t3.id;
or:
DELETE [ LOW_PRIORITY ] [ QUICK ] [ IGNORE ]
FROM
tbl_name [.*] [, tbl_name [.*]]... USING table_references [
WHERE
where_condition ]
# eg:
DELETE
FROM
t1,
t2 USING t1
INNER JOIN t2
INNER JOIN t3
WHERE
t1.id = t2.id
AND t2.id = t3.id;
截断表:
mysql> truncate table <table_name>;
/*
截断表可以用于删除表中的所有数据。截断表命令还会回收所有索引的分配页。截断表的执行速度与不带where子句的delete(删除)命令相同,甚至比它还要快。delete(删除)一次删除一行数据,并且将每一行被删除的数据都作为一个事务记录日志;而truncate (截断)表则回收整个数据页,只记录很少的日志项。delete(删除)和truncate(截断)都会回收被数据占用的空间,以及相关的索引。只有表的拥有者可以截断表。
另外,truncate表之后,如果有自动主键的话,会恢复成默认值。
*/
select语法
基本语法:
SELECT
[ ALL | DISTINCT | DISTINCTROW ] [ HIGH_PRIORITY ] [ STRAIGHT_JOIN ] [ SQL_SMALL_RESULT ] [ SQL_BIG_RESULT ] [ SQL_BUFFER_RESULT ] [ SQL_CACHE | SQL_NO_CACHE ] [ SQL_CALC_FOUND_ROWS ] select_expr [, select_expr...] [
FROM
table_references [ PARTITION partition_list ] [
WHERE
where_condition ] [
GROUP BY
{ col_name | expr | position } [ ASC | DESC ],...[ WITH ROLLUP ]] [
HAVING
where_condition ] [
ORDER BY
{ col_name | expr | position } [ ASC | DESC ],...] [
LIMIT {[ OFFSET ,] row_count | row_count OFFSET OFFSET }] [ PROCEDURE procedure_name (argument_list) ] [ INTO OUTFILE 'file_name' [ CHARACTER
SET charset_name ] export_options | INTO DUMPFILE 'file_name' | INTO var_name [, var_name ]] [ FOR UPDATE | LOCK IN SHARE MODE ]]
#eg:
#查询总条数
mysql> SELECT COUNT(*) FROM test_table WHERE tf_b = 1;
#倒序分页查询
mysql> SELECT tf_a, tf_b FROM test_table WHERE tf_b = 1 ORDER BY tf_a DESC LIMIT 100,10;
花式操作
# 创建学生表1
CREATE TABLE `student1` (
`STUDENT_ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '学生自增长ID',
`STUDENT_NAME` varchar(30) DEFAULT NULL COMMENT '学生名称',
`STUDENT_COURSE` varchar(30) DEFAULT NULL COMMENT '学科',
`STUDENT_SCORE` int(11) DEFAULT NULL COMMENT '成绩',
PRIMARY KEY (`STUDENT_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='学生表';
# 插入数据
INSERT INTO student1 (
STUDENT_NAME,
STUDENT_COURSE,
STUDENT_SCORE
)
VALUES
("张三", "语文", 80),
("张三", "数学", 90),
("张三", "英语", 85),
("李四", "语文", 30),
("李四", "数学", 90),
("李四", "英语", 100);
STUDENT_ID | STUDENT_NAME | STUDENT_COURSE | STUDENT_SCORE |
---|---|---|---|
1 | 张三 | 语文 | 80 |
2 | 张三 | 数学 | 90 |
3 | 张三 | 英语 | 85 |
4 | 李四 | 语文 | 30 |
5 | 李四 | 数学 | 90 |
6 | 李四 | 英语 | 100 |
# 创建学生表2
CREATE TABLE `student2` (
`STUDENT_ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '学生自增长ID',
`STUDENT_NAME` varchar(30) DEFAULT NULL COMMENT '学生名称',
`STUDENT_TOTAL_SCORE` int(1) DEFAULT NULL COMMENT '总成绩',
PRIMARY KEY (`STUDENT_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='学生总成绩';
查询并插入
语法格式
INSERT INTO 表名1(字段列表1) SELECT 字段列表2 FROM 表名2 WHERE 条件表达式;
# eg 用一条语句查询出student1表中学生总成绩并且降序插入student2表中
INSERT INTO student2 (
STUDENT_NAME,
STUDENT_TOTAL_SCORE
) SELECT
STUDENT_NAME,
SUM(STUDENT_SCORE) AS STUDENT_TOTAL_SCORE
FROM
student1
GROUP BY
STUDENT_NAME
运行结果:
STUDENT_ID | STUDENT_NAME | STUDENT_TOTAL_SCORE |
---|---|---|
1 | 张三 | 255 |
2 | 李四 | 220 |
查询并更新
update时,更新的表不能在set和where中用于子查询,但是可以对多个表进行更新(INNER JOIN),所以根据这个特性我们来做查询并更新 语法格式:
UPDATE table1 a INNER JOIN table2 b on a.id = b.id set ... where ...
# eg: 用一条语句将所有人的语文成绩改成95
UPDATE student1 a
INNER JOIN (
SELECT
STUDENT_ID,
STUDENT_NAME,
STUDENT_COURSE,
STUDENT_SCORE
FROM
student1
WHERE
STUDENT_COURSE LIKE '%英语%'
) b ON a.STUDENT_ID = b.STUDENT_ID
SET a.STUDENT_SCORE = 95
查询并删除
通常查询并删除针对的是表中的重复记录,所以我们首先要查找到重复的记录:
查找记录
方法一(推荐):
SELECT * FROM
table a
WHERE
[(a.field1,a.field2,...)] IN (
SELECT
[field1,field2,...]
FROM
table
GROUP BY
[field1 ,field2,...]
HAVING
Count(*) > 1
)
方法二:
SELECT * FROM
table a
WHERE
(( SELECT
COUNT(*)
FROM
table
WHERE
field1 = a.field1
AND field2 = a.field2
AND ...
)> 1)
eg: ps. 如果需要只显示一条最新记录,则添加a.STUDENT_ID和MAX(STUDENT_ID)。
# 根据多个字段查询student1
SELECT
STUDENT_ID,
STUDENT_NAME,
STUDENT_COURSE,
STUDENT_SCORE
FROM
student1 a
WHERE
(a.STUDENT_NAME, a.STUDENT_COURSE) IN (
# (a.STUDENT_NAME, a.STUDENT_COURSE,a.STUDENT_ID) IN (
SELECT
# MAX(STUDENT_ID)
STUDENT_NAME,
STUDENT_COURSE
FROM
student1
GROUP BY
STUDENT_NAME,
STUDENT_COURSE
HAVING
count(*) > 1
)
ORDER BY
STUDENT_COURSE DESC
删除记录
如上所提,可以得到最新的一条数据,那只保留id最大的一条数据: 两种方法目前手头没有大的数据无法做测试,等以后再比较性能差异。 方法一:
DELETE FROM student1
WHERE
# 将最后插入的数据保留 其他数据删除
STUDENT_ID NOT IN (
# 查询最后插入的数据
SELECT
MAX(STUDENT_ID)
FROM
(
# 查询出重复数据
SELECT
STUDENT_ID,
STUDENT_NAME,
STUDENT_COURSE,
STUDENT_SCORE
FROM
student1 a
WHERE
(
a.STUDENT_NAME,
a.STUDENT_COURSE
) IN (
SELECT
STUDENT_NAME,
STUDENT_COURSE
FROM
student1
GROUP BY
STUDENT_NAME,
STUDENT_COURSE
HAVING
count(*) > 1
)
) AS tmp
GROUP BY
STUDENT_NAME,
STUDENT_COURSE
HAVING
count(*) > 1
)
方法二:
DELETE
FROM
student1
WHERE
#查出重复数据
(
STUDENT_NAME,
STUDENT_COURSE
) IN (
SELECT
STUDENT_NAME,
STUDENT_COURSE
FROM
(
SELECT
STUDENT_NAME,
STUDENT_COURSE
FROM
student1
GROUP BY
STUDENT_NAME,
STUDENT_COURSE
HAVING
COUNT(*) > 1
) s1
)
# 排除最后插入的数据保留
AND STUDENT_ID NOT IN (
SELECT
STUDENT_ID
FROM
(
SELECT
MAX(STUDENT_ID)
FROM
student1
GROUP BY
STUDENT_NAME,
STUDENT_COURSE
HAVING
COUNT(*) > 1
) s2
);