0%

达梦数据库插入或更新

记录下在国产达梦数据库中使用merge into来进行数据的更新或新增

使用达梦是因为有国产化需求,因为我这里还不是那种性能敏感的开发,所以对我来说除了在安装上稍微麻烦一点外,使用起来和mysql没有太大的区别,这里使用达梦自己的dmPython库来进行数据库操作

replace into

这部分主要参考以下该篇博客

首先说一下比较常见的replace into操作,在mysql中经常会用到replace into操作。

replace into 首先尝试插入数据到表中:

  1. 如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据。
  2. 否则,直接插入新数据

用法:

1
replace into tbl_name(col_name, …) values(…)

注意事项:

  • 插入数据的表必须有主键或者是唯一索引!否则的话,replace into 会直接插入数据,这将导致表中出现重复的数据。
  • 如果数据库里边有这条记录,则直接修改这条记录;如果没有则,则直接插入,在有外键的情况下,对主表进行这样操作时,因为如果主表存在一条记录,被从表所用时,直接使用replace into是会报错的,这和replace into的内部原理是相关(先删除然后再插入)。
  • 表中有一个自增的主键,会带来的问题:
    • replace操作在自增主键的情况下,遇到唯一键冲突时执行的是delete+insert,但是在记录binlog时,却记录成了update操作,update操作不会涉及到auto_increment的修改。备库应用了binlog之后,备库的表的auto_increment属性不变。如果主备库发生主从切换,备库变为原来的主库,写新的主库则有风险发生主键冲突。
    • 频繁的REPLACE INTO 会造成新纪录的主键的值迅速增大。总有一天。达到最大值后就会因为数据太大溢出了。就没法再插入新纪录了。数据表满了,不是因为空间不够了,而是因为主键的值没法再增加了。

merge into

达梦数据库不是每个版本都支持replace into命令的,而且replace into命令功能比较固定,而且在存在自增主键时还会有一些限制,所以这里我们采用merge into命令来完成达梦数据库的插入或更新

merge into是Oracle的指令,达梦对Oracle的兼容性还比较好,而且开发文档里说明了支持merge into指令。

用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 新增或更新基线
db = dmPython.connect(user=dm_user, password=dm_pwds, server=dm_host, port=dm_port,
cursorclass=dmPython.DictCursor)
cursor = db.cursor()

sql = "merge into %s.%s " \
"using (select ? sIP,? updatetime from dual) t " \
"on(%s.%s.sIP = t.sIP) " \
"when matched then " \
"update set updatetime=t.updatetime " \
"when not matched then " \
"insert (sIP, updatetime) values (t.sIP,t.updatetime)" \
% (dm_db, baseline_table, dm_db, baseline_table)
try:
cursor.executemany(sql, baseline_list_tuple)
db.commit()
print("更新成功")
except Exception as e:
print(e)
db.rollback()
finally:
cursor.close()
db.close()

注意事项:

  • 我看到的资料上面说on后面要跟主键信息,但是我这里使用的不是主键,但是能正常使用
  • merge into是通过执⾏using后括号内的sql语句结果逐条与on括号内条件进⾏匹配,若匹配则执⾏更新,若不匹配则执⾏插⼊
  • when matched then语句需在when not matched then 之前,否则达梦数据库会报错
  • 关于dual表,我个⼈理解为类似于“缓存器”的表,你可以向它⾥⾯插⼊多条数据,删除多条数据,但你查询时,表中均只显⽰⼀个字段,⼀⾏数据。
  • 在使用merge into语句的时候我遇到了一个关于字符型数据的问题,在达梦数据库管理软件中只能使用单引号来框住字符串,用双引号则会报错,这其实不是merge into语句的问题,而是达梦sql语句的问题,很久没用其他数据库了,不知道这是数据库的通用规则,还是达梦的特殊规则。
-------------本 文 结 束 啦 感 谢 您 的 阅 读-------------

欢迎关注我的其它发布渠道