oracle如何快速地插入一千万条数据

时间:2020-12-26 23:27:18
数据库中有A表和B表,A表有一千万条数据,B表是空表,如何快速地把A表数据移到B表中。

9 个解决方案

#1


两个表的表结构是一样的吗

#2


引用 1 楼 wildwave 的回复:
两个表的表结构是一样的吗

不一样的,表A中有个varchar2字段,我要把它转为blob字段再插入到表B的另一个字段中

#3


如果B原来就是空表,不是某张大表经过delete变成的那种空表。加个append提示来进行insert
 insert /*+append*/ into B select ......... from A

#4


引用 3 楼 wildwave 的回复:
如果B原来就是空表,不是某张大表经过delete变成的那种空表。加个append提示来进行insert
 insert /*+append*/ into B select ......... from A

delete与否有什么区别啊?因为之前是有一些数据的,删过了,这样的话需要drop掉这张表重建吗?
还有我看到网上说append配合nologging一起使用比较好,alter table nologging之后插入数据,再执行altere table logging,这样可以吗?有没有什么影响

#5


可以这么做。但是用了no_logging,不产生redo时,如果用了数据库同步工具,可能会对同步造成影响
对备份恢复也会造成影响

如果先前delete过,且原来的数据量较大,在用append前,先将空表做个truncate操作降低水位即可,不用重建

#6


引用 5 楼 wildwave 的回复:
可以这么做。但是用了no_logging,不产生redo时,如果用了数据库同步工具,可能会对同步造成影响
对备份恢复也会造成影响

如果先前delete过,且原来的数据量较大,在用append前,先将空表做个truncate操作降低水位即可,不用重建

这样子啊,谢了啊。还有一个问题想请教下。
A表有detail varchar2字段,B表有detail blob字段,A表的detail列数据里有换行。我直接用insert into B selete V2B(detail) from A,这样B表中的detail列的显示的数据和A表的的detail列一致。但是如果用触发器,即A表插入一条数据后触发添加数据到B表,可是B表得到的数据是没有换行的,这是为什么呢?
可能表述的不太清楚,比如说插入A表数据为



,然后触发器起作用,B表得到的数据是
我爱你。
数据没有换行,这是为什么啊,有什么办法使得数据一致呢?
下面是varchar2转blob的函数

/*---CLOB转换为BLOB---*/
FUNCTION C2B(v_clob IN CLOB DEFAULT EMPTY_CLOB()) RETURN BLOB
AS
  res         BLOB;
  b_len       NUMBER := dbms_lob.getlength(v_clob);
  dest_offset NUMBER := 1;
  src_offset  NUMBER := 1;
  amount_c    INTEGER := DBMS_LOB.lobmaxsize;
  blob_csid   NUMBER := DBMS_LOB.default_csid;
  lang_ctx    INTEGER := DBMS_LOB.default_lang_ctx;
  warning     INTEGER;
BEGIN
  IF b_len>0 THEN
    DBMS_LOB.createtemporary(res,true);
    DBMS_LOB.open(res,DBMS_LOB.lob_readwrite);
    DBMS_LOB.convertToBlob(res,v_clob,amount_c,dest_offset,src_offset,blob_csid,lang_ctx,warning);
  ELSE
    SELECT EMPTY_BLOB() INTO res FROM DUAL;
  END IF;
  RETURN res;
END;

FUNCTION V2B(v_str IN VARCHAR2) RETURN BLOB
AS
  V_CLOB CLOB;
  V_BLOB BLOB;
BEGIN
  IF LENGTH(v_str)>0 THEN
    SELECT TO_CLOB(v_str) INTO V_CLOB FROM DUAL;
    SELECT C2B(V_CLOB) INTO V_BLOB FROM DUAL;
  ELSE
    SELECT EMPTY_BLOB() INTO V_BLOB FROM DUAL;
  END IF;
  RETURN V_BLOB;
END;

#7


可能只是显示的问题。可以拷贝出来,粘贴到别的地方。或是查看字符串长度,是否存在不可见字符

#8


引用 7 楼 wildwave 的回复:
可能只是显示的问题。可以拷贝出来,粘贴到别的地方。或是查看字符串长度,是否存在不可见字符

嗯。

#9


获取一张表的数据,根据两张表的关系进行查询,看另一张表存在重复的数据吗,如果不存在就insert

#1


两个表的表结构是一样的吗

#2


引用 1 楼 wildwave 的回复:
两个表的表结构是一样的吗

不一样的,表A中有个varchar2字段,我要把它转为blob字段再插入到表B的另一个字段中

#3


如果B原来就是空表,不是某张大表经过delete变成的那种空表。加个append提示来进行insert
 insert /*+append*/ into B select ......... from A

#4


引用 3 楼 wildwave 的回复:
如果B原来就是空表,不是某张大表经过delete变成的那种空表。加个append提示来进行insert
 insert /*+append*/ into B select ......... from A

delete与否有什么区别啊?因为之前是有一些数据的,删过了,这样的话需要drop掉这张表重建吗?
还有我看到网上说append配合nologging一起使用比较好,alter table nologging之后插入数据,再执行altere table logging,这样可以吗?有没有什么影响

#5


可以这么做。但是用了no_logging,不产生redo时,如果用了数据库同步工具,可能会对同步造成影响
对备份恢复也会造成影响

如果先前delete过,且原来的数据量较大,在用append前,先将空表做个truncate操作降低水位即可,不用重建

#6


引用 5 楼 wildwave 的回复:
可以这么做。但是用了no_logging,不产生redo时,如果用了数据库同步工具,可能会对同步造成影响
对备份恢复也会造成影响

如果先前delete过,且原来的数据量较大,在用append前,先将空表做个truncate操作降低水位即可,不用重建

这样子啊,谢了啊。还有一个问题想请教下。
A表有detail varchar2字段,B表有detail blob字段,A表的detail列数据里有换行。我直接用insert into B selete V2B(detail) from A,这样B表中的detail列的显示的数据和A表的的detail列一致。但是如果用触发器,即A表插入一条数据后触发添加数据到B表,可是B表得到的数据是没有换行的,这是为什么呢?
可能表述的不太清楚,比如说插入A表数据为



,然后触发器起作用,B表得到的数据是
我爱你。
数据没有换行,这是为什么啊,有什么办法使得数据一致呢?
下面是varchar2转blob的函数

/*---CLOB转换为BLOB---*/
FUNCTION C2B(v_clob IN CLOB DEFAULT EMPTY_CLOB()) RETURN BLOB
AS
  res         BLOB;
  b_len       NUMBER := dbms_lob.getlength(v_clob);
  dest_offset NUMBER := 1;
  src_offset  NUMBER := 1;
  amount_c    INTEGER := DBMS_LOB.lobmaxsize;
  blob_csid   NUMBER := DBMS_LOB.default_csid;
  lang_ctx    INTEGER := DBMS_LOB.default_lang_ctx;
  warning     INTEGER;
BEGIN
  IF b_len>0 THEN
    DBMS_LOB.createtemporary(res,true);
    DBMS_LOB.open(res,DBMS_LOB.lob_readwrite);
    DBMS_LOB.convertToBlob(res,v_clob,amount_c,dest_offset,src_offset,blob_csid,lang_ctx,warning);
  ELSE
    SELECT EMPTY_BLOB() INTO res FROM DUAL;
  END IF;
  RETURN res;
END;

FUNCTION V2B(v_str IN VARCHAR2) RETURN BLOB
AS
  V_CLOB CLOB;
  V_BLOB BLOB;
BEGIN
  IF LENGTH(v_str)>0 THEN
    SELECT TO_CLOB(v_str) INTO V_CLOB FROM DUAL;
    SELECT C2B(V_CLOB) INTO V_BLOB FROM DUAL;
  ELSE
    SELECT EMPTY_BLOB() INTO V_BLOB FROM DUAL;
  END IF;
  RETURN V_BLOB;
END;

#7


可能只是显示的问题。可以拷贝出来,粘贴到别的地方。或是查看字符串长度,是否存在不可见字符

#8


引用 7 楼 wildwave 的回复:
可能只是显示的问题。可以拷贝出来,粘贴到别的地方。或是查看字符串长度,是否存在不可见字符

嗯。

#9


获取一张表的数据,根据两张表的关系进行查询,看另一张表存在重复的数据吗,如果不存在就insert