Oracle数据库批量foreach涉及union all插入自增长主键实现方案
2016-11-26 00:00
204 查看
摘要: 在Oracle数据库中采用MyBatis框架进行数据的foreach批量插入时涉及了union all 出现的种种问题进行总结。也源于自己对Oracle的不熟悉。
事件发生的背景同动弹同步,我接到了一个把我的项目从mysql迁移到oracle数据库的噩耗。本来以为这事件麻烦的事儿,但是实际情况比我想的麻烦的多。
顺便总结一下我换库遇到的种种问题:
1、mysql和oracle的分页方式不一样,涉及到分页的地方要注意
2、oracle的自增长要写函数自己实现,并不能像MySql那样去直接用自增长属性
3、mysql中的很多常用字段如 id,name,sort,description...在Oracle中被强制为关键字占用,所以你在mysql中导出的建表语句并不适用
4、mysql和oracle中字段类型不通用,这也导致了你mysql中导出的建表语句并不适用
5、日期字段的处理,这个我就不多说了
6、空字符的处理,MYSQL的非空字段也有空的内容,ORACLE里定义了非空字段就不容许有空的内容。按MYSQL的NOT NULL来定义ORACLE表结构,导数据的时候会产生错误。因此导数据时要对空字符进行判断,如果为NULL或空字符,需要把它改成一个空格的字符串。
这些都是次要的,下面我们来切入主题:
第一步,实现oracle的自增长,首先你要有一个序列
定义好sequence后,你就可以用currVal,nextVal取得值。
CurrVal:返回 sequence的当前值
NextVal:增加sequence的值,然后返回 增加后sequence值
然后在进行插入操作时就可以:
第二步,也是我们要处理的问题了:我在mybatis中涉及了批量的插入使用了foreach,然后我把当时在mysql底下的xml问题贴出来。
然后这个肯定是不行的啊,没有rm_id的自增长主键。所以我就稍微修改了下:
理所应当的把portal_sequence.nextval加上去了,然后测试了一下,竟然成功了,然后我继续测了一下才发现,在list.size()<=1的时候是没问题的,一旦list里面有两条/两条以上的记录时就涉及到了union all,然后就又不成功了。
经过网上一翻查找,最后定义到了问题,要先创建函数才可以,创建函数get_seq()
然后我把我xml里面的foreach修改为如下情况,在调用序列的时候通过我的get_seq()函数来调用:
问题完美解决,这个bug浪费时间超过两个,在此记录下。
附带贴上mybatis中的转移字符如下:
因为这个是xml格式的,所以不允许出现类似“>”这样的字符,但是都可以使用<![CDATA[ ]]>符号进行说明,将此类符号不进行解析
你的可以写成这个:
mapper文件示例代码
事件发生的背景同动弹同步,我接到了一个把我的项目从mysql迁移到oracle数据库的噩耗。本来以为这事件麻烦的事儿,但是实际情况比我想的麻烦的多。
顺便总结一下我换库遇到的种种问题:
1、mysql和oracle的分页方式不一样,涉及到分页的地方要注意
2、oracle的自增长要写函数自己实现,并不能像MySql那样去直接用自增长属性
3、mysql中的很多常用字段如 id,name,sort,description...在Oracle中被强制为关键字占用,所以你在mysql中导出的建表语句并不适用
4、mysql和oracle中字段类型不通用,这也导致了你mysql中导出的建表语句并不适用
5、日期字段的处理,这个我就不多说了
6、空字符的处理,MYSQL的非空字段也有空的内容,ORACLE里定义了非空字段就不容许有空的内容。按MYSQL的NOT NULL来定义ORACLE表结构,导数据的时候会产生错误。因此导数据时要对空字符进行判断,如果为NULL或空字符,需要把它改成一个空格的字符串。
这些都是次要的,下面我们来切入主题:
第一步,实现oracle的自增长,首先你要有一个序列
CREATE SEQUENCE portal_sequence --序列名 INCREMENT BY 1 -- 每次加几个 START WITH 250 -- 从1开始计数 NOMAXVALUE -- 不设置最大值 NOCYCLE; -- 一直累加,不循环 ;
定义好sequence后,你就可以用currVal,nextVal取得值。
CurrVal:返回 sequence的当前值
NextVal:增加sequence的值,然后返回 增加后sequence值
然后在进行插入操作时就可以:
insert into p_sys_rolemenu (rm_id,role_id, menu_id,creator, create_time,update_time,updator, is_deleted) select get_seq('portal_sequence.nextval') , 2,113,053023,sysdate,sysdate,053023,0 from dual
第二步,也是我们要处理的问题了:我在mybatis中涉及了批量的插入使用了foreach,然后我把当时在mysql底下的xml问题贴出来。
<insert id="insert" parameterType="com.aneop.sys.userfunc.entity.RoleMenu" > insert into t_sys_rolemenu (role_id, menu_id,creator, create_time,update_time,updator, is_deleted) <foreach collection="list" separator="UNION ALL" item="item"> select #{item.roleId},#{item.menuId},#{item.creator},NOW(),NOW(),#{item.creator},0 </foreach> </insert>
然后这个肯定是不行的啊,没有rm_id的自增长主键。所以我就稍微修改了下:
理所应当的把portal_sequence.nextval加上去了,然后测试了一下,竟然成功了,然后我继续测了一下才发现,在list.size()<=1的时候是没问题的,一旦list里面有两条/两条以上的记录时就涉及到了union all,然后就又不成功了。
<insert id="insert" parameterType="com.ane56.sys.userfunc.entity.RoleMenu" > insert into p_sys_rolemenu (rm_id,role_id, menu_id,creator, create_time,update_time,updator, is_deleted) <foreach collection="list" separator="UNION ALL" item="item"> select portal_sequence.nextval, #{item.roleId},#{item.menuId},#{item.creator},sysdate,sysdate,#{item.creator},0 from dual </foreach> </insert>
经过网上一翻查找,最后定义到了问题,要先创建函数才可以,创建函数get_seq()
create or replace function get_seq (p_in_sqname in varchar2) return number is l_res number ; begin execute immediate 'select '|| p_in_sqname|| '.nextval from dual' into l_res ; return l_res ; end ;
然后我把我xml里面的foreach修改为如下情况,在调用序列的时候通过我的get_seq()函数来调用:
<insert id="insert" parameterType="com.ane56.sys.userfunc.entity.RoleMenu" > insert into p_sys_rolemenu (rm_id,role_id, menu_id,creator, create_time,update_time,updator, is_deleted) <foreach collection="list" separator="UNION ALL" item="item"> select get_seq('portal_sequence.nextval'), #{item.roleId},#{item.menuId},#{item.creator},sysdate,sysdate,#{item.creator},0 from dual </foreach> </insert>
问题完美解决,这个bug浪费时间超过两个,在此记录下。
附带贴上mybatis中的转移字符如下:
< | > | 大于号 |
> | < | 小于号 |
& | & | 和 |
' | ' | 单引号 |
" | " | 双引号 |
你的可以写成这个:
mapper文件示例代码
<![CDATA[ where rowno <=60 and rowno >=40 ]]>
相关文章推荐
- 使用mybatis 实现批量插入,主键自增长
- mysql实现插入一条记录时候还回主键值,表的主键是自增长方式AUTO_INCREMENT
- oracle主键自动增长的实现 Oracle Sequence oracle maxid自动生成--ORA-00001: 违反唯一约束条件 (NAME.SYS_C005547)产生的原因之一(select * from all_cons_columns w
- UNION ALL实现的分级汇总示例.sql
- mysql 插入数据失败防止自增长主键增长的方法
- Hibernate + Oracle实现主键自增长
- Oracle 实现主键自动增长之序列,触发器
- mysql 插入数据失败防止自增长主键增长的方法
- 在Oracle下基于序列和触发器实现主键自增长
- Oracle实现插入记录ID自增长
- 2017.9.15 mybatis批量插入后实现主键回填
- 润乾报表实现主键自增长
- ibatis annotations 注解方式返回刚插入的自增长主键ID的值--转
- MySql 使用foreach标签 批量插入list中数据,主键自增,插入
- 关于如何获得数据库插入操作中数据的自增长主键的值
- 2017.9.15 mybatis批量插入后实现主键回填
- mysql主主同步两个数据库同时写入,实现原理:自动增长主键不重复
- spring JdbcTemplate下访问Oracle数据库插入数据时返回序列增长的主键
- Mybatis 插入一条或批量插入 返回带有自增长主键记录的实例
- 数据库insert and update--查询是否主键存在和插入语句用一条sql来实现。