1

@ShannonSeverance 对这个问题给出了很好的回答

在同一个表中复制一行而无需键入 50 多个列名(同时更改 2 列)

这显示了如何将表中的一行动态复制到同一个表(更改 pk)

declare
r table_name%ROWTYPE;
begin
select *
into r
from table_name
where pk_id = "original_primary_key";
-- 
select pk_seq.nextval into r.pk_id from dual;
 -- For 11g can use instead: r.pk_id := pk_seq.nextval;
r.fk_id := "new_foreign_key";
insert into table_name values r;
end;

我想应用这种方法,但在每次从表名数组中调用的函数中

所以基本上我可以使用立即执行进行选择 - 但我如何声明'r'?我可以用传递给函数的变量替换代码中的“table_name”吗?

table(1)="Table1";

table(2)="Table2";

for t 1..table.count loop
 CopyTableContacts(table(i));
end loop;

TIA

麦克风

4

1 回答 1

0

最后,我稍微修改了我的功能

我现在构建 2 个数组

1 - USER_TAB_COLUMNS 表中的表名列表 2 - 对于 array1 中的每个表,我构建了一个逗号分隔的 ALL_TAB_COLUMNS 表中的列名列表

所以我最终得到了 2 个数组(例如......)

tableName(1) = 'MEMBER'
tableName(2) = 'SALARY'

tableColumns(1) = 'ID, SURNAME, SEX, DOB'
tableColumns(2) = 'ID, CURRENTSAL, BONUS, GRADE'

然后我将这两个数组值传递给我的函数,并在 tableName() 数组的循环过程中使用一些动态 SQL ...

PROCEDURE CopyTableRow(inOrigMemNo NUMBER, inNewMemNo NUMBER, inTableName USER_TAB_COLUMNS.TABLE_NAME%TYPE, inTableString LONG) AS
selectString VARCHAR2(32000):=null;
newTableString LONG:=null;
insertTableString LONG:=null;
sqlResultCount NUMBER:=0;
BEGIN
/*CHECK IF THERE IS AT LEAST ONE ROW TO COPY*/
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || inTableName || ' WHERE ID= ' || inOrigMemNo INTO sqlResultCount;
IF sqlResultCount > 0 THEN
  /*BUILD INSERT STATEMENT FOR EACH ROW RETURNED*/
  dbms_output.put_line('At least one row found on ' || inTableName || '(' || sqlResultCount || ')');

  newTableString    := REPLACE(inTableString, 'ID', 'REPLACE(ID, ID,' || inNewMemNo || ')');
  selectString      := 'SELECT ' || newTableString || ' FROM ' || inTableName || ' WHERE ID = ' || inOrigMemNo;
  insertTableString := 'INSERT INTO ' || inTableName || '(' || inTableString || ') (' || selectString || ')';
    END IF;

然后我留下一个基于我可以执行的表定义和值的 INSERT 语句

这似乎工作正常,适合我目前的需求

注意- 它仅在每个表只有一行要复制时才有效。我的下一个挑战是处理一些为需要复制的 ID 返回多行的表(这会很有趣,因为我已经将自己描绘成一个非光标角落!)

麦克风

于 2013-09-25T12:41:36.293 回答