插入select *-覆盖某些列

时间:2018-07-18 19:30:40

标签: sql oracle plsql

假设我有一张桌子T。

T定义为

create table t(
  pk     number,       -- set with sequence by trigger
  col01  varchar2(10),
  col02  varchar2(10),
  .
  .
  .
  col20  varchar2(10)
);

(在您说类似“您应该考虑规范化数据之前-这只是一个例子。实际表已规范化,但问题仍然存在)。

现在让我们说我想“复制”一些行,但是一两个列应该获得新值。 我显然可以写一些乏味的插入内容,例如:

insert into t
(pk, col01, col02, ... col20)
select  null pk,
        col01, 
        'NEW_C02' as col02,
        'NEW_C03' as col03,
        .
        .
        .
        col20
 from t
where t.col01 = 'qqq'
  and t.col02 = 'OLD_C02';

但是没有任何语法可以减少重写列名的开销吗?

我可以想到几种解决方案,但是它们都有主要缺点,例如:

1)我已经在stackoverflow上看到过的方法-使用数据透视表对“大多数”列进行分组-这不仅是性能问题本身,而且也不是我想要做的(即-我的行)如果不包含pk,则不能保证是唯一的)

2)Pl / sql方法:使用行类型并循环记录,更改它们并插入新的列值,或者在批量收集后使用forall。 批量收集将需要大量内存,因此是“不”。从理论上讲,可以管理的限制是有限的,但这仅意味着我已经将开销代码从sql移到了plsql。 循环插入会导致很多上下文切换-因此它也是“否”。

3)Pl / sql方法:使用数据字典构建动态sql为我完成此任务。 显然,此后我再也不会睡着了,甚至都不会通过代码审查来谈论它。

1 个答案:

答案 0 :(得分:0)

在性能方面,这可能很差,因为它是逐行方法,而不是纯SQL。

DECLARE
    l_row t%ROWTYPE;
BEGIN
    SELECT * INTO l_row FROM t WHERE ...

    l_row.pk := NULL;
    l_row.col01 := 'New col01 value';

    INSERT INTO t VALUES l_row;
END;