Что может привести к тому, что «затронутые строки» будут неправильными? - PullRequest
8 голосов
/ 05 октября 2010

Использование Microsoft SQL Server Management Studio 2008. Я сделал простую транзакцию:

BEGIN TRAN

SELECT ko.ID, os.ID AS ID2
FROM table_a AS ko
JOIN table_b AS os ON os.ID=ko.ID
WHERE (ko.the_date IS NOT NULL AND os.the_date IS NULL);

UPDATE table_b SET the_date=ko.the_date
FROM table_a AS ko
JOIN table_b AS os ON os.ID=ko.ID
WHERE (ko.the_date IS NOT NULL AND os.the_date IS NULL);

SELECT ko.ID, os.ID AS ID2
FROM table_a AS ko
JOIN table_b AS os ON os.ID=ko.ID
WHERE (ko.the_date IS NOT NULL AND os.the_date IS NULL);


ROLLBACK

Таким образом, SELECT и UPDATE должны быть одинаковыми.И результат должен вернуть 0 строк.Но ОБНОВЛЕНИЕ влияет на одну строку меньше, чем SELECT получает от БД:

(затронуто 61 строк)

(затронуто 60 строк)

(0затронутые строки)

Что мне здесь не хватает?

Ответы [ 2 ]

2 голосов
/ 05 октября 2010

Я подозреваю, что наиболее вероятная причина в том, что Table_a в вашем примере содержит строку с повторяющимся идентификатором - в этом случае дополнительная строка появляется в объединении в вашем первом select, но только update имеет дело со строками в Table_b, поэтому ваша дублирующаяся строка не имеет значения. Это утверждение должно дать вам виновника:

SELECT ko.ID
FROM table_a AS ko
JOIN table_b AS os ON os.ID=ko.ID
WHERE (ko.the_date IS NOT NULL AND os.the_date IS NULL)
GROUP BY ko.ID
HAVING COUNT(*) > 1
0 голосов
/ 05 октября 2010

UPDATE ... FROM не обнаруживает неоднозначности, подобные этой:

CREATE TABLE dbo.source
    (
      id INT NOT NULL ,
      SomeNumber INT
    )
GO
CREATE TABLE dbo.target
    (
      id INT NOT NULL
             PRIMARY KEY ,
      SomeNumber INT
    )
GO
INSERT  INTO dbo.source
        ( id, SomeNumber )
        SELECT  1 ,
                2
        UNION ALL
        SELECT  1 ,
                3

INSERT  INTO dbo.target
        ( id, SomeNumber )
        SELECT  1 ,
                0

UPDATE  dbo.TARGET
SET     SomeNumber = s.SomeNumber
FROM    dbo.source AS s
        JOIN dbo.TARGET AS t ON s.id = t.id

Строка в вашей целевой таблице содержит два совпадения в источнике, и мы не можем заранее знать, какое значение в конечном итоге обновитцель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...