Sql server 这个表达式如何到达空表达式?

Sql server 这个表达式如何到达空表达式?,sql-server,null,Sql Server,Null,我尝试使用以下语句使用另一个表中的值随机填充列: UPDATE dbo.SERVICE_TICKET SET Vehicle_Type = (SELECT TOP 1 [text] FROM dbo.vehicle_typ WHERE id = abs(checksum(NewID()))%21) 它似乎工作正常,但是值NULL被插入到列中。如何去除NULL并仅插入表中的值?如果您的车辆类型表的ID列上没

我尝试使用以下语句使用另一个表中的值随机填充列:

UPDATE dbo.SERVICE_TICKET    
SET Vehicle_Type = (SELECT TOP 1 [text]
                    FROM dbo.vehicle_typ 
                    WHERE id = abs(checksum(NewID()))%21)

它似乎工作正常,但是值
NULL
被插入到列中。如何去除
NULL
并仅插入表中的值?

如果您的
车辆类型表的
ID
列上没有适当的索引,则可能发生这种情况。下面是一个显示相同问题的较小查询:

create table T (ID int null)
insert into T(ID) values (0),(1),(2),(3)
select top 1 * from T where ID = abs(checksum(NewID()))%3
因为
T
上没有索引,所以SQL Server会执行表扫描,然后对每一行尝试满足where子句。这意味着,对于每一行,它将重新计算
abs(校验和(NewID()))%3
。只有当该表达式对ID为
1的行求值时,碰巧生成了
1
时,才会得到结果


如果可能的话(我不知道您的表结构),我会首先在
SERVICE\u TICKET
中用一个介于0和20之间的随机数填充一列,然后使用已经生成的数字执行此更新。否则,在当前的查询结构中,您总是依赖SQL Server足够聪明,只对每个外部行计算一次
abs(checksum(NewID())%21
,这可能并不总是如此(正如您已经发现的那样)。

@Damien\u不信者解释了查询失败的原因

我的第一个变体不正确,因为我没有完全理解这个问题

您希望将
服务\u TICKET
中的每一行设置为与
车辆类型
不同的随机值

要修复它,只需按随机数排序,而不是将随机数与
ID
进行比较。这样(只要至少有一行,你就不在乎车辆类型中有多少行)


首先,我们创建一个公共表表达式,您可以将其视为一个临时表。对于
SERVICE\u TICKET
中的每一行,我们使用
交叉应用
车辆类型
中随机选取一行。然后我们用所选行更新原始表。

这不是
mysql
语法,更新问题并更改标记。这不是
mysql
语法。请使用
sql server
标记。在
vehicle\u typ
中是否有包含从
0
20
的所有可能ID的行?如果不是,这就是产生
NULL
s的原因。是的,车辆类型包括从0到20的所有可能行-因此这不是NULL的原因。好的,我看到了问题。。。那么,我怎样才能从上面改变我的表达来摆脱这个问题呢?@LKH-我不知道你读到了我的答案的哪个版本-我在底部添加了一个新段落,其中一个建议是我如何尝试解决这个问题。感谢你的回答-我创建了一个聚集索引,空值消失了。然而,现在每个值都是相同的。。。你知道如何让随机不同的值不为NULL吗?我完全按照你描述的复制了表达式。但是,我无法执行它,因为找不到多部分标识符dbo.SERVICE\u TICKET.Vehicle\u Type。此外,“交叉应用”显示为灰色。@LKH,我不明白您为什么会出现错误。如果您尝试简单的
从dbo.SERVICE\u TICKET中选择dbo.SERVICE\u TICKET.Vehicle\u Type
是否有效?
WITH
CTE
AS
(
    SELECT
        dbo.SERVICE_TICKET.Vehicle_Type
        CA.[text]
    FROM
        dbo.SERVICE_TICKET
        CROSS APPLY
        (
            SELECT TOP 1 [text]
            FROM dbo.vehicle_typ
            ORDER BY NewID()
        ) AS CA
)
UPDATE CTE
SET Vehicle_Type = [text];