2012-10-25 89 views
1

我正在尝试更新表格中的所有记录。在阅读记录时,我需要用当前记录中的NEXT记录的值更新当前记录中的一列。问题在于更新需要按照指定的顺序完成。以特定顺序更新记录

我在想这样的事情...

Update t1 
Set col1 = (select LEAD(col2,1) OVER (ORDER BY col3, col4, col5) 
      from t1); 

这并不编译,但你明白我开车...任何想法?

...更新

这peice的不顺利运行,但只能写入空值

Update t1 A 
Set t1.col1 = (select LEAD(col2,1) OVER (ORDER BY col3, col4, col5) 
      from t1 B 
      where A.col3 = B.col3 AND 
       A.col4 = B.col4 AND 
       A.col5 = B.col5); 
+2

你是什么意思“更新需要按照指定的顺序完成”?你是否试图控制SQL语句实际改变各个块的顺序?或者你是否只是说'LEAD'函数需要一个指定的'ORDER BY'子句才能找到正确的“下一个记录”? –

+0

@danihp:不需要临时表。 –

+0

@JustinCave - 我需要LEAD函数从逻辑上正确的NEXT记录中返回一个值。这些是来自同一个表的记录,所以用于返回NEXT记录的键需要与用于执行Update语句的键相同。 – jojoberry

回答

1

这应做到:

merge into t1 
using 
(
    select rowid as rid, 
      LEAD(col2,1) OVER (ORDER BY col3, col4, col5) as ld 
    from t1 
) lv on (lv.rid = t1.rowid) 
when matched then 
    update set col1 = lv.ld; 

不是100%肯定,如果我得到的语法完全正确,但你没有提供任何TESTDATA,我会留下潜在的语法错误,为您解决。

您还可以将rowid的用法替换为表格的真正主键列。

+0

+1,但ORA-00969:缺少括号的ON关键字。 http://sqlfiddle.com/#!4/31821/9/1 – danihp

+0

@danihp:谢谢。我*总是*忘记了;) –

+0

真棒,谢谢!我不知道为什么我的思维过程没有朝着合并的方向前进。它后面的视觉非常有意义。 – jojoberry

0

你为什么不使用游标?您可以按指定顺序在游标内使用更新。

+0

我能够用游标和一大堆for循环完成它,但我试图尽可能有效地编写它。 – jojoberry

0

您可以使用with语句做到这一点:

with toupdate as (
    select t1.*, 
      lead(col2, 1) over (order by col3, col4, col5) as nextval 
    from t1 
) 
Update toupdate 
    Set col1 = nextval 

顺便说一句,这并不能保证更新的订购。但是,分区条款中没有提到col2,因此它应该做正确的事情。

上述语法适用于SQL Server,但不适用于Oracle。原来的问题没有指定数据库(并且lead是SQL Server 2012中的有效函数)。看来merge语句是获取子查询中值的方式。

+0

@a_horse_with_no_name。 。 。不,这将更新col1与“下一个”记录中col2的值,其中“下一个”由col3,col4和col5的顺序定义。如果col2总是包含相同的值,它只会给它们所有相同的值。 –