Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
PetrovichSK
Guest
Доброго всем
SELECT @@VERSION

Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64)
Jun 17 2016 19:14:09
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 14393: )

А теперь фокус
DECLARE @NewID UNIQUEIDENTIFIER = NEWID()

DECLARE @T TABLE (PK INT PRIMARY KEY, ID UNIQUEIDENTIFIER)
INSERT INTO @T VALUES(1, NULL)

WHILE 1 = 1
BEGIN

	UPDATE @T SET ID = @NewID WHERE PK = 1 AND ISNULL(ID, NEWID()) <> @NewID
	
	IF @@ROWCOUNT = 0
	BEGIN
		SELECT 'WTF',  *, @NewID FROM @T WHERE PK = 1

		BREAK
	END

	UPDATE @T SET ID = NULL WHERE PK = 1 
	
END


Подскажите, каким макаром оно может попасть в IF @@ROWCOUNT = 0?
Это баг? Кто нибудь его репортал уже?
5 янв 17, 16:34    [20075202]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
SQL2008
Member

Откуда: Москва
Сообщений: 4422
Надеюсь, вы в курсе, что это

UPDATE @T SET ID = @NewID WHERE PK = 1 AND ISNULL(ID, NEWID()) <> @NewID

никогда не выполнится?
5 янв 17, 16:56    [20075250]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
SQL2008
Member

Откуда: Москва
Сообщений: 4422
Имелось, конечно же в виду условие

... ISNULL(ID, NEWID()) <> @NewID
5 янв 17, 16:58    [20075257]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
SQL2008
Member

Откуда: Москва
Сообщений: 4422
SQL2008
Надеюсь, вы в курсе, что это

UPDATE @T SET ID = @NewID WHERE PK = 1 AND ISNULL(ID, NEWID()) <> @NewID

никогда не выполнится?

Точнее, с учетом вышесказанного, выполняется всегда.
5 янв 17, 17:00    [20075261]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
PetrovichSK
Guest
SQL2008
SQL2008
Надеюсь, вы в курсе, что это

UPDATE @T SET ID = @NewID WHERE PK = 1 AND ISNULL(ID, NEWID()) <> @NewID

никогда не выполнится?

Точнее, с учетом вышесказанного, выполняется всегда.

Угу. Я тоже был уверен, что это условие выполняется всегда. И мой цикл будет бесконечным.
Т.е. всегда будет выполнятся UPDATE и на IF я НИКОГДА не выйду.
Однако, если Вы запустите мой скрипт, то увидите, что это не так.
5 янв 17, 17:16    [20075309]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
o-o
Guest
SQL2008
Надеюсь, вы в курсе, что это

UPDATE @T SET ID = @NewID WHERE PK = 1 AND ISNULL(ID, NEWID()) <> @NewID

никогда не выполнится?

выполняется, да еще и на разных итерациях, то сразу, то через черт знает сколько,
в последний раз 40 итераций было прежде, чем выполнилось

DECLARE @NewID UNIQUEIDENTIFIER = NEWID()
declare @i int = 0;

declare @rc int;

DECLARE @T TABLE (PK INT PRIMARY KEY, ID UNIQUEIDENTIFIER)
INSERT INTO @T VALUES(1, NULL)

WHILE 1 = 1
BEGIN
    select '@i = ' + cast(@i as varchar(10));
	UPDATE @T SET ID = @NewID WHERE PK = 1 AND ISNULL(ID, NEWID())  <> @NewID
	set @rc = @@ROWCOUNT
	select '@rc = ' + cast(@rc as varchar(10));
	select @NewID FROM @T WHERE PK = 1
	
	IF  @rc = 0
	BEGIN
		SELECT 'WTF',  *, @NewID FROM @T WHERE PK = 1

		BREAK
	END

	UPDATE @T SET ID = NULL WHERE PK = 1 
	set @i = @i + 1
END
5 янв 17, 17:22    [20075330]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
invm
Member

Откуда: Москва
Сообщений: 9683
PetrovichSK
Однако, если Вы запустите мой скрипт, то увидите, что это не так.
Дело в том как оптимизатор раскрывает предикат ISNULL(ID, NEWID()) <> @NewID, а раскрывает он его в
isnull([ID],newid())<[@NewID] OR isnull([ID],newid())>[@NewID]
В результате newid() вычисляется два раза вместо одного и иногда это приводит к озвученному результату.
Налицо баг. Возможно на коннекте уже есть соответствующий запрос.

Сделайте через промежуточную переменную и эффект пропадет.
5 янв 17, 18:14    [20075438]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
PetrovichSK
Guest
invm
PetrovichSK
Однако, если Вы запустите мой скрипт, то увидите, что это не так.
Дело в том как оптимизатор раскрывает предикат ISNULL(ID, NEWID()) <> @NewID, а раскрывает он его в
isnull([ID],newid())<[@NewID] OR isnull([ID],newid())>[@NewID]
В результате newid() вычисляется два раза вместо одного и иногда это приводит к озвученному результату.
Налицо баг. Возможно на коннекте уже есть соответствующий запрос.

Сделайте через промежуточную переменную и эффект пропадет.

Спасибо большое за обьяснение.
А я то и забыл, как <> раскрывается. Позор на мою седую голову....
Предложенный Вами вариант с переменной сделали сразу. Там еще можно и 0x0 он же '00000000-0000-0000-0000-000000000000' использовать, если быть уверенным, что никто насильно в таблице не вставил такое значение.
Еще раз спасибо. Все стало на места в моей голове.
5 янв 17, 18:53    [20075511]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
iljy
Member

Откуда:
Сообщений: 8711
PetrovichSK,

а можно написать
(ID is null or ID <> @NewID)


и не ломать голову.
5 янв 17, 19:01    [20075536]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
PetrovichSK
Guest
iljy
PetrovichSK,

а можно написать
(ID is null or ID <> @NewID)


и не ломать голову.

Я обычно так и пишу. А вот напарница любит ISNULL и COALESCE :). Вот и вылезло...
С другой стороны, когда, как не на таких полетах, всомнишь основы. :D
Еще раз спасибо, что уделили мне время.
5 янв 17, 19:21    [20075576]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
iljy
Member

Откуда:
Сообщений: 8711
PetrovichSK,

тогда уж лучше писать NULLIF(@NewID, ID) IS NOT NULL. Хотя в любом случае подобная запись блокирует использование индексов.
5 янв 17, 19:33    [20075609]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
aleks2
Guest
iljy
PetrovichSK,

а можно написать
(ID is null or ID <> @NewID)


и не ломать голову.


Писать надо
not exists( select ID except select @NewID )

и чудо сравнения с NULL произойдет.
6 янв 17, 06:50    [20076831]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
PetrovichSK
Guest
aleks2
iljy
PetrovichSK,

а можно написать
(ID is null or ID <> @NewID)


и не ломать голову.


Писать надо
not exists( select ID except select @NewID )

и чудо сравнения с NULL произойдет.

Откуда категоричное НАДО? Всего лишь один из вариантов синтаксиса сравнения, которые не приводят к той неприятности, что я запостал... Причем не самый очевидный для понимания.
6 янв 17, 07:40    [20076844]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
aleks2
Guest
PetrovichSK
aleks2
пропущено...


Писать надо
not exists( select ID except select @NewID )

и чудо сравнения с NULL произойдет.

Откуда категоричное НАДО? Всего лишь один из вариантов синтаксиса сравнения, которые не приводят к той неприятности, что я запостал... Причем не самый очевидный для понимания.


Ты не возбуждайся - это не для тебя.

ЗЫ. Ты можешь продолжать писать "очевидно для понимания". Хе-хе.
6 янв 17, 08:03    [20076852]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
PetrovichSK
Guest
aleks2
Ты не возбуждайся - это не для тебя.

ЗЫ. Ты можешь продолжать писать "очевидно для понимания". Хе-хе.

Никогда не понимал людей, которые вместо конструктивного диалога пытаются самоутвердиться путем оскорбления собеседника.
А теперь в тему. Есть логичное обоснование чем используемый Вами синтаксис лучше любого другого?
P.S. И попросил бы мне не тыкать. Я с Вами телят не пас.
6 янв 17, 10:00    [20076904]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
iljy
Member

Откуда:
Сообщений: 8711
aleks2
Писать надо
not exists( select ID except select @NewID )

и чудо сравнения с NULL произойдет.


Так писать как раз не надо. Не знаю почему, но, в отличии от exists( select ID intersect select @NewID ), оптимизатор not exists и except не умеет преобразовывать в проверки на равенство/неравенство и всегда реализует как Nested Loop. Что автоматом убивает даже теоретическую возможность использования индексов.
6 янв 17, 10:59    [20076989]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
aleks2
Guest
iljy
aleks2
Писать надо
not exists( select ID except select @NewID )

и чудо сравнения с NULL произойдет.


Так писать как раз не надо. Не знаю почему, но, в отличии от exists( select ID intersect select @NewID ), оптимизатор not exists и except не умеет преобразовывать в проверки на равенство/неравенство и всегда реализует как Nested Loop. Что автоматом убивает даже теоретическую возможность использования индексов.


Осознай тривиальную истину: индексы нужны не фсегда.
Но
not exists( select A except select B )


позволяет раза в три-четыре короче написать
 ( A is null or A <> B or B is null) and (хотя бы что-то из AиB не null)


Причем именно в контексте UPDATE тредстартера, где индекс - это PK и строку он однозначно определяет.
А когда полей "за десять" - это очень помогает. Ишо и на знаке неравенства и and экономишь.
6 янв 17, 11:16    [20077027]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
PetrovichSK
Guest
iljy
aleks2
Писать надо
not exists( select ID except select @NewID )

и чудо сравнения с NULL произойдет.


Так писать как раз не надо. Не знаю почему, но, в отличии от exists( select ID intersect select @NewID ), оптимизатор not exists и except не умеет преобразовывать в проверки на равенство/неравенство и всегда реализует как Nested Loop. Что автоматом убивает даже теоретическую возможность использования индексов.

Если сравнение идет по многим записям - однозначно нет.
Если же, как в моем примере выбирается всего одна запись причем по PK и второе условие на UPDATE нужно всего лишь чтоб не менять на то же самое значение, то можно и такой синтаксис.
iljy, Я не прав?
6 янв 17, 11:16    [20077028]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
PetrovichSK
Guest
aleks2
Причем именно в контексте UPDATE тредстартера, где индекс - это PK и строку он однозначно определяет.
А когда полей "за десять" - это очень помогает. Ишо и на знаке неравенства и and экономишь.

Причем именно в контексте UPDATE тредстартера надо писать именно AND EXISTS(select ID except select @NewID ). Без всякого NOT :)
Я не прав?
6 янв 17, 11:44    [20077077]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
iljy
Member

Откуда:
Сообщений: 8711
PetrovichSK,

такой синтаксис действительно можно использовать для краткости записи, если полей много - полное выражение будет очень громоздким.
6 янв 17, 11:50    [20077087]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
PetrovichSK
Guest
iljy
PetrovichSK,

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

Да я как бы и использовал уже не раз. Именно поэтому и удивился not exists
6 янв 17, 11:56    [20077091]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
invm
Member

Откуда: Москва
Сообщений: 9683
aleks2
Писать надо
Осознай тривиальную истину: чтобы понять "как надо", нужно план выполнения анализировать, а не в астрале витать, познавая суть вещей.

Так что сравни для осознания
select ... where not exists(select ID except select @NewID)
и
select ... where exists(select ID intersect select @NewID)
6 янв 17, 12:12    [20077126]     Ответить | Цитировать Сообщить модератору
 Re: Сравнение ISNULL(поле, NEWID()) c другим UNIQUEIDENTIFIER при UPDATE не работает  [new]
MSSQLAndDotNet
Member

Откуда:
Сообщений: 10398
если SARG, то IS NULL
иначе COALESCE

если SELECT INTO, то ISNULL

вроде так
9 янв 17, 14:08    [20084723]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить