包含updatesetin的词条
Mysql查询将查询的结果进行更新
有时候我们会不小心对一个大表进行了 update,比如说写错了 where 条件......
此时,如果 kill 掉 update 线程,那回滚 undo log 需要不少时间。如果放置不管,也不知道 update 会持续多久。
那我们能知道 update 的进度么?
实验
我们先创建一个测试数据库:
快速创建一些数据:
连续执行同样的 SQL 数次,就可以快速构造千万级别的数据:
查看一下总的行数:
我们来释放一个大的 update:
然后另起一个 session,观察 performance_schema 中的信息:
可以看到,performance_schema 会列出当前 SQL 从引擎获取的行数。
等 SQL 结束后,我们看一下 update 从引擎总共获取了多少行:
可以看到该 update 从引擎总共获取的行数是表大小的两倍,那我们可以估算:update 的进度 = (rows_examined) / (2 * 表行数)
??小贴士
information_schema.tables 中,提供了对表行数的估算,比起使用 select count(1) 的成本低很多,几乎可以忽略不计。
那么是不是所有的 update,从引擎中获取的行数都会是表大小的两倍呢?这个还是要分情况讨论的,上面的 SQL 更新了主键,如果只更新内容而不更新主键呢?我们来试验一下:
等待 update 结束,查看 row_examined,发现其刚好是表大小:
那我们怎么准确的这个倍数呢?
一种方法是靠经验:update 语句的 where 中会扫描多少行,是否修改主键,是否修改唯一键,以这些条件来估算系数。
另一种方法就是在同样结构的较小的表上试验一下,获取倍数。
这样,我们就能准确估算一个大型 update 的进度了。
sql 请教update语句in多个值时,进行多次更新
在数据库的操作中,更新数据,是很常见的情况。其中sql 请教update语句in多个值时,进行多次更新的方法为:
1、创建一个临时表,用于演示sqlserver语法中update更新修改使用方法。
2、创建另外一个临时表,用于演示如何将一个临时表的数据更新到另外一个临时表。
3、往临时表中插入几行测试数据,其中的Total栏位都不插入值。
4、查询临时表中的测试数据select * from #tblUpdate;select * from #tblTotal。
5、使用update更新临时表#tblUpdate中的Total结果,假设Total = num * price update #tblUpdate set Total = Num * Price。
6、再次查询临时表#tblUpdate的结果,可以看到之前为NULL的Total列都有值了。
注意事项:
SQL的核心部分相当于关系代数,但又具有关系代数所没有的许多特点,如聚集、数据库更新等。它是一个综合的、通用的、功能极强的关系数据库语言。
update语句中条件限制是不能用in语句的吗
一、要求
当然此表你在文件存储时可以这样表示
1,li,22,18230393840,IT,2013-06-01 现需要对这个员工信息文件,实现增删改查操作
1.?可进行模糊查询,语法至少支持下面3种:
1.?select?name,age?from?staff_table?where?age??22
2.?select??*?from?staff_table?where?dept?=?"IT"
3.?select??*?from?staff_table?where?enroll_date?like?"2013“
2.?可修改员工信息,语法如下:
1.?UPDATE?staff_table?SET?dept="Market"?WHERE?where?dept?=?"IT"
注意:以上需求,要充分使用函数,请尽你的最大限度来减少重复代码!
二、实现流程第一部分:SQL解析
1.接收用户SQL
判断用户输入是否为SQL
2.SQL解析主函数sql_parse
where_parse
three_parse
insert_parse
delete_parse
update_parse
select_parse
分发SQL给对应语句的函数来做解析
解析后交给handle_parse,来控制返回
解析SQL语句中的多条件
返回解析后的SQL
第二部分:SQL执行
1.接收解析后的SQL
2.SQL执行主函数sql_action
where_action
logic_action
limit_action
search_action
insert
delete
update
select
分发SQL给对应函数来执行
执行SQL语句时的多条件
返回执行SQL的结果
三、图解
代码:
#/usr/local/env?python
#_*_coding:utf-8_*_
#第一部分:sql解析
import?os
def?sql_parse(sql):?#用户输入sql?转成结构化的字典
????'''
????第一步:sql解析?流程
????1.收到?sql查询条件
????2.sql_parse?来分发要求给?select_parse
????3.select_parse?调用?handle_parse?解析sql
????4.handle_parse?返回解析sql后的结果?sql_dic?给?select_parse
????5.select_parse?把?sql_dic?返回给sql_parse
????sql_dic=sql_parse(sql)?#用户输入sql?转成结构化的字典sql_dic
????sql语句四种操作格式:insert?delete?update?select
????提取用户输入sql?的操作关键词?再进行分析和分发操作
????把sql字符串切分,提取命令信息,分发给具体解析函数去解析
????:param?sql:用户输入的字符串
????:return:返回字典格式sql解析结果
????'''
????#sql命令操作?解析函数的字典??根据用户的命令来找相对应的函数
????parse_func={
????????'insert':insert_parse,
????????'delete':delete_parse,
????????'update':update_parse,
????????'select':select_parse,
????}
????#print('用户输入?sql?str?is?:?%s'?%sql)?#打印用户输入的sql
????sql_l=sql.split('?')?#按空格切割用户sql?成列表?方便提取命令信息
????func=sql_l[0]?#取出用户的sql命令
????#判断用户输入的sql命令?是否在定义好的sql命令函数的字典里面,如果不在字典里面,则返回空
????res=''
????if?func?in?parse_func:
????????res=parse_func[func](sql_l)?#把切割后的?用户sql的列表?传入对应的sql命令函数里
????return?res
def?insert_parse(sql_l):
????'''
????定义insert语句的语法结构,执行sql解析操作,返回sql_dic
????:param?sql:sql按照空格分割的列表
????:return:返回字典格式的sql解析结果
????'''
????sql_dic={
????????'func':insert,?#函数名
????????'insert':[],???#insert选项,留出扩展
????????'into':[],?????#表名
????????'values':[],???#值
????}
????return?handle_parse(sql_l,sql_dic)
def?delete_parse(sql_l):
????'''
????定义delete语句的语法结构,执行sql解析操作,返回sql_dic
????:param?sql:sql按照空格分割的列表
????:return:返回字典格式的sql解析结果
????'''
????sql_dic?=?{
????????'func':?delete,
????????'delete':?[],??#?delete选项,留出扩展
????????'from':?[],??#?表名
????????'where':?[],??#?filter条件
????}
????return?handle_parse(sql_l,?sql_dic)
def?update_parse(sql_l):
????'''
????定义update语句的语法结构,执行sql解析操作,返回sql_dic
????:param?sql:sql按照空格分割的列表
????:return:返回字典格式的sql解析结果
????'''
????sql_dic?=?{
????????'func':?update,
????????'update':?[],??#?update选项,留出扩展
????????'set':?[],??#?修改的值
????????'where':?[],??#?filter条件
????}
????return?handle_parse(sql_l,?sql_dic)
def?select_parse(sql_l):
????'''
????定义select语句的语法结构,执行sql解析操作,返回sql_dic
????:param?sql:sql按照空格分割的列表
????:return:返回字典格式的sql解析结果
????'''
????#?print('from?in?the?select_parse?:\033[42;1m%s\033[0m'?%sql_l)
????#?select语句多种条件查询,列成字典,不同条件不同列表
????sql_dic={
????????'func':select,?#执行select语句
????????'select':[],?#查询字段
????????'from':[],???#数据库.表
????????'where':[],??#filter条件,怎么找
????????'limit':[],??#limit条件,限制
????}
????return?handle_parse(sql_l,sql_dic)
def?handle_parse(sql_l,sql_dic):?#专门做sql解析操作
????'''
????执行sql解析操作,返回sql_dic
????:param?sql_l:?sql按照空格分割的列表
????:param?sql_dic:?待填充的字典
????:return:?返回字典格式的sql解析结果
????'''
????#?print('sql_l?is?\033[41;1m%s\033[0m?\nsql_dic?is?\033[41;1m%s\033[0m'?%(sql_l,sql_dic))
????tag=False??#设置警报?默认是关闭False
????for?item?in?sql_l:??#循环?按空格切割用户sql的列表
????????if?tag?and?item?in?sql_dic:?#判断警报拉响是True?并且用户sql的条件?在条件select语句字典里面,则关闭警报
????????????tag=False?#关闭警报
????????if?not?tag?and?item?in?sql_dic:?#判断警报没有拉响?并且用户sql的条件?在条件select语句字典里面
????????????tag=True?#拉响警报
????????????key=item?#取出用户sql的条件
????????????continue?#跳出本次判断
????????if?tag:?#判断报警拉响
????????????sql_dic[key].append(item)?#把取出的用户sql?添加到?select语句多种条件对应的字典里
????if?sql_dic.get('where'):?#判断?用户sql?where语句
????????sql_dic['where']=where_parse(sql_dic.get('where'))?#['id4','and','id10']?#调用where_parse函数?把整理好的用户sql的where语句?覆盖之前没整理好的
????#?print('from?in?the?handle_parse?sql_dic?is?\033[43;1m%s\033[0m'?%sql_dic)
????return?sql_dic?#返回?解析好的?用户sql?字典
def?where_parse(where_l):?#['id','4','and','id','10']?---?#['id4','and','id10']
????'''
????分析用户sql?where的各种条件,再拼成合理的条件字符串
????:param?where_l:用户输入where后对应的过滤条件列表
????:return:
????'''
????res=[]??#存放最后整理好条件的列表
????key=['and','or','not']??#逻辑运算符
????char=''??#存放拼接时的字符串
????for?i?in?where_l:??#循环用户sql
????????if?len(i)?==?0?:continue??#判断?长度是0?就继续循环
????????if?i?in?key:
????????????#i为key当中存放的逻辑运算符
????????????if?len(char)?!=?0:??#必须?char的长度大于0
????????????????char=three_parse(char)??#把char字符串?转成列表的形式
????????????????res.append(char)??#把之前char的字符串,加入res?#char='id4'---char=['id','','4']
????????????????res.append(i)??#把用户sql?的逻辑运算符?加入res
????????????????char=''??#清空?char?,为了下次加入char到res时?数据不重复
????????else:
????????????char+=i??#'id4'?#除了逻辑运算符,都加入char?#char='id10'---char=['id','','4']
????else:
????????char?=?three_parse(char)??#?把char字符串?转成列表的形式
????????res.append(char)??#循环完成后?char里面有数据?,再加入到res里面
????#?['id4','and','id10']?---?#['id','','4','and','id','','10']
????#?print('from?in?the?where_parse?res?is?\033[43;1m%s\033[0m'?%?res)
????return?res??#返回整理好的?where语句列表
def?three_parse(exp_str):??#?把where_parse函数里面?char的字符串?转成字典
????'''
????将每一个小的过滤条件如,name=1转换成['name','=','1']
????:param?exp_str:条件表达式的字符串形式,例如'name=1'
????:return:
????'''
????key=['','','=']??#区分运算符
????res=[]???#定义空列表?存放最终值
????char=''??#拼接?值的字符串
????opt=''???#拼接?运算符
????tag=False???#定义警报
????for?i?in?exp_str:??#循环?字符串和运算符
????????if?i?in?key:??#判断?当是运算符时
????????????tag=True???#拉响警报
????????????if?len(char)?!=?0:??#判断char的长度不等于0时(方便添加连续运算符)才做列表添加
????????????????res.append(char)??#把拼接的字符串加入?res列表
????????????????char=''???#清空char?使下次循环不重复添加数据到res列表
????????????opt+=i????#把循环的运算符加入opt
????????if?not?tag:???#判断?警报没有拉响
????????????char+=i????#把循环的字符串加入?char
????????if?tag?and?i?not?in?key:?#判断?警报拉响(表示上次循环到运算符),并且本次循环的不是运算符
????????????tag=False??#关闭警报
????????????res.append(opt)??#把opt里面的运算符?加入res列表
????????????opt=''??#清空opt?使下次循环不重复添加数据到res列表
????????????char+=i?#把循环到的?字符串加入char
????else:
????????res.append(char)?#循环结束,把最后char的字符串加入res列表
????#新增解析?like的功能
????if?len(res)?==?1:??#判断?['namelike李']?是个整体
????????res=res[0].split('like')??#以like切分字符串
????????res.insert(1,'like')??#加入like字符串,因为上面切分的时候剔除了like
????#?print('three_parse?res?is?\033[43;1m%s\033[0m'?%?res)
????return?res??#返回res列表结果
#第二部分:sql执行
def?sql_action(sql_dic):?#接收用户输入的sql?的结构化的字典??然后执行sql
????'''
????从字典sql_dic提取命令,分发给具体的命令执行函数去执行
????执行sql的统一接口,内部执行细节对用户完全透明
????:param?sql_dic:
????:return:
????'''
????return?sql_dic.get('func')(sql_dic)?#接收用户sql,分发sql,执行命令
def?insert(sql_dic):
????print('insert?%s'?%sql_dic)
????db,table=sql_dic.get('into')[0].split('.')??#切分文件路径,相对应数据库,表
????with?open('%s/%s'?%(db,table),'ab+')?as?fh:??#安装上面的路径?打开文件?ab+模式
????????#?读出文件最后一行,赋值给last?配合+
????????offs?=?-100??#
????????while?True:
????????????fh.seek(offs,2)
????????????lines?=?fh.readlines()
????????????if?len(lines)1:
????????????????last?=?lines[-1]
????????????????break
????????????offs?*=?2
????????last=last.decode(encoding='utf-8')
????????last_id=int(last.split(',')[0])??#取出最后一行id号
????????new_id=last_id+1???#id号加1?实现id自增效果
????????#insert?into?db1.emp?values?alex,30,18500841678,运维,2007-8-1
????????record=sql_dic.get('values')[0].split(',')???#提取用户想要?添加的sql
????????record.insert(0,str(new_id))??#加入自增后的id?到用户sql的头部
????????#['26','alex','35','13910015353','运维','2005?-?06?-?27\n']
????????record_str=','.join(record)+'\n'??#把用户sql列表切成字符串
????????fh.write(bytes(record_str,encoding='utf-8'))??#把添加?id后的用户想添加的sql??用bytes写入文件
sql update set in
UPDATE tab a
SET beactive= '否'
FROM TABLE1
WHERE TABLE1.beactive IN (SELECT beactive FROM tab b )