Oracle:将行类型数据插入另一个表

时间:2012-12-13 19:23:41

标签: oracle plsql insert rowtype

我有一个名为 event 的表,并使用与事件相同的列和定义创建了另一个全局临时表 tmp_event 。是否可以使用此命令将事件中的记录插入tmp_event?

DECLARE
   v_record event%rowtype;
BEGIN 
   Insert into tmp_event values v_record;
END;

事件表中有太多列,我想尝试这个,因为我不想列出所有列。

忘了提一下:我会在触发器中使用它,在EVENT表上插入后,这个v_record可以是:new 对象吗?

3 个答案:

答案 0 :(得分:19)

要插入一行 -

DECLARE
   v_record event%rowtype;
BEGIN 
   SELECT * INTO v_record from event where rownum=1; --or whatever where clause
   Insert into tmp_event values v_record;
END;

或更精细的版本,以插入event -

中的所有行
DECLARE
  TYPE t_bulk_collect_test_tab IS TABLE OF event%ROWTYPE;

  l_tab t_bulk_collect_test_tab;

  CURSOR c_data IS
    SELECT *
    FROM event;
BEGIN
  OPEN c_data;
  LOOP
    FETCH c_data
    BULK COLLECT INTO l_tab LIMIT 10000;
    EXIT WHEN l_tab.count = 0;

    -- Process contents of collection here.
    Insert into tmp_event values v_record;
  END LOOP;
  CLOSE c_data;
END;
/

在触发器中,是的,它可能,但它像鸡肉或鸡蛋。您必须使用rowtype列值初始化:new的每个字段,例如 -

v_record.col1 := :new.col1;
v_record.col2 := :new.col2;
v_record.col3 := :new.col3;
....

显然,上面的PLSQL示例不能在触发器中使用,因为它会引发变异触发器错误。如上所述,除了单独访问每个列之外,没有其他方法可以获取触发器中的整行,所以如果你这样做,为什么不直接在:new.col本身使用INSERT into temp_event ,会为你节省很多工作。


此外,既然你说要提及所有列是很多工作,(在 Oracle 11gR2 中)这里有一个快速的方法,通过生成INSERT语句并动态执行它(虽然未经过性能测试)。

CREATE OR REPLACE TRIGGER event_air --air stands for "after insert of row"
AFTER INSERT ON EVENT
FOR EACH ROW
   L_query varchar2(2000);   --size it appropriately
BEGIN

   SELECT 'INSERT INTO tmp_event VALUES ('|| listagg (':new.'||column_name, ',') 
                                           WITHIN GROUP (ORDER BY column_name) ||')' 
     INTO l_query
     FROM all_tab_columns
    WHERE table_name='EVENT';

   EXECUTE IMMEDIATE l_query;

EXCEPTION
    WHEN OTHERS THEN
        --Meaningful exception handling here
END;

答案 1 :(得分:2)

有一种方法可以使用%Rowtyp 将多行插入表中

在下面的示例中结帐。

DECLARE
TYPE v_test IS   TABLE OF TEST_TAB%rowtype;
  v_test_tab v_test ;


 EXECUTE immediate ' SELECT  * FROM TEST_TAB ' bulk collect INTO v_test_tab ;
  dbms_output.put_line('v_test_tab.count -->'||v_test_tab.count);
  FOR i IN 1..v_test_tab.count
  LOOP
    INSERT INTO TEST_TAB_1 VALUES v_test_tab
      (i
      ) ;
  END LOOP;

END;

答案 2 :(得分:0)

总和就是完整的工作示例...

DECLARE
  TYPE t_bulk_collect_test_tab IS TABLE OF event%ROWTYPE;
  l_tab t_bulk_collect_test_tab;
  CURSOR c_data IS SELECT * FROM event;
BEGIN
  OPEN c_data;
  LOOP
    FETCH c_data
    BULK COLLECT INTO l_tab LIMIT 10000;
    EXIT WHEN l_tab.count = 0;
    FORALL i IN 1..l_tab.count
        Insert into tmp_event values l_tab(i);
    commit;
  END LOOP;
  CLOSE c_data;
END;
/