INNER LOOP JOIN失败

时间:2013-11-29 12:37:57

标签: sql sql-server-2008-r2 join-hints

我需要在名为FamName的表中更新一个名为Episode的字段,其中包含来自另一个名为Surnames的表的随机生成的日语名称,该表有一列名为Surname

要做到这一点,我首先在ID表中添加了NONCLUSTERED INDEX字段和Surnames

ALTER TABLE Surnames 
ADD ID INT NOT NULL IDENTITY(1, 1);
GO
CREATE UNIQUE NONCLUSTERED INDEX idx ON Surnames(ID);
GO

然后我尝试通过

更新我的Episode
UPDATE E  
SET E.FamName = S.Surnames 
FROM Episode AS E 
INNER LOOP JOIN Surnames AS S 
    ON S.ID = (1 + ABS(CRYPT_GEN_RANDOM(8) % (SELECT COUNT(*) FROM Surnames)));
GO

我试图使用LOOP联接提示强制查询“循环”。当然,如果我不强制优化器循环(使用LOOP),我将获得所有行的相同德语名称。但是,此查询奇怪地返回受影响的零行。

为什么返回零影响行以及如何修改它?


注意,我可以使用WHILE循环来执行此更新,但我想要一种简洁的方法来执行此操作,并找出在这种特殊情况下我做错了什么。

1 个答案:

答案 0 :(得分:3)

您不能(可靠地)使用联接提示影响查询结果。它们是性能提示,而不是语义提示。你试图依赖未定义的行为。

将连接条件中的随机数计算移动到其中一个连接源中可防止将表达式视为常量:

UPDATE E  
SET E.FamName = S.Surnames 
FROM (
 SELECT *, (1 + ABS(CRYPT_GEN_RANDOM(8) % (SELECT COUNT(*) FROM Surnames))) AS SurnameID
 FROM Episode AS E 
) E
INNER LOOP JOIN Surnames AS S ON S.ID = E.SurnameID

派生表E将计算出的SurnameID添加为新列。

您不再需要加入提示。我刚刚测试过这个在我的特定测试用例中有效,尽管我不确定这是否可以保证工作。