CTE算术移位操作导致算术溢出错误

问题描述 投票:2回答:1

当执行CTE表达通过换挡来查询有序的孩子父母的关系,它失败

算术溢出错误将表达式转换为数据类型BIGINT

问题是,移位值变大很容易。我知道我可以增加数据类型支持38个数值,但具有深厚的父子关系时,我还是会打这个号码。我想知道是否有任何其他方法来排序的结果,所以我不会打这个限制。

下面是一个示例脚本,显示的移位参数的增大。

CREATE TABLE [dbo].[ParentChild] (
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ParentId] [int] NULL,
    [Name] [nvarchar](150) NOT NULL
 CONSTRAINT [PK_Dialog] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
))
GO

ALTER TABLE [dbo].[ParentChild]  WITH CHECK ADD  CONSTRAINT [FK_ParentChild_ParentId] FOREIGN KEY([ParentId])
REFERENCES [dbo].[ParentChild] ([Id])
GO

ALTER TABLE [dbo].[ParentChild] CHECK CONSTRAINT [FK_ParentChild_ParentId]
GO

set identity_insert [dbo].[ParentChild] on
insert into [dbo].[ParentChild] ([Id], [ParentId],[Name])
values 
(1, NULL, '1'),
(2, NULL, '2'),
(3, 1, '1.1'),
(4, 1, '1.2'),
(5, 2, '2.1'),
(6, 5, '2.1.1')
set identity_insert [dbo].[ParentChild] off

-- without shift
with Parent as (
        select d1.[Id], d1.[ParentId], d1.[Name], 0 AS [Level]
        FROM [dbo].[ParentChild] as d1
        WHERE d1.[ParentId] IS NULL
    UNION ALL
        SELECT d2.Id, d2.ParentId, d2.[Name], [Level] + 1
        FROM [dbo].[ParentChild] as d2
        INNER JOIN Parent d1 ON d1.[Id] = d2.ParentId
    )

    select p.Id, p.ParentId, p.[Name], [Level]
    from Parent p
    group by p.Id, p.ParentId, p.[Name], [Level];

-- desired  
with Parent as (
    select d1.[Id], d1.[ParentId], d1.[Name], 0 AS [Level],
    CAST(row_number() over(order by id) as DECIMAL(38,0)) as [shift]
    FROM [dbo].[ParentChild] as d1
    WHERE d1.[ParentId] IS NULL
UNION ALL
    SELECT d2.Id, d2.ParentId, d2.[Name], [Level] + 1, 
    CAST([shift] * 100 + row_number() over(order by d2.id) as DECIMAL(38,0))
    FROM [dbo].[ParentChild] as d2
    INNER JOIN Parent d1 ON d1.[Id] = d2.ParentId
)

select p.Id, p.ParentId, p.[Name], [Level], [shift]
from Parent p
group by p.Id, p.ParentId, p.[Name], [Level], [shift]
order by cast([shift] as varchar(50))

输出,而不移位参数

Id  ParentId    Name    Level
1   NULL        1       0
2   NULL        2       0
3   1           1.1     1
4   1           1.2     1
5   2           2.1     1
6   5           2.1.1   2

与移位参数输出(期望的)

Id  ParentId    Name    Level   shift
1   NULL        1       0       1
3   1           1.1     1       101
4   1           1.2     1       102
2   NULL        2       0       2
5   2           2.1     1       201
6   5           2.1.1   2       20101
sql sql-server
1个回答
1
投票

假设我们可以shift一个字符串,而不是一个数学-支持的数据类型,我们可以只是这样做:

with Parent as (
    select d1.[Id], d1.[ParentId], d1.[Name], 0 AS [Level],
    CONVERT(varchar(max),row_number() over(order by id)) as [shift]
    FROM [dbo].[ParentChild] as d1
    WHERE d1.[ParentId] IS NULL
UNION ALL
    SELECT d2.Id, d2.ParentId, d2.[Name], [Level] + 1,
    shift + RIGHT('0' + CONVERT(varchar(2),row_number() over(order by d2.id)),2)
    FROM [dbo].[ParentChild] as d2
    INNER JOIN Parent d1 ON d1.[Id] = d2.ParentId
)
select p.Id, p.ParentId, p.[Name], [Level], [shift]
from Parent p
group by p.Id, p.ParentId, p.[Name], [Level], [shift]
order by shift

它产生不同的结果,如果行号都不能超过100,但似乎导致这一问题表示反正(暧昧编码)。

© www.soinside.com 2019 - 2024. All rights reserved.