2017-06-12 113 views
1

我想了解我正在执行的UPDATE/REPLACE的行为,即删除一些无效数据并用首选数据替换。TSQL - SELECT TOP和UPDATE影响比预期更多的行

UPDATE执行正常,并做它需要做的事情,但受影响的行不是我所期望的在某些情况下(我在多个数据库中执行此操作)。

我已经把下面(其余基本上是复制跨多个表的相同功能)

UPDATE TBL_HISTORY 
SET DETAILS = REPLACE(DETAILS,'&QUOT','Times New Roman') 
WHERE HISTORYID IN 
(SELECT TOP 1000 (HISTORYID) FROM TBL_HISTORY 
WHERE DETAILS LIKE '%&QUOT%') 

GO 

什么我想像上面的脚本发生是选择TOP 1000记录的脚本的一部分在TBL_HISTORY中包含不需要的数据字符串并执行REPLACE

结果发生在有超过1000个受影响的行的情况下,它将更新所有这些行,例如返回受影响的1068行的值。

HISTORYID是桌上的PK。我误解这应该如何工作?任何指导将不胜感激。

+1

我可以看到这种可能的唯一方法是如果表中没有包含'SET NOCOUNT ON'的触发器。否则,如果'HISTORYID'是唯一的,则不会有超过1000行受到影响。 –

+0

如果将上述内容转换为“SELECT”语句,会返回多少行? 'SELECT COUNT(*)FROM TBL_HISTORY WHERE HISTORY_ID IN(SELECT TOP [...]'?我倾向于HISTORYID并不是唯一的... – Shaneis

+0

@Shaneis:HISTORYID是PK。它必须是唯一的OP。 –

回答

1

试试这个(它更快)。如果它仍然更新超过1000行,这是由于触发器。如果它更新1000行,那么HISTORYID不是主键(复合主键)中唯一的列。

;WITH CTE as 
(
    SELECT top 1000 
    DETAILS 
    FROM 
    TBL_HISTORY 
    WHERE 
    DETAILS LIKE '%&QUOT%' 
) 
UPDATE CTE 
SET DETAILS = REPLACE(DETAILS,'&QUOT','Times New Roman') 
+1

太好了,谢谢你,我会放手去检查一下表演。就PK而言,它绝对是一个列键,桌子上没有触发器。我将恢复其中一个数据库的“预先修复”的备份以执行一些测试。至少我不会误解UPDATE应该做什么。以为我失去了阴谋。如果我找到原因,我会更新问题。 – KEW

+2

CTE(或子查询)在这里真的有必要吗?将不可能做'UPDATE TOP(1000)TBL_HISTORY 设置细节=更换(细节,'和QUOT','Times New Roman') 细节如'%&QUOT%'? – cars10m

+0

@ cars10m语法也是有效的 –