事务修改表的sql语句

数据库基础五结束篇

一.重点

1.1 python操作数据库

1.第三方模块pymysql
  pip3 install pymysql
2.基本使用
  import pymysql
3.链接数据库
  conn_obj = pymysql.connect(
	host='127.0.0.1',  # mysql服务端的ip地址
    port=3306,    # mysql默认rort端口地址
    user='root',  # 用户名
    password='xxx',  # 数据库密码 可简写为passwd
    databases='库名',# 选择连接的库
    charset='utf8'   # 设定字符编码
)
4.产生游标
  cursor=conn_obj.cursor(
  	cursor=pymysql.cursors.DictCursor
  ) # 括号内默认数据为元组,设置了之后会将数据处理成字典
5.获取操作的命令
  sql1='selcet * from XXX;'
6.将执行命令丢入数据库中
  affect_rows=cursor.execute(sql1) # 可以获取到结果的行数
7.执行语句
  res=cursor.fetchall()  # 获取全部表内信息
  print(res) # 可以查看所有的信息
8.获取结果的关键字
  fetchone() # 获取一行游标也会在一行的最后面
  fetchmany() # 执行指定获取数据的条数
  fetchall()  # 获取表内全部数据
9.控制游标所在位置
  cursor.scroll(n,'relative') # 将游标向右移动n个数据单位
  cursor.scroll(n,'absolute') # 让游标停在离起始位置的n个数据位置

1.2 SQL注入问题

1.对于输入用户名
  用户名:jason' -- hdfhshhdsc
  密码:
2.对于不输入用户名 
  用户名:xxx' or 1=1 -- fjvbdhfvhd
  密码:
3.对于这两种方式都会登录成功
  钻了mysql注释语法以及逻辑运算符的空隙
  解决方式
  execute自带校验SQL注入问题,自动处理特殊符号
  sql='select * from 表名 where name=%s and password=%s;'
  cursor.exe.cute(sql,(name,password))
4.对于插入多条数据
  sql='insert into userinfo(name,password) values(%s,%s)'
  cursor.executemany(sql,[('name1','password1'),('name2','password2')])

1.3 二次确认

1.方式一
  affect_row=cursor.execyte(sql)
  conn_obj.commit   # 手动二次确认
2.方式二
  conn_obj=pymysql.connect(
  	autocommit=True   #自动二次确认
  )

1.4 修改表的SQL语句补充

1.修改表名  rename
  alter table t1 rename ttt;
2.添加字段  add
  alter table ttt add pwd int; # 默认尾部添加
  alter table ttt add tid int after name;
  '''指定添加到name字段名后面'''
  alter table ttt add nid int first; # 头部
3.修改字段  change
  alter table ttt change pwd password tinyint;
4.删除字段  drop
  alter table ttt drop nid;

1.5 视图

1.视图就是将一些查询的结果作为一个虚拟表
2.创建虚拟表
  create viev 视图名 as sql语句
  '''建议将视图名取名为xxx_viev便于区分'''

1.6事务

"""
事务的概念
	事务可以包含诸多SQL语句并且这些SQL语句
	要么同时执行成功 要么同时执行失败 这是事务的原子性特点
事务的作用
	戴某某欠了赵某某一笔钱 现在想要还钱
		戴某某拿着交行的银行卡去招商银行的ATM机给赵某某的建行卡转钱
			1.朝交行的服务器发送请求 修改戴某某账户余额(减钱)
			2.朝建行的服务器发送请求 修改赵某某账户余额(加钱)
事务的四大特性(重点)
	ACID
		A:原子性
			一个事务是一个不可分割的整体 里面的操作要么都成立要么都不成立
		C:一致性
			事务必须使数据库从一个一致性状态变到另外一个一致性状态
		I:隔离性
			并发编程中 多个事务之间是相互隔离的 不会彼此干扰
		D:持久性
			事务一旦提交 产生的结果应该是永久的 不可逆的
"""
具体使用
	1.创建表及录入数据
  	create table user(
      id int primary key auto_increment,
      name char(32),
      balance int
      );
    insert into user(name,balance)
      values
      ('jason',1000),
      ('kevin',1000),
      ('tank',1000);
  2.事务操作
  	开启一个事务的操作
    	start transaction;
    编写SQL语句(同属于一个事务)
    	update user set balance=900 where name='jason';
			update user set balance=1010 where name='kevin'; 
			update user set balance=1090 where name='tank';
    事务回滚(返回执行事务操作之前的数据库状态)
    	rollback;  # 执行完回滚之后 事务自动结束
    事务确认(执行完事务的主动操作之后 确认无误之后 需要执行确认命令)
    	commit;  # 执行完确认提交之后 无法回滚 事务自动结束

二.需知

2.1 触发器

"""
触发器概念
	在对表数据进行增、删、改的具体操作下,自动触发的功能
触发器作用
	专门针对表数据的操作 定制个性化配套功能
触发器种类
	表数据新增之前、新增之后
	表数据修改之前、修改之后
	表数据删除之前、删除之后
触发器创建
	create trigger 触发器名字 before/after insert/update/delete
	on 表名 for each row
		begin
			SQL语句
		end
	触发器的名字一般情况下建议采用下列布局形式
		tri_after_insert_t1
		tri_before_update_t2
		tri_before_delete_t3
"""
具体案例(了解)
"""
补充:临时修改SQL语句的结束符
	delimiter $$
临时修改的原因是因为触发器 存储过程等技术点 代码中也需要使用分号
如果不修改 则无法书写出完成的代码
"""
	1.先创建两张表
  	# 案例
    CREATE TABLE cmd (
        id INT PRIMARY KEY auto_increment,
        USER CHAR (32),
        priv CHAR (10),
        cmd CHAR (64),
        sub_time datetime, #提交时间
        success enum ('yes', 'no') #0代表执行失败
    );

    CREATE TABLE errlog (
        id INT PRIMARY KEY auto_increment,
        err_cmd CHAR (64),
        err_time datetime
    );
  2.需求:cmd表插入数据的success如果值为no 则去errlog表中插入一条记录
    delimiter $$  # 将mysql默认的结束符由;换成$$
    create trigger tri_after_insert_cmd after insert on cmd for each row
    begin
        if NEW.success = 'no' then  # 新记录都会被MySQL封装成NEW对象
            insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time);
        end if;
    end $$
    delimiter ;  # 结束之后记得再改回来,不然后面结束符就都是$$了
  3.仅仅往cmd表中插入数据
  	INSERT INTO cmd (
          USER,
          priv,
          cmd,
          sub_time,
          success
    )VALUES
        ('kevin','0755','ls -l /etc',NOW(),'yes'),
        ('kevin','0755','cat /etc/passwd',NOW(),'no'),
        ('kevin','0755','useradd xxx',NOW(),'no'),
        ('kevin','0755','ps aux',NOW(),'yes');
  4.触发器其他补充
  	查看当前库下所有的触发器信息
    	show triggers\G;
    删除当前库下指定的触发器信息
    	drop trigger 触发器名称;

2.2 存储过程

类似于python中的自定义函数

# 相当于定义函数
delimiter $$
create procedure p1()
begin
	select * from cmd;
end $$
delimiter ;

# 相当于调用函数
call p1()

"""
类似于有参函数
  delimiter $$
  create procedure p1(
      in m int,  # in表示这个参数必须只能是传入不能被返回出去
      in n int,  
      out res int  # out表示这个参数可以被返回出去,还有一个inout表示即可以传入也可以被返回出去
  )
  begin
      select tname from userinfo where id > m and id < n;
      set res=0;  # 用来标志存储过程是否执行
  end $$
  delimiter ;

# 针对res需要先提前定义
  set @res=10;  定义
  select @res;  查看
  call p1(1,5,@res)  调用
  select @res  查看

查看存储过程具体信息
	show create procedure pro1;
查看所有存储过程
	show procedure status;
删除存储过程
	drop procedure pro1;
"""

2.3 函数

"ps:可以通过help 函数名    查看帮助信息!"
# 1.移除指定字符
Trim、LTrim、RTrim

# 2.大小写转换
Lower、Upper

# 3.获取左右起始指定个数字符
Left、Right

# 4.返回读音相似值(对英文效果)
Soundex
"""
eg:客户表中有一个顾客登记的用户名为J.Lee
		但如果这是输入错误真名其实叫J.Lie,可以使用soundex匹配发音类似的
		where Soundex(name)=Soundex('J.Lie')
"""
# 5.日期格式:date_format
'''在MySQL中表示时间格式尽量采用2022-11-11形式'''
CREATE TABLE blog (
    id INT PRIMARY KEY auto_increment,
    NAME CHAR (32),
    sub_time datetime
);
INSERT INTO blog (NAME, sub_time)
VALUES
    ('第1篇','2015-03-01 11:31:21'),
    ('第2篇','2015-03-11 16:31:21'),
    ('第3篇','2016-07-01 10:21:31'),
    ('第4篇','2016-07-22 09:23:21'),
    ('第5篇','2016-07-23 10:11:11'),
    ('第6篇','2016-07-25 11:21:31'),
    ('第7篇','2017-03-01 15:33:21'),
    ('第8篇','2017-03-01 17:32:21'),
    ('第9篇','2017-03-01 18:31:21');
select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');
1.where Date(sub_time) = '2015-03-01'
2.where Year(sub_time)=2016 AND Month(sub_time)=07;
# 更多日期处理相关函数 
	adddate	增加一个日期 
	addtime	增加一个时间
	datediff	计算两个日期差值
  ...

2.4 流程控制

# python if判断
	if 条件:
    子代码
  elif 条件:
    子代码
  else:
    子代码
# js if判断
	if(条件){
    子代码
  }else if(条件){
    子代码
  }else{
    子代码
  }
# MySQL if判断
	if 条件 then
        子代码
  elseif 条件 then
        子代码
  else
        子代码
  end if;
  
# MySQL while循环
	DECLARE num INT ;
  SET num = 0 ;
  WHILE num < 10 DO
    SELECT num ;
    SET num = num + 1 ;
  END WHILE ;

2.5 索引

# 索引就是一种数据结构
	类似于书的目录。意味着以后再查数据应该先找目录再找数据,而不是用翻页的方式查询数据
  
索引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构
	primary key 	主键
  unique	key		唯一键
  index 	key   索引键
上面三种key前两种除了有加速查询的效果之外还有额外的约束条件(primary key:非空且唯一,unique key:唯一),而index key没有任何约束功能只会帮你加速查询
# ps:foreign key不是用来加速查询用的,不在我们研究范围之内

# 索引的基本用法
id	name	pwd		post_comment  addr  age 
	基于id查找数据很快 但是基于addr查找数据就很慢 
  	解决的措施可以是给addr添加索引
'''索引虽然好用 但是不能无限制的创建!!!'''
**索引的影响:**
	* 在表中有大量数据的前提下,创建索引速度会很慢
	* 在索引创建完毕后,对表的查询性能会大幅度提升,但是写的性能会降低

索引的底层数据结构是b+树
	b树 红黑树 二叉树 b*树 b+树
  	上述结构都是为了更好的基于树查找到相应的数据

只有叶子结点存放真实数据,根和树枝节点存的仅仅是虚拟数据
查询次数由树的层级决定,层级越低次数越少
一个磁盘块儿的大小是一定的,那也就意味着能存的数据量是一定的。如何保证树的层级最低呢?一个磁盘块儿存放占用空间比较小的数据项
思考我们应该给我们一张表里面的什么字段字段建立索引能够降低树的层级高度>>> 主键id字段

"""
聚集索引(primary key)
辅助索引(unique key,index key)
	查询数据的时候不可能都是用id作为筛选条件,也可能会用name,password等字段信息,那么这个时候就无法利用到聚集索引的加速查询效果。就需要给其他字段建立索引,这些索引就叫辅助索引

叶子结点存放的是辅助索引字段对应的那条记录的主键的值(比如:按照name字段创建索引,那么叶子节点存放的是:{name对应的值:name所在的那条记录的主键值})
数据查找 如果一开始使用的是辅助索引 那么还需要使用聚焦索引才可以获取到真实数据

覆盖索引:只在辅助索引的叶子节点中就已经找到了所有我们想要的数据
	select name from user where name='jason';
非覆盖索引:虽然查询的时候命中了索引字段name,但是要查的是age字段,所以还需要利用主键才去查找
	select age from user where name='jason';
"""

posted on 2022-05-10 00:08  淦白嫖怪  阅读(143)  评论(0)    收藏  举报

导航