Reputation: 235
I want to change serial of table by batch update.
Since update do not contain order by, I used CTE, with clause, made a data set and issued update on the result, expected that it will do as I will.
But it update by Id not by my ordered set.
what is wrong with this update?
CREATE TABLE [dbo].[Test](
[Id] [int] NOT NULL,
[Serial] [nvarchar](10) NOT NULL
)
insert into Test values
(1, 1001),
(2, 1002),
(3, 1003),
(4, 1004),
(5, 1005),
(6, 1006),
(7, 1003)
declare @serial int, @Id int
set @Id =3
select @serial = Serial from Test WHERE Id=@Id
declare @new_serial nvarchar(10);
select @new_serial = cast(@serial as nvarchar(10));
;with Records as
(
Select Id, Serial
, ROW_NUMBER() over
(
order by serial
) as RN
FROM [Test]
where Id>@Id
)
UPDATE Records set
[Serial] = cast(@new_serial as int),
@new_serial = cast(@new_serial as int)+1
Here is what after insert exists:
+--+----+
|1 |1001|
|2 |1002|
|3 |1003|
|4 |1004|
|5 |1005|
|6 |1006|
|7 |1003|
Here is what we need:
+--+----+
|1 |1001|
|2 |1002|
|3 |1003|
|4 |1005|
|5 |1006|
|6 |1007|
|7 |1004|
Upvotes: 3
Views: 1005
Reputation: 358
You can either count how many rows in your table first and use a variable or pick a large number for your TOP to select the entire table and then order that by your serial:
;with Records as
(
Select TOP 100000
Id
, Serial
FROM [Test]
where Id>@Id
ORDER BY Serial
)
Upvotes: 0
Reputation: 8687
But it update by Id not by my ordered set. what is wrong with this update?
You have no ordered set in your code. CTE is not and cannot be "ordered".
You should use your calculated RN in your update, if you don't, your code does not depend on row_number() at all:
declare @Test table(
[Id] [int] NOT NULL,
[Serial] [nvarchar](10) NOT NULL
)
insert into @Test values
(1, 1001),
(2, 1002),
(3, 1003),
(4, 1004),
(5, 1005),
(6, 1006),
(7, 1003)
declare @serial int, @Id int
set @Id =3
select @serial = Serial from @Test WHERE Id=@Id
--declare @new_serial nvarchar(10);
--select @new_serial = cast(@serial as nvarchar(10));
;with Records as
(
Select Id, Serial
, ROW_NUMBER() over
(
order by serial
) as RN
FROM @Test
where Id>@Id
)
UPDATE Records set
[Serial] = cast(cast(@serial as int) + RN as nvarchar(10))
select *
from @test
Upvotes: 0
Reputation: 82474
Your update statement is wrong. You are updating the cte and then setting a value to a local variable. I'm guessing you expect that the update will be executed row by row, thus setting the value of Serial
in each row to the previous value + 1. However, that's not how sql works.
To get your desired output from the input you provided you do not need a cte nor do you need to use row_number
. You can simply do this:
DECLARE @Id int = 3
UPDATE Test
SET [Serial] = cast(Serial as int) + 1
WHERE Id > @Id
Check:
SELECT Id, Serial
FROM Test
Results:
Id Serial
1 1001
2 1002
3 1003
4 1005
5 1006
6 1007
7 1004
Upvotes: 1