2016-01-26 81 views
1

下面是示例代碼,我已將所有表名存儲在一個表(table_config)中,並嘗試將每個表的一個記錄插入其臨時表並嘗試獲取特定的rowid以滿足進一步需要。如何動態聲明%rowtype?

所以我需要每個表rowtype使這個工作,動態的東西。你能幫我解決這個問題嗎?

DECLARE 
l_row table_name%ROWTYPE; 
l_rowid ROWID; 
l_table_name all_tab_partitions.table_name%TYPE; 
l_temp_table_name all_tab_partitions.table_name%TYPE; 
BEGIN 
FOR tab IN 
(select table_name from 
Table_config) 
    LOOP 
    l_table_name:= tab.table_name; 
    l_temp_table_name:= 'TEMP_'||l_table_name; 
    SELECT * INTO l_row 
    FROM l_table_name 
    WHERE ROWNUM=1; 
    INSERT INTO l_temp_table_name VALUES l_row 
    RETURNING ROWID INTO l_rowid; 
    COMMIT; 
    END LOOP; 
END; 

謝謝 普拉迪普

+4

你不能那樣做。 %ROWTYPE是一個編譯時指令,需要一個表名。您可以使用引用遊標和動態sql。 – OldProgrammer

回答

0

你不能這樣做,因爲已經在評論由OldProgrammer如上所述。

您將不得不使用動態SQL來實現您要實現的目標。

DECLARE 
temp_table VARCHAR2(255); 
source_table VARCHAR2(255); 
sql_stmt VARCHAR2(255); 
CURSOR c1 IS 
SELECT table_name FROM user_Tables; 
BEGIN 
    FOR c1_Rec IN c1 LOOP 
     temp_table := 'TEMP_'||c1_rec.table_name; 
     source_table := c1_rec.table_name; 
     sql_stmt := 'INSERT INTO '||temp_table||' SELECT * FROM '||source_table||' WHERE rownum = 1'; 
     EXECUTE IMMEDIATE sql_stmt; 
    END LOOP; 
END; 
/
0

沒有爲您編碼完整答案。 爲什麼你不這樣做?

FOR tab IN 
(select table_name from 
Table_config) 

EXECUTE_IMMEDIATE(
'declare 
l_row '||table_name||'%ROWTYPE; 
begin 
INSERT INTO '||l_temp_table_name 
SELECT * FROM '||l_table_name||' WHERE ROWNUM=1; 
end;'); 

EXECUTE_IMMEDIATE ('SELECT ROWID FROM '||l_table_name) 
INTO l_rowid; 

END LOOP; 
  • 它假定目標表是空的,開始與該過程中只插入一個記錄。
0

下面是解決方案。你需要什麼rowids?我會沒有它要簡單得多,因爲你不能使用插入返回的選擇

DECLARE 
    l_rowid ROWID; 
    l_table_name all_tab_partitions.table_name%TYPE; 
    l_temp_table_name all_tab_partitions.table_name%TYPE; 
    v_sql1 varchar2(4000); 
    v_sql2 varchar2(4000); 
    BEGIN 
    FOR tab IN (select table_name from Table_config) LOOP 
     l_table_name:= tab.table_name; 
     l_temp_table_name:= 'TEMP_'||l_table_name; 
     v_sql1 := 'select rowid from ' || l_table_name || ' where rownum =1 for update'; 
     v_sql2 := 'insert into ' || l_temp_table_name || ' select * from ' || l_table_name || ' where rownum = 1'; 
     execute immediate v_sql1 into l_rowid; 
     execute immediate v_sql2; 
     commit; 
     END LOOP; 
    END; 
    /
+0

謝謝Piotr Siekierski你的方法幫助我在一種情況下進一步移動。 –

0

您應該調查EXECUTE IMMEDIATE INTO。我認爲這將是一個很好的方式來獲得ROWID結合上面的一些動態SQL示例。這裏有一個例子:

DECLARE 
    DYN_SQL VARCHAR(4000) := 'SELECT 1 FROM DUAL'; 
    INTO_VAR NUMBER(1); 
BEGIN 
    EXECUTE IMMEDIATE DYN_SQL INTO INTO_VAR; 

    DBMS_OUTPUT.PUT_LINE(INTO_VAR); 
END; 
0

謝謝你們的回覆。其實我試圖在間隔分區表上實現分區交換。我現在通過使用Dynamic Sql來實現它。最初我試圖通過使用rowid來實現它,當我爲一個表進行硬編碼時沒問題,但是當我想到配置它並將它用於多個表時,我被卡在了%ROWTYPE中。

在下面的代碼中,我在幾處可以修改爲動態的硬編碼表名,但問題是如何獲得我們傳遞的每個表的%ROWTYPE。

DECLARE 
l_table_name  table_config.table_name%TYPE; 
l_query_temp  VARCHAR2(1000); 
l_part_table_name all_tab_partitions.table_name%TYPE; 
l_part_name   all_tab_partitions.partition_name%TYPE; 
l_temp_table_name all_tab_partitions.table_name%TYPE; 
l_row    test_archival%ROWTYPE; 
l_rowid    ROWID; 
l_arch_table_name all_tab_partitions.table_name%TYPE; 
l_arch_part_name VARCHAR2(30); 
l_query_arch  VARCHAR2(1000); 
l_query_source  VARCHAR2(1000); 
BEGIN 
<<outer_loop>> 
FOR tab IN 
(SELECT table_name FROM 
table_config) 
LOOP 
    l_table_name:= tab.table_name;   
    <<inner_loop>> 
    FOR part IN      
      (SELECT table_name, partition_position, partition_name FROM 
       (SELECT table_name, partition_position, partition_name, 
       DENSE_RANK() OVER (PARTITION BY table_name ORDER BY  partition_position DESC) AS RANK 
       FROM all_tab_partitions 
       WHERE table_name=l_table_name 
       ) WHERE RANK NOT IN(1, 2) ORDER BY partition_position) 
       LOOP       
        l_part_table_name:= part.table_name; 
        l_part_name:= part.partition_name; 
        l_temp_table_name := 'TEMP_'||l_part_table_name; 
        l_arch_table_name := 'ARCH_'||l_part_table_name; 

        l_query_temp := 'ALTER TABLE ' 
            || l_part_table_name                
            || ' EXCHANGE PARTITION ' 
            || l_part_name 
            || ' WITH TABLE ' 
            || l_temp_table_name 
            ||' INCLUDING INDEXES WITHOUT VALIDATION'; 
        EXECUTE IMMEDIATE l_query_temp; 
        COMMIT;   

        SELECT * INTO l_row FROM temp_test_archival WHERE ROWNUM = 1; 

        INSERT INTO arch_test_archival VALUES l_row RETURNING ROWID INTO l_rowid;  
        COMMIT; 

        SELECT subobject_name 
        INTO l_arch_part_name FROM user_objects  
        WHERE data_object_id = dbms_rowid.rowid_object(l_rowid); 

        DELETE from arch_test_archival where rowid=l_rowid; 
        COMMIT; 

        l_query_arch := 'ALTER TABLE ' 
        ||'ARCH_TEST_ARCHIVAL' 
        ||' EXCHANGE PARTITION ' 
        ||l_arch_part_name   
        ||' WITH TABLE ' 
        ||'TEMP_TEST_ARCHIVAL' 
        ||' INCLUDING INDEXES WITHOUT VALIDATION'; 
        EXECUTE IMMEDIATE l_query_arch; 
       END LOOP; 
END LOOP; 
END; 
/