简体   繁体   English

如何动态声明%rowtype?

[英]How to declare %rowtype dynamically?

Below is the sample code in which I have stored all the table names in one table (table_config) and trying to insert one record of every table into its temporary table and trying to get the particular rowid for further need. 下面是示例代码,其中我将所有表名存储在一个表(table_config)中,并尝试将每个表的一条记录插入其临时表中,并尝试获取特定的rowid以供进一步使用。

So I need every table rowtype to make this work, something dynamic. 因此,我需要每个表的行类型都可以使这项工作变得动态。 Could you please help me with this? 你能帮我这个忙吗?

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; 

Thank you, Pradeep 谢谢Pradeep

Without coding the complete answer for you. 无需为您编码完整答案。 Why don't you do something like this? 你为什么不做这样的事?

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;
  • it assumes target table is empty to begin with with only one record inserted during the process. 它假定目标表在开始时为空,并且在此过程中仅插入了一条记录。

You can't do that as already mentioned in the comment by OldProgrammer above. 正如上面的OldProgrammer的注释中已经提到的那样,您不能这样做。

You'll have to use Dynamic SQL to achieve what you're trying to achieve. 您必须使用Dynamic 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;
/

Below is solution. 下面是解决方案。 What do you need this rowids for? 您需要这些rowid做什么? I would be much simpler without it, as you cannot use returning with insert as select 如果没有它,我会简单得多,因为您不能使用带有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; 
    /

You should investigate EXECUTE IMMEDIATE INTO . 您应该调查EXECUTE IMMEDIATE INTO I think this would be an excellent way to get the ROWID when combined with some dynamic SQL examples from above. 我认为当与上面的一些动态SQL示例结合使用时,这将是获取ROWID的绝佳方法。 Here's an example: 这是一个例子:

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;

Thank you guys for your response. 谢谢你们的回应。 Actually I was trying to implement partition exchange on interval partitioned tables. 实际上,我试图在间隔分区表上实现分区交换。 I achieved it by using Dynamic Sql now. 我现在通过使用Dynamic Sql实现了它。 Initially I was trying to implement it by using rowid which is ok when I hard coded for one table, but when I thought of configuring it and using it for multiple tables I got stuck at that %ROWTYPE. 最初,我试图通过使用rowid来实现它,当我为一个表进行硬编码时,可以这样做,但是当我考虑配置它并将其用于多个表时,我陷入了那个%ROWTYPE的困境。

In the below code I have hard coded table name in few places which can be modified as dynamic but the problem is how to get the %ROWTYPE for the every table we pass. 在下面的代码中,我在几个地方都对表名进行了硬编码,可以将其修改为动态表,但问题是如何为我们传递的每个表获取%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;
/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM