按顺序更新cte不工作,为什么?

时间:2017-09-18 08:58:09

标签: sql-server tsql common-table-expression

我想通过批量更新来更改表的序列。 由于更新不包含order by,我使用了CTE,with子句,制作了数据集并对结果发布了更新,期望它会按照我的意愿执行。
但它不是由我订购的套装更新 这次更新出了什么问题?

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

以下是插入后的内容:

+--+----+
|1 |1001|
|2 |1002|
|3 |1003|
|4 |1004|
|5 |1005|
|6 |1006|
|7 |1003|

以下是我们的需求:

+--+----+
|1 |1001|
|2 |1002|
|3 |1003|
|4 |1005|
|5 |1006|
|6 |1007|
|7 |1004|

3 个答案:

答案 0 :(得分:1)

您的更新声明有误。您正在更新cte,然后将值设置为局部变量。我猜你期望更新将逐行执行,从而将每行Serial的值设置为前一个值+ 1.但是,这不是sql的工作方式。

要从您提供的输入中获得所需的输出,您不需要cte,也不需要使用row_number。你可以这样做:

DECLARE @Id int = 3
UPDATE Test 
SET [Serial] = cast(Serial as int) + 1 
WHERE Id > @Id

检查:

SELECT Id, Serial
FROM Test

结果:

Id  Serial
1   1001
2   1002
3   1003
4   1005
5   1006
6   1007
7   1004

See a live demo on rextster.

答案 1 :(得分:1)

您可以先计算表格中的行数,然后使用变量或为TOP选择一个大数字来选择整个表格,然后按顺序排序:

;with Records as 
( 
    Select TOP 100000 
        Id
        , Serial 
    FROM [Test]
    where Id>@Id
    ORDER BY Serial
)

答案 2 :(得分:0)

  

但它不是由我的有序集更新。这有什么问题   更新

您的代码中没有有序集。 CTE不是也不能“订购”。

您应该在更新中使用计算出的RN,否则,您的代码根本不依赖于row_number():

public sealed partial class MainPage : Page
{

    ObservableCollection<Data> Products;

    public MainPage()
    {
        this.InitializeComponent();
        Products = new ObservableCollection<Data>()
        {
         new Data { Product = "Milk", Stock = true },
         new Data { Product = "Cheese", Stock = false },
         new Data { Product = "Bread", Stock = false },
         new Data { Product = "Chocolate", Stock = true }
        };
        this.DataContext = Products;
    }
}
public class Data
{
    public string Product { get; set; }
    public bool Stock { get; set; }
}