Как проверить, отличается ли новое значение от старого для пустых столбцов - PullRequest
0 голосов
/ 31 мая 2018

Цель состоит в том, чтобы предотвратить обновления для строк, в которых новое значение идентично старому значению (поскольку таблица имеет автоматически обновляемую метку времени, которую я не хочу сбрасывать).

Проблема заключается в том, чтонекоторые столбцы обнуляются, поэтому New <> Old не работает, так как это приводит к NULL, если New или Old равен NULL.

Обходной путь использует ISNULL, но это не работает, если значение замены может бытьдопустимое значение в таблице:

UPDATE tableName
SET ColumnName = @newValue
WHERE ISNULL(ColumnName, 'ValueIsNull') <> ISNULL(@newValue, 'ValueIsNull')

Другой способ, который я нашел, это сравнение значений, а затем проверка XOR New и Old, чтобы увидеть, является ли либо NULL.Это не очень понятно, особенно если вам нужно проверить несколько столбцов:

UPDATE tableName
SET ColumnName = @newValue
WHERE
    ColumnName <> @newValue
    OR (
        (ColumnName IS NULL AND @newValue IS NOT NULL)
        OR (ColumnName IS NOT NULL AND @newValue IS NULL)
    )

Есть ли лучший способ сделать это?

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Мне нравится этот метод, потому что вы можете легко сравнивать несколько столбцов одновременно.Запустите его, и вы увидите, что он обновляет строку только тогда, когда изменяются столбцы, о которых вы заботитесь.

DECLARE @T1 TABLE (ID INT, Val1 VARCHAR(20),Val2 VARCHAR(20),LastUpdated DATETIME,VersionNum INT)
DECLARE @Val1 VARCHAR(20)='test'
DECLARE @Val2 VARCHAR(20)='test2'
INSERT INTO @T1 (ID,Val1,Val2,LastUpdated,VersionNum) SELECT 1,@Val1,@Val2,GETDATE(),1

SELECT * FROM @T1

UPDATE @T1
SET Val1=@Val1,Val2=@Val2, LastUpdated=GETDATE(),VersionNum=VersionNum+1
WHERE BINARY_CHECKSUM(Val1,Val2)<>BINARY_CHECKSUM(@Val1,@Val2)

SELECT * FROM @T1

SET @Val1 ='test'
SET @Val2 ='Oooooo'

UPDATE @T1
SET Val1=@Val1,Val2=@Val2, LastUpdated=GETDATE(),VersionNum=VersionNum+1
WHERE BINARY_CHECKSUM(Val1,Val2)<>BINARY_CHECKSUM(@Val1,@Val2)

SELECT * FROM @T1
0 голосов
/ 31 мая 2018

Вот одна хитрость:

UPDATE t
    SET ColumnName = @newValue
    FROM tableName t CROSS APPLY
         (SELECT COUNT(*) as num_values
          FROM (SELECT DISTINCT val
                FROM (VALUES (ColumnName), (@newValue) )  v(val)
               ) v
         ) v
    WHERE num_values <> 1;

SQL Server не поддерживает IS DISTINCT FROM.Но агрегация имеет правильную логику, которую вы хотите.Если значения равны или оба NULL, то счетчик равен 1. В противном случае счет будет равен 0 или 2.

...