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

你可能感兴趣的:(MySQL一些我不熟悉的技巧)