从SQL表中的数字开始连续更新值
我有一个关于从SQL表中的数字开始连续更新值,sql,oracle,sql-update,Sql,Oracle,Sql Update,我有一个关于UPDATE语句用法的问题。有没有一种方法可以让我只用SQL编写以下场景,而不是编写存储过程 我试图简化这个案子 myTable有4列,其值如下: COMP1 COMP2 NO ACTIVE 0 0 4 N 4 1 Y 2 2 21 Y 3 1 1 Y 1 3 43 Y 2 1 Y 3 1
UPDATE
语句用法的问题。有没有一种方法可以让我只用SQL编写以下场景,而不是编写存储过程
我试图简化这个案子
myTable
有4列,其值如下:
COMP1 COMP2 NO ACTIVE
0 0 4 N
4 1 Y
2 2 21 Y
3 1 1 Y
1 3 43 Y
2 1 Y
3 1 12 Y
2 2 0 Y
3 2 Y
1 1 5 N
- 我想选择值
并开始更新 通过按WHERE ACTIVE='Y'
对其进行排序,它们的值不在任何列中COMP1、COMP2 ASC
- 编号必须从表
中的
值开始,其中ACTIVE='N'MAX(NO)
- 具有相同COMP1和COMP2的行将具有相同的NO值
- (注释后更新)无列不总是空的。此列中存在错误值,需要通过更新查询进行更正
UPDATE
语句之后,myTable
将如下所示(如果我们订购的话)
我想知道我是否能够做到这一点,而不需要选择整个列表并在存储过程中循环游标
(更新:我已经编写了SP。一个简化版本如下。它可能有问题,因为我更改了所有名称并删除了许多条件。)
我正在使用Oracle 11g 我假设
NO
字段在ACTIVE='Y'
时始终为空。如果是这种情况,则无论是否指定了WHERE ACTIVE='N'
条件,MAX(NO)都将返回相同的值。有了这个假设,这个UPDATE
语句应该可以实现这个目的
UPDATE myTable
SET NO = (SELECT MAX(NO) FROM myTable) + 1
WHERE ROWID IN
(SELECT ROWID FROM myTable
WHERE ACTIVE = 'Y'
ORDER BY COMP1, COMP2);
可以使用窗口函数检索新号码: 下面将检索活动行并计算
no
select comp1,
comp2,
row_number() over (order by comp1, comp2) + (select max(no) from mytable where active = 'N') as rn
from mytable
where active = 'Y'
现在可以在MERGE
语句中使用它来对表运行更新。由于该表显然没有主键,我将使用ROWID
匹配行:
merge into mytable tg
using (
select rowid as rid,
comp1,
comp2,
row_number() over (order by comp1, comp2) + (select max(no) from mytable where active = 'N') as rn
from mytable
where active = 'Y'
) t on (t.rid = tg.rowid)
when matched then update
set no = t.rn;
这肯定比使用单行更新的循环要快,尤其是对于较大的表 谢谢你的回答。但活动列为“Y”的字段中没有错误的值,即它们并不总是空的。Update语句必须更正这些值,并将正确的数字设置为NO列(我在问题中添加了这个)。我也试过你的例子,但它给出了ORA-00934错误,不允许我使用组函数。我编辑以消除错误。仍然不适合你,但我不想把坏代码留在这里。谢谢你。除了COMP1=COMP2的情况外,它几乎解决了这个问题。我也在尝试,但是您知道如何为具有与我的示例中相同的COMP1和COMP2的行设置相同的NO吗。我想,我们需要在行号()行写一个案例或类似的东西。@YigitalpErtem:
comp1=comp2
的问题可以通过使用densite\u rank()
而不是row\u number()
来解决。非常感谢。我需要学习分析函数,它们看起来很强大。
select comp1,
comp2,
row_number() over (order by comp1, comp2) + (select max(no) from mytable where active = 'N') as rn
from mytable
where active = 'Y'
merge into mytable tg
using (
select rowid as rid,
comp1,
comp2,
row_number() over (order by comp1, comp2) + (select max(no) from mytable where active = 'N') as rn
from mytable
where active = 'Y'
) t on (t.rid = tg.rowid)
when matched then update
set no = t.rn;