在同一个表中插入select语句

时间:2017-03-06 03:38:44

标签: oracle plsql oracle-sqldeveloper oracle11gr2

我目前正在将数据从旧系统迁移到当前系统。

我在存储过程中有这个INSERT语句。

INSERT INTO TABLE_1
(PRIMARY_ID, SEQUENCE_ID, DESCR)
SELECT LEGACY_ID PRIMARY_ID
 , (SELECT COUNT(*) + 1
    FROM TABLE_1 T1
    WHERE T1.PRIMARY_ID = L1.LEGACY_ID) SEQUENCE_ID
 , L1.DESCR
FROM LEGACY_TABLE L1;

但是,每当我从LEGACY_ID获得LEGACY_TABLE的多个值时,SEQUENCE_ID的查询就不会增加。

为什么会这样?我似乎无法找到有关INSERT INTO SELECT语句如何在幕后工作的任何文档。我猜它会从您选择的表中选择所有值,然后同时插入它们,这就是为什么它不会增加COUNT(*)值?

我可以做哪些其他变通办法?我无法创建SEQUENCE,因为SEQUENCE_ID必须基于所存在的PRIMARY_ID的数量。他们都是主要的ids。

提前致谢。

1 个答案:

答案 0 :(得分:2)

是的,SELECT将被执行FIRST,然后只有INSERT发生。

下面的简单PL / SQL块将是一种更简单的方法,但效率不高。

DECLARE
    V_SEQUENCE_ID NUMBER;
    V_COMMIT_LIMIT:= 20000;
    V_ITEM_COUNT := 0;
BEGIN
    FOR REC IN (SELECT LEGACY_ID,DESCR FROM LEGACY_TABLE)
    LOOP
        V_SEQUENCE_ID:= 0;

        SELECT COUNT(*)+1 INTO V_SEQUENCE_ID FROM TABLE_1 T1
         WHERE T1.PRIMARY_ID = REC.LEGACY_ID


        INSERT INTO TABLE_1
        (PRIMARY_ID, SEQUENCE_ID, DESCR)
        VALUES
        (REC.LEGACY_ID,V_SEQUENCE_ID,REC.DESCR);

        V_ITEM_COUNT := V_ITEM_COUNT + 1;

        IF(V_ITEM_COUNT >= V_COMMIT_LIMIT)
        THEN
             COMMIT;
             V_ITEM_COUNT := 0;
        END IF;

    END LOOP;
    COMMIT;
END;
/
  

编辑:使用CTE:

WITH TABLE_1_PRIM_CT(PRIMARY_ID, SEQUENCE_ID) AS
(
    SELECT L1.LEGACY_ID,COUNT(*) 
    FROM LEGACY_TABLE L1 
      LEFT OUTER JOIN TABLE_1 T1 
        ON(L1.LEGACY_ID = T1.PRIMARY_ID)
    GROUP BY L1.LEGACY_ID
)
INSERT INTO TABLE_1
(SELECT L1.LEGACY_ID,
       CTE.SEQUENCE_ID+ (ROW_NUMBER() OVER (PARTITION BY L1.LEGACY_ID ORDER BY null)), 
       L1.DESCR
FROM TABLE_1_PRIM_CT CTE, LEGACY_TABLE L1
WHERE L1.LEGACY_ID = CTE.PRIMARY_ID);
  

PS:凭借你的百万行,这将创建一个临时表   在执行期间,大小相同。在实际执行之前执行Explain Plan