Что может привести к тому, что «затронутые строки» будут неверными?

Используя 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 строк. Но UPDATE влияет на одну строку меньше, чем SELECT получает из БД:

(затронуты 61 ряд)

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

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

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


person Indrek    schedule 05.10.2010    source источник
comment
Таблица a имеет две строки с одинаковым идентификатором?   -  person Arvo    schedule 05.10.2010
comment
поле идентификатора уникально в обеих таблицах?   -  person Beth    schedule 05.10.2010


Ответы (2)


Я подозреваю, что наиболее вероятная причина заключается в том, что 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
person SqlRyan    schedule 05.10.2010
comment
Это была table_a, у которой были дубликаты внешних ключей table_b, которые я не мог найти, в результате чего внутреннее соединение выбрало 2 строки, но обновление затронуло только одну строку в table_b. Я был совершенно уверен, что это запрещено, но думаю, кто-то в 2004 году подумал, что это отличная идея! Спасибо за ответ. - person Indrek; 06.10.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

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

person A-K    schedule 05.10.2010