如何动态声明%rowtype?

时间:2016-01-26 12:55:49

标签: sql oracle plsql plsqldeveloper

下面是示例代码,其中我将所有表名存储在一个表(table_config)中,并尝试将每个表的一条记录插入其临时表中,并尝试获取特定的rowid以进一步需要。

所以我需要每个表格行类型来完成这项工作,这是动态的。你能帮帮我吗?

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; 

谢谢你, 普拉迪普

5 个答案:

答案 0 :(得分: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;
/

答案 1 :(得分:0)

没有为您编写完整的答案。 你为什么不做这样的事?

DrawerLayout
  • 它假定目标表为空,开始时只在过程中插入一条记录。

答案 2 :(得分:0)

以下是解决方案。你需要这个rowid?没有它我会更简单,因为你不能使用insert作为select

返回
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; 
    /

答案 3 :(得分:0)

您应该调查EXECUTE IMMEDIATE INTO。我认为,当与上面的一些动态SQL示例结合使用时,这将是获得ROWID的绝佳方法。这是一个例子:

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;

答案 4 :(得分: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;
/