MySQL一些我不熟悉的技巧

1. 插入数据
  • 简单插入数据
insert into table [(cols)] #检查主键,有重复的则报错
select "xxx", 1, "111" 
  • 批量插入数据
insert into table [(cols)]
select * from another_table
或者
select * from another_table1
union [all]
select * from another_table2
  • insert ignore into table [(cols)] # 检查数据,如果有重复的数据则忽略插入的数据
  • replace into table [(cols)] # 检查主键/唯一索引,如有重复则用新的记录代替覆盖之
2. union
  • union 将两张表横向连接(列不变增加行),删除重复的记录
  • union all 保留所有记录
3. 创建表
  • create table [if not exsits] table_name #常规建表,检查表名是否重复
  • create table table_name as select * from another_table [limit 0]
    可以复制表的字段结构和所有数据,可灵活筛选要复制哪些字段,可用limit决定是否要复制数据,但不可复制索引和权限
  • create table table_name like another_table
    可复制全部的表结构和索引,不可选择字段,不可复制数据(需要后续批量插入),不可复制权限
4. replace

replace (field_name,’from_str’,'to_str’) 可以在更新数据的时候使用

5. 键、约束、索引
  • 主键,外键又被称为主键约束、外键约束
  • 约束是一列数据应该满足的规则,确保数据的准确性和一致性,约束是为了保证数据的完整性,索引是为了辅助查询。约束除了主键、外键之外,还有:
    唯一性约束:创建唯一性约束的同时会创建唯一性索引,唯一约束靠唯一索引实现,两者的不同是创建以及删除时的关键字不同,其他使用方法等都一样(至少在MySQL中)。
    check约束:约定某字段的值的取值范围,不然就报错
  • 添加约束的方式:
create table table_name 
(
  col1 xx xx,
  col2 yy yy,
  [constraint constraint_name] primary key (col1),
  [constraint constraint_name] foreign key(col2) references another_table(col2),
  [constraint constraint_name] unique [key](col1),
  [constraint constraint_name] check(col1 > 0),
  # 如不指定constraint及其name,那么系统会自动命名
)
# OR
  alter table table_name add [constraint constraint_name] primary key (col1),
  alter table table_name add [constraint constraint_name] foreign key(col2) references     
  another_table(col2),
  alter table table_name add [constraint constraint_name] unique [key](col1),
  alter table table_name add [constraint constraint_name] check(col1 > 0),
  # 如不指定constraint及其name,那么系统会自动命名
  • 没有索引的时候,数据在磁盘中按照顺序一一排列,因此查询数据时需要将查询条件依次与每一条记录相比较,O(n)的时间复杂度,非常慢。为字段添加索引之后,索引值会形成一个树的结构,查询时只需要依次比较树的分支节点直至叶节点即可,查询时间随数据量增大而指数级减少时间复杂度O(logn)。但是,增删改数据都会改变索引的数据的内容,导致系统需要重新更新一次索引,这也造成了额外的时间开销。同时,储存索引还会造成存储开销。
  • 按数据在磁盘中的物理存储方式分,索引可分为聚集索引和非聚集索引。聚集索引使数据在磁盘中按照顺序排成一个树的结构。一张表中只能有一个聚集索引,通过聚集索引可以直接查询到同一行的数据记录。一张表中可以存在多个非聚集索引。创建非聚集索引时,系统会将相应的字段数据copy一份出来用于创建索引。通过非聚集索引可以查找到表中主键/聚集索引的键值,再通过主键值间接地查询出其他字段的数据。当非聚集索引有组合字段创建时,则可以通过组合字段1直接查询到组合字段2,而无需经过主键/聚集索引中转。
  • 主键不可null,但唯一索引可为null。在创建主键的同时会自动创建一个唯一索引。
  • 唯一索引可为聚集or非聚集,创建主键时同时创建的索引也可为聚集or非聚集。但在mysql数据库innodb引擎里面,创建主键的同时就会创建一个聚集的唯一的索引,而在其他数据库引擎如SQL server中则可以选择索引要聚集还是非聚集的。
  • 主键(约束)!= xx索引
  • 创建聚集索引:MySQL的聚集索引一般为主键,没有主键时则会寻找第一个非空的唯一索引作为聚集索引,否则就以rowid作为聚集索引。因此,要想在除了主键列的其他字段设置聚集索引,则应该删除主键约束后,在某其他字段上建立唯一索引,并确保其not null,这样系统就会自动把它作为聚集索引而非默认的非聚集。
  • 添加索引的方式
create table table_name 
(
  col1 xx xx,
  col2 yy yy,
  [unique] index [index_name] (col1)
)
  # 如不指定index_name,那么系统会自动命名
OR
alter table table_name add [unique] index [index_name] (col2)
create index index_name on tb2 (name);
6. 创建视图
create view view_name as
  select * from table
7. 强制/禁止使用索引

当表中有多个索引时,可能需要手动确定使用/不使用哪一个索引进行查询

select * from table
force/ignore index(index_name)
where ..........
8. 创建触发器
  • new表是即将插入的/更新后的数据,old中是删除后/更新前的数据
create trigger trigger_name 
after/before update/delete/insert
**for each row**
begin
  xxxxxxx
  xxxxxxx;
end;
9. update/delete and 子查询

mySQL不支持对正在查询的表进行修改,具体而言,不能在update和delete中的where条件里使用子查询,只能将查询结果取名建立临时表,再select *

delete from table_name
where col in/not in
(
  select * from
    (
      select xxx from table_name
      where xxx
      group by xxx
    ) temp
);
10. with建立临时表
with temp_table_name as
(select xxx from table_name);
11. 同一条件下更新多个字段
update table_name
set col1 = xxx, col2 = xxx
where col1 = xxxx;
12. alter table 总结
alter table table_name
{ ADD COLUMN <列名> <类型>
| CHANGE COLUMN <旧列名> <新列名> <新列类型> #可改字段名and类型
| ALTER COLUMN <列名> { SET DEFAULT <默认值> | DROP DEFAULT } #不可改类型/字段名,只可改默认值
| MODIFY COLUMN <列名> <类型> #只可改类型
| DROP COLUMN <列名>
| RENAME TO <新表名> }
13. concat 函数

select concat(col1/str1, '分隔符', col2/str2) from table_name

14. length函数

length(str)

  • length('')=0 空字符长度为0
15. replace函数

replace(str, 'str中要被替换的字符', '替换后的字符')

16. group_concat函数

分组后,有时需要把组内某个字段的所有记录的值都连接起来
group_concat(col) 表示将组内col字段的所有记录都以‘,’分隔并连接,如:
10001 123
10001 456
这样输出结果为123,456
group_concat(str/col, col, str/col) 则表示在上面group_concat的结果中每一个字段的记录之前或之后再加一个东西, 如:
10001 123
10001 456
group_concat(col, col, "+") => 123123+,456456+

17. 存储过程与函数
  • 存储过程与函数的基本概念十分相似,都是封装一段可以实现一种功能的代码。存储过程封装的更多是一段相对独立的业务逻辑,因此存储过程需要单独执行。而函数则聚焦在某一种相对更基本的功能,如加减法,本质上是在为实现一个更大的功能造轮子,所以函数需要/可以在其他SQL语句中调用。
  • 存储过程可以设置输入/输出参数,局部or全局地改变变量的值,输出不限量。而函数只能且必须输出一个值。
  • 封装的好处:将一段代码预编译后存储在数据库中,使用时可以直接调用,减少了编译时间,减少了数据传输的数量(传几个参数就可以了,没有必要传整段代码)
  • 创建存储过程:
delimeter $$
drop procedure if exsits proc_name $$
create procedure proc_name
(
  [in 参数名 参数类型 #输入参数,
  out 参数名 参数类型 #输出参数 全局地改变变量的值,
  inout 参数名 参数类型]
)
begin
  SQL语句;
  xxxxxx;
end; $$
delimeter ;
# 调用
call proc_name(输入参数);
  • 创建函数
delimeter $$
drop function if exsits func_name $$
create function func_name
(
[输入参数1 类型,
输入参数2 类型,]
) returns (输出类型)
begin
  SQL语句;
  return ;
end;$$
delimeter ;
# 调用
select func_name(参数)
or select * from table where xxx = func_name(参数)
18. if else
if (比较条件, 为真输出, 为假输出)
or
if (比较条件)
then 
  xxxx;
elseif (比较条件)
then 
  xxxx;
else 
  xxxx;
end if;
19. 循环
  • Loop-leave
loop: loop_name
  if (条件)
  then
    leave loop_name (相当于if-break)
  end if;
  循环执行语句
end loop
  • while
while (i < constant)  do #循环准入条件
  set i = i + 1
  循环体
end while;
  • repeat-untill
repeat
  循环体
  set i = i +1
untill i > constant 
end repeat;
20. 游标

常与循环、存储过程搭配,对结果集(表)的所有记录一行一行地依次取出进行操作

drop procedure if exists sp_name;
demiliter $$
create procedure sp_name ()
begin
declare flag bool deault False #定义局部变量;## declare 只能用于存储过程begin-end中
declare vars int;
declare cur_name cursor for (select xxxxx); #在结果集上定义游标
declare continue handler for not found set flag = True; #游到最后触发此条件:继续执行下面的语句,并且设置flag(循环退出条件)
open cur_name; #打开游标
loop_name: loop
  if (flag = True)
  then leave loop_name
  fetch [next/prior/first/last from] cur_name into (var1, var2) / fetch cur_name into (var1, var2) ; #如不指明 next/prior from 则默认next #将一行的记录存在变量里
  select var1, var2 # or other SQL operations interms of var1 var2
end loop;
close cur_name #关闭游标
end;$$
demiliter ;
21. 定义变量
  • 局部变量
    只在begin-end语句块中有用,用declare声明
    declare var var_type;
  • 用户变量
    在当前数据库连接中有效,在当前会话中属于“全局变量”,用set/select定义并且赋初值
    set @var=1/select @var:=null
  • 会话变量
    作用域与用户变量相同,每个客户端连接数据库时系统会用全局变量初始化会话变量的值,用户只能改动自己的会话变量,不能改动其他的会话变量。
    set session var = value
  • 全局变量
    在整个服务器上,跨数据库有效
    set global var=1
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容