事务索引等

事务索引等

 

pymysql 模块
import pymysql
conn=pymysql.connect(
	host='127.0.0.1',
    port=3306,
    user='账户名',
    passwd='密码',
    database='数据库名称'
    charset='utf8',
    autocommit=True
)

cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)#制作游标对象
sql='select * from userinfo'#编写sql语句
#执行sql语句
cursor.execute(sql) 
cursor.executemany(sql,[(),()])#多个sql语句列表里套元组 
#获取执行结果
cursor.fetchall   #所有
cursor.fetchone   #第一个
cursor.fetchmany  #多个

注册登录功能

def register(cursor):
    username=input('输入你要注册的用户').strip()
    sql = 'select * from userinfo where name=%s'
    cursor.execute(sql,(username))
    res=cursor.fetchall()
    if not res:
        password=input('请输入密码').strip()
        sql1='insert into userinfo(name,password) values(%s,%s)'
        cursor.execute(sql1,(username,password))
        print('用户%s注册成功'%username)
    else:
        print('用户已存在')

def login(cursor):
    username=input('请输入你要登录的用户').strip()
    sql='select * from userinfo where name=%s'
    cursor.execute(sql,(username))
    res=cursor.fetchall()
    if res :
        password=input('请输入密码').strip()
        # print(res)
        dict_name=res[0]  #列表套字典
        if str(dict_name.get('password'))==password:
            print('登陆成功')
        else:
            print('密码错误')

    else:
        print('账户不存在')




def loginout(cursor):
    cursor.close
    print('退出成功')
    exit()


def get_conn():
    import pymysql

    conn=pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123',
        charset='utf8',
        database='db5_1',
        autocommit=True
    )

    cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)
    return cursor

func_dic={'1':register,'2':login ,'3':loginout}

while True:
    cursor=get_conn()
    print('''
    1.注册功能
    2.登录功能
    3.退出
    
    ''')
    choise=input('请输入你要选择的编号').strip()
    if choise in func_dic:
        func_name=func_dic.get(choise)
        func_name(cursor)
    else:
        print('输入有误,请从新输入')

 

  • 视图(了解)
  • 触发器(了解,但是比视图有用)
  • 存储过程(了解)
  • 流程控制(了解)
  • 内置函数
  • 事务(重点)
  • 索引(二叉树、b树、b+树、b*树)与慢查询优化(explain语句)

视图(view)

将SQL语句的查询结果当做虚拟表实体化保存起来,以后可以反复使用 #(一般不使用因为在cmd它显示是个表,其实本质在Navicat里看是view视图)

create view teacher2course as
select * from teacher inner join course on teacher.tid = course.teacher_id;

drop view teacher2course;
# 视图使用频率不高

触发器(了解)trigger

满足特定条件执行  类似于crontab(定时器)
#在mysql中只有满足 
#三大类 :
    增加
    删除
    修改
#六小类:
    增加前,增加后
    删除前,删除后
    修改前,修改后
#语法结构  befor:之前  after:之后  for each row:每一行
create trigger 触发器的名字 before/after insert/update/delete on 表名 for each row
begin
	sql语句
end
#命名规则
	tri_after_insere_t1
	触发器_之前/之后_插入/修改/删除_表名
#修改sql语句结束符 之前是; 修改为$$
	delimiter $$ 临时修改

# 在MySQL中NEW特指数据对象可以通过点的方式获取字段对应的数据
#添加一条数据
	id    name	pwd  hobby
	1     zzz  123  read
	NEW.name  >>>  zzz



#触发器实例
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
);

delimiter $$  # 将mysql默认的结束符由;换成$$
create trigger tri_after_insert_cmd after insert on cmd for each row
begin
    if NEW.success = 'no' then  # 新记录都会被MySQL封装成NEW对象 new.字段名 拿到添加的字段数据
        insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time);
    end if;
end $$
delimiter ;  # 结束之后记得再改回来,不然后面结束符就都是$$了

#往表cmd中插入记录,触发触发器,根据IF的条件决定是否插入错误日志
INSERT INTO cmd (
    USER,
    priv,
    cmd,
    sub_time,
    success
)
VALUES
    ('tony','0755','ls -l /etc',NOW(),'yes'),
    ('tony','0755','cat /etc/passwd',NOW(),'no'),
    ('tony','0755','useradd xxx',NOW(),'no'),
    ('tony','0755','ps aux',NOW(),'yes');

# 查询errlog表记录
select * from errlog;
# 查看触发器
show triggers\G;
# 删除触发器
drop trigger tri_after_insert_cmd;

存储过程(了解)

# 类似于python中的自定义函数 定义个函数
#存储过程在哪个库下面创建的只能在对应的库下面使用
# 1.无参存储过程
delimiter $$ #修改默认结束符,临时修改
create procedure p1()
begin
	select * from user;
end $$
delimiter ;
# 调用函数
call p1()
----------------------------------------------------
# 2.有参存储过程

set @res =10  #定义变量 
select @res #查看变量  res=10


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

#调用
call p2(2,4,10) #报错
call p2(2,4,@res);
select @res  #发现变为0因为存储过程里把res修改成0了

#查看存储过程具体信息
	show create procedure 函数名;
#查看所有存储过程
	show procedure status;
#删除存储过程
	drop procedure 函数名;

------------------------------------------------------------------------------------------
# 代码操作存储过程
import pymysql
conn = pymysql.connect(
    host='127.0.0.1',
    port=3306,
    user='root',
    passwd='123',
    db='db6',
    charset='utf8',
    autocommit=True
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.callproc('p2',(1,3,10))
# @_p1_0=1,@_p1_1=3,@_p1_2=10;    上面对应的那三个数字变形成下面这个
print(cursor.fetchall())


流程控制(了解)

# if判断
if  条件 then
	子代码;
    #不满足条件会执行下面的
elseif 条件1 then
	子代码;
else #上面都不满足
	子代码
 endif
-----------------------------------------------------------------
if i = 1 THEN
       SELECT 1;
ELSEIF i = 2 THEN
       SELECT 2;
ELSE
       SELECT 7;
END IF;

# while循环

while 条件 do
	满足执行这个;
    改变条件;
end while    

SET num = 0 ;
WHILE num < 10 DO
    SELECT
        num ;
    SET num = num + 1 ;
END WHILE ;

内置函数

#只能在sql语句中使用 不能单独调用   
#help 内置函数名   可以查看内置函数怎么用
help trim
mysql> SELECT TRIM('  bar   ');
        -> 'bar'
mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
        -> 'barxxx'
mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
        -> 'bar'
mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
        -> 'barx'
# 1.移除指定字符
Trim、LTrim、RTrim

# 2.大小写转换
Lower、Upper

mysql> SET @str = BINARY 'New York';
mysql> SELECT LOWER(@str), LOWER(CONVERT(@str USING latin1));

mysql> SELECT UPPER('Hej');
        -> 'HEJ'

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

mysql> SELECT LEFT('foobarbar', 5);
        -> 'fooba'

mysql> SELECT RIGHT('foobarbar', 4);
        -> 'rbar'

# 4.返回读音相似值(对英文效果)
Soundex #目前只对英文有效
"""
eg:客户表中有一个顾客登记的用户名为J.Lee
		但如果这是输入错误真名其实叫J.Lie,可以使用soundex匹配发音类似的
	#####	where Soundex(name)=Soundex('J.Lie')
"""

# 5.日期格式:date_format
'''在MySQL中表示时间格式尽量采用2022-11-11形式'''
#创建blog表 添加数据  
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');
    
#按照年月分组
Y  m  d  H  M  S     X
年 月 日 时 分 秒     时分秒

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'  #where 年月日等于
2.where Year(sub_time)=2016 AND Month(sub_time)=07;
# 更多日期处理相关函数 
	adddate	增加一个日期 
	addtime	增加一个时间
	datediff计算两个日期差值
  ...

事务(重点)

四大特性(ACID)
    A:原子性 
        每个事务都是不可分割的最小单位,同一个事务内的多个操作 要么同时成功,要么同时失败
    C:一致性
        执行完事务之后,数据库数据的状态从一个一致性状态变为另一个一致性状态(一致性与原子性是密切相关的)
    I:隔离性(也可以叫独立性)
        事务与事务彼此之间不干扰,每个事务都是彼此独立的
    D:持久性(也叫永久性)
        一个事务一旦提交,他对数据库中数据的改变应该是永久性的
        
# 如何开启事务
start transaction;
开始执行操作数据库代码    #开启事务之后操作数据库代码 没有写入到硬盘 写入到内存 需要commit才可以
# 如何回滚
rollback; #回滚之后 事务就结束了 如果还需要事务需要在启动
# 如何确认
commit;  #commit之后 事务也结束了

索引与慢查询优化

#什么是索引
	简单理解为:加快数据查询速度的工具,也可以比喻成书的目录
    让获取的数据更有目的性,从而提高数据库检索数据的性能
#索引内部基于算法构造出来的   什么是算法
	算法:解决事物的办法
    入门级算法:二分法(不能算算法的算法)  前提必须有序
    	[1,2,3,4,5,6...1000000]8888
        比较中间的 判断数据在那面   然后再对半分比较中间的 以此类推
     python 实现二分法
        l =[1,12,21,31,41,51,61,71,81,91]

        def dichotomy(nums,find_nums):
            print(nums)
            if len(nums)==0:
                print('不存在')
                return
            mid_nums=len(nums)//2  #求中间值索引
            if find_nums>nums[mid_nums]:#要查找的数字大于中间的数字,左面的肯定不是  取右面的
                dichotomy(nums[mid_nums+1:],find_nums) # 在调用这个方法,通过中间值取右面的值
            elif find_nums<nums[mid_nums]:#要查找的数字小于中间的数字,右面的肯定不是 取左面的
                dichotomy(nums[:mid_nums],find_nums)
            else:
                print('你要找的数字为:',nums[mid_nums])


dichotomy(l,41)

数据结构:二叉树:每个节点只能分两个叉

img

数据结构:b树

在这里插入图片描述

查找一个精确数字  :需要三次
查找一个范围数字  :次数由树的高度决定 次数为 层数的倍数
	查找完小于xxx的 再回到开始再找大于yyy的

数据结构:b+树(为了解决范围查找)

在这里插入图片描述

在叶子层加了索引直接到另一个叶子层

数据结构:b*树

在这里插入图片描述

#总结
二叉树(只能分两个叉)
b树 b+(叶子节点添加了指针) b*(枝节点也添加了指针)
# 添加指针是为了加快范围查询的速度

将某个字段添加成索引就相当于依据该字段建立了一颗b+树从而加快查询速度
如果某个字段没有添加索引 那么依据该字段查询数据会非常的慢(一行行查找)

索引的分类

1.primary key
	主键索引除了有加速查询的效果之外 还具有一定的约束条件
2.unique key
	唯一键索引 除了有加速查询的效果之外 还具有一定的约束条件
3.index key
	普通索引 只有加速查询的效果 没有额外约束
4.foreign key 
	# 注意外键不是索引 它仅仅是用来创建表与表之间关系的

数据库设计三大范式

第一范式
	要求确保表中每列的原子性,也就是不可拆分
第二范式
	要求确保表中每列与主键相关,而不能只与主键的某部分相关(主要针对联合主键),主键列与非主键列遵循完全函数依赖关系,也就是完全依赖; 表里的数据都应该和主键有直接关系 完全依赖
第三范式
	确保主键列之间没有传递函数依赖关系,也就是消除传递依赖。确保数据表中的每一列数据都和主键直接相关,而不能间接相关,属性不依赖于其他非主属性


范式优点
结构合理
冗余较小
尽量避免插入删除修改异常
范式缺点
性能降低
多表查询比单表查询速度慢
数据库的设计应该根据当前情况和需求做出灵活的处理
在实际设计中,要整体遵循范式理论
如果在某些特定的情况下还死死遵循范式也是不可取的,因为可能降低数据库的效率,此时可以适当增加冗余而提高性能。
posted @ 2021-11-17 10:17  迪迦张  阅读(21)  评论(0编辑  收藏  举报