ORACLE:插入对象类型集合的表值
Posted
技术标签:
【中文标题】ORACLE:插入对象类型集合的表值【英文标题】:ORACLE: INSERT INTO Table VALUES of object type collection 【发布时间】:2016-03-20 10:17:45 【问题描述】:已创建以下类型;
CREATE OR REPLACE TYPE OBJ_TYPE AS OBJECT
( FLAG DATE
, NUMB NUMBER(2,0)
, VARC VARCHAR2(40 BYTE));
/
CREATE OR REPLACE TYPE TBL_OBJ_TYPE AS TABLE OF OBJ_TYPE;
/
我想简单地将数据集插入到表中;
DECLARE
DATA_SET TBL_OBJ_TYPE := TBL_OBJ_TYPE();
BEGIN
FOR REC IN (SELECT * FROM TBL_01)
LOOP
DATA_SET.EXTEND;
DATA_SET(DATA_SET.COUNT) :=
OBJ_TYPE( 1
, REC.TBL_01_COL1
, REC.TBL_01_COL2);
END LOOP;
FORALL REC IN DATA_SET.FIRST..DATA_SET.LAST
INSERT INTO TBL_02
VALUES ( DATA_SET(REC).FLAG --listed column
, DATA_SET(REC).NUMB --listed column
, DATA_SET(REC).VARC); --listed column
END;
这个工作正常,但是否有可能更改“VALUES”子句以避免命名源对象中的每个属性?我想要这样的东西:
VALUES DATA_SET(REC)
任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:我们可以使用对象类型定义创建表:
SQL> create table TBL_02 of OBJ_TYPE
2 /
Table created.
SQL>
这样做的充分理由并不多,但我们可以使用程序中的类型。
这里是一个小例子,从测试数据开始
SQL> select * from tbl_01
2 /
COL_1 COL_2
---------- ----------------------------------------
23 ABC
42 XYZ
SQL> DECLARE
2 DATA_SET TBL_OBJ_TYPE := TBL_OBJ_TYPE();
3 BEGIN
4 FOR REC IN (SELECT * FROM TBL_01)
5 LOOP
6 DATA_SET.EXTEND;
7 DATA_SET(DATA_SET.COUNT) :=
8 OBJ_TYPE( sysdate
9 , REC.COL_1
10 , REC.COL_2);
11 END LOOP;
12
13 FORALL REC IN DATA_SET.FIRST..DATA_SET.LAST
14 INSERT INTO TBL_02
15 VALUES DATA_SET(REC)
16 ;
17 END;
18 /
PL/SQL procedure successfully completed.
SQL> select * from tbl_02;
FLAG NUMB VARC
--------- ---------- ----------------------------------------
20-MAR-16 23 ABC
20-MAR-16 42 XYZ
SQL>
或者,我们可以使用针对目标表定义的 PL/SQL 对象。这对 TBL_02 使用常规堆表:
DECLARE
type tgt_nt is table of TBL_02%rowtype;
data_set tgt_nt;
BEGIN
SELECT sysdate, COL_1, COL_2
bulk collect into data_set
FROM TBL_01;
FORALL REC IN DATA_SET.FIRST..DATA_SET.LAST
INSERT INTO TBL_02
VALUES DATA_SET(REC)
;
END;
/
【讨论】:
【参考方案2】:假设表 TBL_01
中的列与对象声明中的名称相同:
DECLARE
DATA_SET TBL_OBJ_TYPE := TBL_OBJ_TYPE();
BEGIN
SELECT OBJ_TYPE( sysdate, numb, varc ) BULK COLLECT INTO DATA_SET
FROM TBL_01;
INSERT INTO TBL_02( flag, numb, varc )
SELECT * FROM Table( DATA_SET );
END;
/
如果TBL_01
列有不同的名称,例如 X、Y、Z,则分别更改此行:SELECT OBJ_TYPE( X, Y, Z ) BULK COLLECT ...
注意:您不能将1
分配到此处的第一个字段:
OBJ_TYPE( 1
, REC.TBL_01_COL1
, REC.TBL_01_COL2);
因为第一个字段FLAG
在对象声明中被声明为date
类型。
在我的示例中,我已将 1
替换为 sysdate
。
【讨论】:
您好 kordirko,您显然是正确的 sysdate,只是忘记更改。但是无论如何,有什么方法可以遵循我提到的内容吗? FORALL + INSERT INTO table VALUES --> 带有集合而不指定每个列名,而不是使用 SELECT 子句?【参考方案3】:--Rollbaclk--
DROP TYPE TBL_OBJ_TYPE;
DROP TYPE OBJ_TYPE;
DROP TABLE TBL_02;
DROP TABLE TBL_01;
--execute--
CREATE OR REPLACE TYPE OBJ_TYPE AS OBJECT
(
FLAG DATE,
NUMB NUMBER (2, 0),
VARC VARCHAR2 (40 BYTE)
);
/
CREATE OR REPLACE TYPE TBL_OBJ_TYPE AS TABLE OF OBJ_TYPE;
/
CREATE TABLE TBL_02
(
FLAG DATE,
NUMB NUMBER (2, 0),
VARC VARCHAR2 (40 BYTE)
);
CREATE TABLE TBL_01
(
TBL_01_COL0 DATE,
TBL_01_COL1 NUMBER (2, 0),
TBL_01_COL2 VARCHAR2 (40 BYTE)
);
INSERT INTO TBL_01
VALUES (SYSDATE, 1, 'mohit');
INSERT INTO TBL_01
VALUES (SYSDATE, 2, 'vijay');
INSERT INTO TBL_01
VALUES (SYSDATE, 3, 'sohan');
COMMIT;
SELECT * FROM TBL_01;
DECLARE
DATA_SET TBL_OBJ_TYPE := TBL_OBJ_TYPE ();
BEGIN
FOR REC IN (SELECT * FROM TBL_01)
LOOP
DATA_SET.EXTEND;
DATA_SET (DATA_SET.COUNT) :=
OBJ_TYPE (REC.TBL_01_COL0, REC.TBL_01_COL1, REC.TBL_01_COL2);
END LOOP;
FORALL REC IN DATA_SET.FIRST .. DATA_SET.LAST
INSERT INTO TBL_02
VALUES (
DATA_SET (REC).FLAG,
DATA_SET (REC).NUMB,
DATA_SET (REC).VARC);
END;
SELECT * FROM TBL_02;
【讨论】:
以上是关于ORACLE:插入对象类型集合的表值的主要内容,如果未能解决你的问题,请参考以下文章
从集合类型 oracle 12c 插入表 - ORA-00902:无效数据类型