为什么我的非空列在我的 CTE 递归查询中变得可以为空?

web*_*ner 2 null sql-server cte recursive

我有一个简单的分层表。假设它有这些列:

Id, [Guid], ParentId, Title
Run Code Online (Sandbox Code Playgroud)

只有可以ParentId为空。其他列不可为空。

我创建了一个递归查询来显示从节点到根的路径。为此,我使用了 CTE。这是我的查询:

with Anchor (Id, [Guid], ParentId, Title, [Path])
as
(
    select Id, [Guid], ParentId, Title, cast('' as nvarchar(100)) as [Path]
    from Hierarchies
    where ParentId is null
    union all
    select Hierarchies.Id, Hierarchies.[Guid], Hierarchies.ParentId, Hierarchies.Title, cast(Anchor.[Path] + '/' + Hierarchies.Title as nvarchar(100)) as [Path]
    from Hierarchies
    inner join Anchor
    on Hierarchies.ParentId = Anchor.Id
)
select 
    isnull(Anchor.Id, 0) as Id,
    isnull(Anchor.[Guid], newid()) as [Guid],
    Anchor.ParentId,
    Anchor.Title,
    Anchor.[Path]
from Anchor
Run Code Online (Sandbox Code Playgroud)

问题是,当我将此查询转换为视图时,该Guid列变为可以为空。我什至使用isnull()函数来强制它不为空。令我惊讶的是,这isnull实际上对Id专栏有用。但它不适用于Guid.

我该怎么办?为什么 SQL Server 有这种行为?

Cha*_*ace 5

NEWID()编译器不确定该函数总是返回一个值(即使你和我都知道),所以解决这个问题的唯一方法是ISNULL再次使用

ISNULL(ISNULL(Anchor.[Guid], NEWID()), CAST(0x0 AS uniqueidentifier))
Run Code Online (Sandbox Code Playgroud)

最后一个参数实际上从未被执行。

显然,如果您实际上不需要,NEWID()那么您可以使用CAST

ISNULL(Anchor.[Guid], CAST(0x0 AS uniqueidentifier))
Run Code Online (Sandbox Code Playgroud)