powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / UPDATE FROM обновляет по первому значению результата джойна
30 сообщений из 30, показаны все 2 страниц
UPDATE FROM обновляет по первому значению результата джойна
    #39813601
Ёжик25
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Drop table #src;
drop table #trg

create table #src (id int, type int, value nvarchar(20))
insert into #src values (10,8,'888'), (10,8,'777'), (10,8,'999'), (111,8,'999')
create table #trg (id int, type int, value nvarchar(20))
insert into #trg values (10,8,'111')


select #src.value from #trg join #src on #trg.id = #src.id and #trg.type=#src.type --возвращает 3 строки (как и в таблице источнике) со значениями '888','777','999' по полю value


update #trg set #trg.value = #src.value
from #trg join #src on #trg.id = #src.id and #trg.type=#src.type --обновление в таблице #trg произошло только по "первому" значению '888' 



Почему такая конструкция работает и не вызывает ошибки? Ведь по условию возвращается 3 значения. Но SQL выбирает "первое". Слово "первое" в кавычках, потому что, как я понимаю, для реляционной таблицы понятия первой записи не имеет смысла.
Dопрос в том, по какому принципу происходит выборка одного значения, по которому происходит обновление поля value в таблице #trg. Как мне в коде выше узнать, на какое значение обновляется #trg.value.
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813604
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25,

с чего вы решили что обновляет "первое"? оставляет "последнее"
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813608
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKоставляет "последнее"И это описано в документации Microsoft
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813610
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKоставляет "последнее"

А есть какой-то пруф?
Просто, как я помню, не "первое" или "последнее" а просто "одно из".
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813612
Ёжик25
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
iap,

что то ничего не нашел, прошу, дайте ссыль, весь интернет уже облазил на эту тему.
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813613
Ёжик25
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
TaPaK,

выполните приведенный скрипт и посмотрите результат)
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813614
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
msLexTaPaKоставляет "последнее"

А есть какой-то пруф?
Просто, как я помню, не "первое" или "последнее" а просто "одно из".

оно так и будет, предварительно результат не определён, вопрос как будет отсортировано/пересортировано в плане

авторUse caution when specifying the FROM clause to provide the criteria for the update operation. The results of an UPDATE statement are undefined if the statement includes a FROM clause that is not specified in such a way that only one value is available for each column occurrence that is updated, that is if the UPDATE statement is not deterministic. F

авторвыполните приведенный скрипт и посмотрите результат)

нет спасибо
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813615
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKmsLexпропущено...


А есть какой-то пруф?
Просто, как я помню, не "первое" или "последнее" а просто "одно из".

оно так и будет, предварительно результат не определён, вопрос как будет отсортировано/пересортировано в плане

авторUse caution when specifying the FROM clause to provide the criteria for the update operation. The results of an UPDATE statement are undefined if the statement includes a FROM clause that is not specified in such a way that only one value is available for each column occurrence that is updated, that is if the UPDATE statement is not deterministic. F

Это я и сам видел, я хотел увидеть какой-то пруф на "последний" с учетом "сортировки" в плане.
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813617
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
msLexTaPaKпропущено...


оно так и будет, предварительно результат не определён, вопрос как будет отсортировано/пересортировано в плане

пропущено...


Это я и сам видел, я хотел увидеть какой-то пруф на "последний" с учетом "сортировки" в плане.

авторCompute summary values for groups of rows in a suitably sorted stream.
расшифровуйте
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813622
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKавторCompute summary values for groups of rows in a suitably sorted stream.
расшифровуйте
хмм, это откуда?

В справке по update такого нет, поиск в гуле находит только про stream aggregate.
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813623
Ёжик25
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
msLexTaPaKпропущено...


оно так и будет, предварительно результат не определён, вопрос как будет отсортировано/пересортировано в плане

пропущено...


Это я и сам видел, я хотел увидеть какой-то пруф на "последний" с учетом "сортировки" в плане.

как я понял, из за такой "недетерминированности" мы не можем абсолютно точно сказать, каким значением из нескольких будет обновлена запись, и следует в таком случае вводить дополнительную логику, row_count какой нибудь, или времянку с отсортированными значениями из таблицы-источника?
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813624
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
msLexTaPaKпропущено...

расшифровуйте
хмм, это откуда?

В справке по update такого нет, поиск в гуле находит только про stream aggregate.
это тот оператор которое "это" делает. На самом деле вопрос бессмысленный, правильней ответ "не определён" заранее
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813625
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25msLexпропущено...


Это я и сам видел, я хотел увидеть какой-то пруф на "последний" с учетом "сортировки" в плане.

как я понял, из за такой "недетерминированности" мы не можем абсолютно точно сказать, каким значением из нескольких будет обновлена запись, и следует в таком случае вводить дополнительную логику, row_count какой нибудь, или времянку с отсортированными значениями из таблицы-источника?

из-за такой недетерменированности, лучше вообще избегать подобных апдейтов.
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813626
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25msLexпропущено...


Это я и сам видел, я хотел увидеть какой-то пруф на "последний" с учетом "сортировки" в плане.

как я понял, из за такой "недетерминированности" мы не можем абсолютно точно сказать, каким значением из нескольких будет обновлена запись, и следует в таком случае вводить дополнительную логику, row_count какой нибудь, или времянку с отсортированными значениями из таблицы-источника?
пусть sql угадывает какое же значение ты хотел получить
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813628
Ёжик25
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
msLexЁжик25пропущено...


как я понял, из за такой "недетерминированности" мы не можем абсолютно точно сказать, каким значением из нескольких будет обновлена запись, и следует в таком случае вводить дополнительную логику, row_count какой нибудь, или времянку с отсортированными значениями из таблицы-источника?

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




Вообще все началось с того, что я пытаюсь из SQL в Postgresql засунуть логику MERGE, которая, кстати, ругается на несколько результирующих значений и не работает.

Пока только через вот такую конструкцию получилось:
WITH cte (
update target from source ...returning ...)insert ...select ...from source left join cte on ...where cte ... is null

ну и вот столкнулся с такой "недетерминированностью" операции UPDATE.

Что ж, придется вводить таки дополнительную логику.

Всех благодарю. Вопрос закрыт.
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813630
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKэто тот оператор которое "это" делает.
"это" вполне может делать и hash aggregate
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813634
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25Но SQL выбирает "первое".
MS как-то не любит распространяться о внутренней кухне, предпочитая просто рассказать про недетерминированность.
В доке к MySQL, например, чётко написано - любая запись обновляется только один раз за запрос. Отсюда и "первой записью" - остальные попытки обновления этой же записи игнорятся, ибо "уже было". А уж какая реально будет "первая" - это фиг знает, бо сортировки в подзапросах (без TOP N) тупо игнорятся (а местами так и вовсе запрещены, вроде).
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813635
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
msLexTaPaKэто тот оператор которое "это" делает.
"это" вполне может делать и hash aggregate
а делает stream aпgregate... или вы предлагаете на этапе join выбрасывать всё?
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813637
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25iap,

что то ничего не нашел, прошу, дайте ссыль, весь интернет уже облазил на эту тему.У меня была неточность: последнее значение присваивается переменной в SELECTе, если он возвращает несколько значений.

Код: sql
1.
SELECT @Var=FieldValue FROM TableName



С UPDATE это не связано.

Про UPDATE написано следующее:

https://docs.microsoft.com/ru-ru/sql/t-sql/queries/update-transact-sql?view=sql-server-2017 Проявляйте осторожность, указывая предложение FROM при задании критериев для операции обновления. Результаты инструкции UPDATE не определены, если инструкция включает предложение FROM, в котором для каждого вхождения обновляемого столбца не задано единственное значение , то есть если инструкция UPDATE не является детерминированной. Например, в инструкции UPDATE следующего скрипта обе строки в Table1 удовлетворяют условиям предложения FROM в инструкции UPDATE, но не определено, какая строка из Table1 используется для обновления строки в Table2

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
USE AdventureWorks2012;  
GO  
IF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL  
    DROP TABLE dbo.Table1;  
GO  
IF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL  
    DROP TABLE dbo.Table2;  
GO  
CREATE TABLE dbo.Table1   
    (ColA int NOT NULL, ColB decimal(10,3) NOT NULL);  
GO  
CREATE TABLE dbo.Table2   
    (ColA int PRIMARY KEY NOT NULL, ColB decimal(10,3) NOT NULL);  
GO  
INSERT INTO dbo.Table1 VALUES(1, 10.0), (1, 20.0);  
INSERT INTO dbo.Table2 VALUES(1, 0.0);  
GO  
UPDATE dbo.Table2   
SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB  
FROM dbo.Table2   
    INNER JOIN dbo.Table1   
    ON (dbo.Table2.ColA = dbo.Table1.ColA);  
GO  
SELECT ColA, ColB   
FROM dbo.Table2;
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813640
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKmsLexпропущено...

"это" вполне может делать и hash aggregate
а делает stream aпgregate... или вы предлагаете на этапе join выбрасывать всё?
Еще раз, "это" не обязательно делает stream aggregate, "это" может делаться и SQL сервером и через Hash aggregate с aggrtype any
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813642
Ёжик25
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
iap,

вообще, конечно, я был очень удивлен такому поведению. Следовало бы, на мой взгляд, возвращать ошибку обновления, как это делается при MERGE. Ну давайте с тем же успехом переменной присваивать "первое" значение из множественного набора результата SELECT. Чего уж там!))))
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813643
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25iap,

вообще, конечно, я был очень удивлен такому поведению. Следовало бы, на мой взгляд, возвращать ошибку обновления, как это делается при MERGE. Ну давайте с тем же успехом переменной присваивать "первое" значение из множественного набора результата SELECT. Чего уж там!))))

Поведение странное, но оно задокументировано, что автомат превращает его (поведение) в фичу.
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813646
Посетитель
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25iap,

вообще, конечно, я был очень удивлен такому поведению. Следовало бы, на мой взгляд, возвращать ошибку обновления, как это делается при MERGE. Ну давайте с тем же успехом переменной присваивать "первое" значение из множественного набора результата SELECT. Чего уж там!))))

напишите свой SQL Server и управляйте его поведением как пожелаете.
зачем удивляться тому, что поведение соответствует описанию в документации?
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813654
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25iap,

вообще, конечно, я был очень удивлен такому поведению. Следовало бы, на мой взгляд, возвращать ошибку обновления, как это делается при MERGE. Ну давайте с тем же успехом переменной присваивать "первое" значение из множественного набора результата SELECT. Чего уж там!))))Полностью согласен.
Правда, UPDATE появился на 200 лет раньше

Таких моментов много. Например, во многих случаях необязательно строго придерживаться
заявленного стиля даты в функции CONVERT() - сервер сконвертирует даже приблизительно
похожую на дату строку. Разве не безобразие? Строгости к нам, балбесам, не хватает!
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813656
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25iap,

вообще, конечно, я был очень удивлен такому поведению. Следовало бы, на мой взгляд, возвращать ошибку обновления, как это делается при MERGE. Ну давайте с тем же успехом переменной присваивать "первое" значение из множественного набора результата SELECT. Чего уж там!))))
вперёд в спортлото

https://feedback.azure.com/forums/908035-sql-server
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813657
Ёжик25
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Посетитель,

потому что такое поведение нелогично с точки зрения логики и с точки зрения реляционной теории, и не очевидно. Знать наизусть всю документацию нереально. А конструкция не выдает ошибки.
Как с теми же переменными, которые ругаются, когда пытаешься присвоить им несколько значений. По той же логике, по сути мы обновляем запись в целевой таблице некой "переменной", которая приняла в операции UPDATE значение, прочитанное из другой таблицы.
Сугубо имхо))).
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813662
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25Посетитель,

потому что такое поведение нелогично с точки зрения логики и с точки зрения реляционной теории, и не очевидно. Знать наизусть всю документацию нереально. А конструкция не выдает ошибки.
Как с теми же переменными, которые ругаются, когда пытаешься присвоить им несколько значений. По той же логике, по сути мы обновляем запись в целевой таблице некой "переменной", которая приняла в операции UPDATE значение, прочитанное из другой таблицы.
Сугубо имхо))).Если написать SELECT @V=V FROM T, то SELECT может вернуть хоть миллиард записей, - присвоится последнее (я, кажется, это уже говорил).
А вот если SET @V=(SELECT V FROM T)то SELECT в скобках обязан вернуть не более одного значения,
ибо это скалярное выражение. Иначе обругается.
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813683
Ёжик25
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
iapЁжик25Посетитель,

потому что такое поведение нелогично с точки зрения логики и с точки зрения реляционной теории, и не очевидно. Знать наизусть всю документацию нереально. А конструкция не выдает ошибки.
Как с теми же переменными, которые ругаются, когда пытаешься присвоить им несколько значений. По той же логике, по сути мы обновляем запись в целевой таблице некой "переменной", которая приняла в операции UPDATE значение, прочитанное из другой таблицы.
Сугубо имхо))).Если написать SELECT @V=V FROM T, то SELECT может вернуть хоть миллиард записей, - присвоится последнее (я, кажется, это уже говорил).
А вот если SET @V=(SELECT V FROM T)то SELECT в скобках обязан вернуть не более одного значения,
ибо это скалярное выражение. Иначе обругается.

Забавно, а вот PG присваивает первое значение при SELECT @V=V FROM T.
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813844
step_ks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25, может еще и так быть
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
if object_id('tempdb..#src') is not null Drop table #src;
if object_id('tempdb..#trg') is not null drop table #trg;
GO

create table #src (id int, type int, value1 nvarchar(20),value2 nvarchar(20))
insert into #src (id,type,value1,value2)  values (10,8,'888',null), (10,8,'777','ccc'), (10,8,'999',null), (111,8,'999',null)

create table #trg (id int, type int, value1 nvarchar(20),value2 nvarchar(20))
insert into #trg (id,type,value1) values (10,8,'111')


select * from #src
select * from #trg

update #trg set
        value1 = #src.value1,
        value2 = #src.value2
    from #trg join #src on #trg.id = #src.id and #trg.type=#src.type;

select * from #trg
GO



Результаты:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
-- select * from #src
id          type        value1               value2
----------- ----------- -------------------- --------------------
10          8           888                  NULL
10          8           777                  ccc
10          8           999                  NULL
111         8           999                  NULL

-- select * from #trg
id          type        value1               value2
----------- ----------- -------------------- --------------------
10          8           111                  NULL


-- select * from #trg после update
id          type        value1               value2
----------- ----------- -------------------- --------------------
10          8           888                  ccc
...
Рейтинг: 0 / 0
UPDATE FROM обновляет по первому значению результата джойна
    #39813849
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёжик25потому что такое поведение нелогично с точки зрения логики и с точки зрения реляционной теории, и не очевидно. Знать наизусть всю документацию нереально. А конструкция не выдает ошибки.Да, наверное, с точки зрения чистой теории это неправильно.
Но так было сделано во всех без исключения реализациях SQL, наверное, потому, что UPDATE с джойнами часто даёт повторяющиеся значения, и генерить ошибку было бы непрактично. Поэтому сделали обновление случайной записью.

То есть это теоретически неправильно, но вполне логично.

Тем более, не забывайте, когда это было сделано - в 70-е, 80-е. Вспомните, что такое SQL, и зачем он появился.
Тогда же, например, придумали понятие "владелец объекта", что бы 2 бухгалтера, набирая запросы в SQL для составления ведомости на зарплату, или сведения квартального баланса, не мешали друг другу.

А MERGE, или скалярный подзапрос, или присвоегие переменной в SET, придумали намного позже, это более сложные конструкции, они расчитаны на программистов, а не бухгалтеров, и они более строгие.
...
Рейтинг: 0 / 0
30 сообщений из 30, показаны все 2 страниц
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / UPDATE FROM обновляет по первому значению результата джойна
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]