У меня есть база данных с account numbers и card numbers. Я сопоставляю их с файлом на update, любые номера карт с номером счета, так что я работаю только с номерами счетов.
Я создал представление, связывающее таблицу с базой данных учетной записи / карты, чтобы вернуть Table ID и соответствующий номер учетной записи, и теперь мне нужно обновить те записи, в которых идентификатор совпадает с номером учетной записи.
Это таблица Sales_Import, в которой необходимо обновить поле account number:
LeadID AccountNumber
147 5807811235
150 5807811326
185 7006100100007267039
А это таблица RetrieveAccountNumber, откуда мне нужно обновить:
LeadID AccountNumber
147 7006100100007266957
150 7006100100007267039
Я попробовал следующее, но пока не повезло:
UPDATE [Sales_Lead].[dbo].[Sales_Import]
SET [AccountNumber] = (SELECT RetrieveAccountNumber.AccountNumber
FROM RetrieveAccountNumber
WHERE [Sales_Lead].[dbo].[Sales_Import]. LeadID =
RetrieveAccountNumber.LeadID)
Он обновляет номера карт до номеров счетов, но номера счетов заменяются на NULL.


Я считаю, что UPDATE FROM с JOIN поможет:
UPDATE
Sales_Import
SET
Sales_Import.AccountNumber = RAN.AccountNumber
FROM
Sales_Import SI
INNER JOIN
RetrieveAccountNumber RAN
ON
SI.LeadID = RAN.LeadID;
UPDATE
Sales_Import SI,
RetrieveAccountNumber RAN
SET
SI.AccountNumber = RAN.AccountNumber
WHERE
SI.LeadID = RAN.LeadID;
В предложении set вы должны изменить SI.AccountNumber на просто AccountNumber, иначе он выйдет из строя.
MS-Access использует другое UPDATE с оператором JOIN. Посмотрите: sql-und-xml.de/sql-tutorial/…
Вы не можете использовать псевдоним таблицы в предложении обновления. Однако я обновил образец, чтобы напрямую ссылаться на обновленную таблицу.
кажется, это нормально для mssql, но, похоже, не работает в mysql. Хотя, похоже, это работает: UPDATE Sales_Import, RetrieveAccountNumber SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;. Немного не по теме, но может быть полезно
Думаю, во внутреннем соединении нет необходимости. Решение Vonki, приведенное ниже, работает: UPDATE [Sales_Lead]. [Dbo]. [Sales_Import] SET [AccountNumber] = RetrieveAccountNumber.AccountNumber FROM RetrieveAccountNumber WHERE [Sales_Lead]. [Dbo]. [Sales_Import] .LeadID = RetrieveLeadIDNumber].
@Gutti По крайней мере, в простых случаях план объяснения тот же: сканирование таблиц -> совпадение хэша -> сортировка -> обновление
@Edd: Я добавил ваше решение MySQL в ответ.
@ MarkS.Rasmussen Фактически вы можете использовать псевдоним как в предложениях update, так и в set. "обновить псевдоним установить alias.column = alias2.column из таблицы1 как псевдоним, присоединиться к таблице2 как псевдоним2 ..." работает.
Вы также можете использовать JOIN в MySQL UPDATE Sales_Import JOIN RetrieveAccountNumber ON Sales_Import.LeadID = RetrieveAccountNumber.LeadID SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber
Это работает лучше, чем ответ ниже, поскольку INNER JOIN решает ошибку «необходимо объявить скалярную переменную» при использовании определенного пользователем типа таблицы в качестве параметра для хранимой процедуры.
Набор должен находиться под соединением на
почему этот комментарий не отображается как верхний ответ, первый, который увидит, не может ли алгоритм отрегулировать это?
Это просто спасло мне день! Спасибо.
Кажется, вы используете MSSQL, значит, если я правильно помню, делается это так:
UPDATE [Sales_Lead].[dbo].[Sales_Import] SET [AccountNumber] =
RetrieveAccountNumber.AccountNumber
FROM RetrieveAccountNumber
WHERE [Sales_Lead].[dbo].[Sales_Import].LeadID = RetrieveAccountNumber.LeadID
Спасибо за ответы. Я нашел решение.
UPDATE Sales_Import
SET AccountNumber = (SELECT RetrieveAccountNumber.AccountNumber
FROM RetrieveAccountNumber
WHERE Sales_Import.leadid =RetrieveAccountNumber.LeadID)
WHERE Sales_Import.leadid = (SELECT RetrieveAccountNumber.LeadID
FROM RetrieveAccountNumber
WHERE Sales_Import.leadid = RetrieveAccountNumber.LeadID)
Независимо от того, работает ли приведенный здесь код, вам, вероятно, следует посмотреть на два других опубликованных решения. Они намного яснее и менее подвержены ошибкам, а также почти наверняка быстрее.
Замечание об этом решении, UPDATE ... FROM является проприетарным, поэтому, если вы не можете использовать оператор MERGE, потому что вы используете SQL 2005 или более раннюю версию, это ANSI-совместимый метод выполнения обновлений с источником таблицы в MSSQL. Источник: sqlblog.com/blogs/hugo_kornelis/archive/2008/03/10/…
единственное решение, которое работает для меня, потому что это стандартный оператор обновления SQL (UPDATE SET WHERE), большое спасибо
У меня была такая же проблема с foo.new, установленным на null для строк foo, у которых не было соответствующего ключа в bar. Я сделал что-то подобное в Oracle:
update foo
set foo.new = (select bar.new
from bar
where foo.key = bar.key)
where exists (select 1
from bar
where foo.key = bar.key)
Почему требуется ГДЕ СУЩЕСТВУЕТ?
Поскольку каждая строка в foo, не имеющая соответствия в bar, оказалась нулевой, потому что оператор select произвел null. Надеюсь, это было яснее, чем моя первая попытка объяснить это.
отметьте этот ответ ниже stackoverflow.com/questions/224732/…
@KjellAndreassen Вы решили мою проблему. Спасибо за ваш код.
Простой способ скопировать содержимое из одной таблицы в другую:
UPDATE table2
SET table2.col1 = table1.col1,
table2.col2 = table1.col2,
...
FROM table1, table2
WHERE table1.memberid = table2.memberid
Вы также можете добавить условие для копирования определенных данных.
Это работает, но вам не нужна table2 в FROM UPDATE table2 SET table2.col1 = table1.col1, table2.col2 = table1.col2, ... FROM table1 WHERE table1.memberid = table2.memberid
Это не сработало, но ОБНОВЛЕНИЕ table2, table1 SET table2.col1 = table1.col1, ... WHERE table1.memberid = table2.memberid (mysql и phpmyadmin)
Для SQL Server 2008 + Использование MERGE вместо проприетарного синтаксиса UPDATE ... FROM имеет некоторую привлекательность.
Помимо того, что он является стандартным SQL и, следовательно, более переносимым, он также вызовет ошибку в случае наличия нескольких соединенных строк на исходной стороне (и, следовательно, нескольких возможных различных значений для использования в обновлении), вместо того, чтобы окончательный результат был неопределенным. .
MERGE INTO Sales_Import
USING RetrieveAccountNumber
ON Sales_Import.LeadID = RetrieveAccountNumber.LeadID
WHEN MATCHED THEN
UPDATE
SET AccountNumber = RetrieveAccountNumber.AccountNumber;
К сожалению, выбор того, что использовать, может не сводиться исключительно к предпочтительному стилю. Реализация MERGE в SQL Server страдает различными ошибками. Аарон Бертран составил список сообщенные здесь.
Я никогда не знал о синтаксисе слияния. Это намного чище, чем Update + Join.
+1 для отчета о реализации MERGE SQL Server
Большое спасибо, Мартин! Я искал это с тех пор, как много дней, наконец, заработал :)
MERGE - это здорово, но стоит отметить, что он не будет работать, если вы используете связанный сервер The target of a MERGE statement cannot be a remote table, a remote view, or a view over remote tables..
Аргументы в пользу использования MERGE (включая те, что указаны в сообщение с sqlblog.com, ссылка на которые приведена выше) могут быть убедительными, но нужно учитывать, что согласно MSDN: ... Оператор MERGE работает лучше всего, когда две таблицы имеют сложную смесь совпадающих характеристик ... При простом обновлении одной таблицы на основе строк другой таблицы улучшенная производительность и масштабируемость могут быть достигнуты с помощью базовых операторов INSERT, UPDATE и DELETE.
Я понимаю, что сейчас он устарел, но связанный пост Бертрана говорит: «Однако изначально MERGE поставлялся с несколькими «неверными результатами» и другими ошибками ... некоторые из которых продолжают существовать даже в ранних предварительных версиях SQL Server 2014 ... Я рекомендовал, чтобы - пока - люди придерживались своих проверенных и верных методов отдельных утверждений.» (эмф мой) См. Также его комментарий к January 26, 2014 - 8:28:58 PM. @MartinSmith - Есть ли основания подозревать, что сейчас дела обстоят лучше?
FWIW не работает с Access, поставляемым с MS Office 365 Pro Plus.
@ jkp1187 Этот вопрос помечен тегом SQL Server. Так что RE: FWIW - примерно ноль.
@MartinSmith Для людей с ограниченным опытом, которые попали на эту страницу благодаря результатам поисковой системы, это ненулевое значение.
Для MySql, который отлично работает:
UPDATE
Sales_Import SI,RetrieveAccountNumber RAN
SET
SI.AccountNumber = RAN.AccountNumber
WHERE
SI.LeadID = RAN.LeadID
Я подумал, что это простой пример, может кому-то будет проще,
DECLARE @TB1 TABLE
(
No Int
,Name NVarchar(50)
)
DECLARE @TB2 TABLE
(
No Int
,Name NVarchar(50)
)
INSERT INTO @TB1 VALUES(1,'asdf');
INSERT INTO @TB1 VALUES(2,'awerq');
INSERT INTO @TB2 VALUES(1,';oiup');
INSERT INTO @TB2 VALUES(2,'lkjhj');
SELECT * FROM @TB1
UPDATE @TB1 SET Name =S.Name
FROM @TB1 T
INNER JOIN @TB2 S
ON S.No = T.No
SELECT * FROM @TB1
обновить в той же таблице:
DECLARE @TB1 TABLE
(
No Int
,Name NVarchar(50)
,linkNo int
)
DECLARE @TB2 TABLE
(
No Int
,Name NVarchar(50)
,linkNo int
)
INSERT INTO @TB1 VALUES(1,'changed person data', 0);
INSERT INTO @TB1 VALUES(2,'old linked data of person', 1);
INSERT INTO @TB2 SELECT * FROM @TB1 WHERE linkNo = 0
SELECT * FROM @TB1
SELECT * FROM @TB2
UPDATE @TB1
SET Name = T2.Name
FROM @TB1 T1
INNER JOIN @TB2 T2 ON T2.No = T1.linkNo
SELECT * FROM @TB1
Для PostgreSQL:
UPDATE Sales_Import SI
SET AccountNumber = RAN.AccountNumber
FROM RetrieveAccountNumber RAN
WHERE RAN.LeadID = SI.LeadID;
Ошибка, которую я делаю: SET SI.AccountNumber = RAN.AccountNumber. Тем не менее, мне интересно, почему это не так в postgresql? Кто-нибудь может объяснить?
Это позволит вам обновить таблицу на основе значения столбца, не найденного в другой таблице.
UPDATE table1 SET table1.column = 'some_new_val' WHERE table1.id IN (
SELECT *
FROM (
SELECT table1.id
FROM table1
LEFT JOIN table2 ON ( table2.column = table1.column )
WHERE table1.column = 'some_expected_val'
AND table12.column IS NULL
) AS Xalias
)
Это обновит таблицу на основе значения столбца, найденного в обеих таблицах.
UPDATE table1 SET table1.column = 'some_new_val' WHERE table1.id IN (
SELECT *
FROM (
SELECT table1.id
FROM table1
JOIN table2 ON ( table2.column = table1.column )
WHERE table1.column = 'some_expected_val'
) AS Xalias
)
он работает с postgresql
UPDATE application
SET omts_received_date = (
SELECT
date_created
FROM
application_history
WHERE
application.id = application_history.application_id
AND application_history.application_status_id = 8
);
Приведенный ниже SQL, предложенный кем-то, НЕ работает в SQL Server. Этот синтаксис напоминает мне мой старый школьный класс:
UPDATE table2
SET table2.col1 = table1.col1,
table2.col2 = table1.col2,
...
FROM table1, table2
WHERE table1.memberid = table2.memberid
Все остальные запросы с использованием NOT IN или NOT EXISTS не рекомендуются. Появляются NULL, потому что OP сравнивает весь набор данных с меньшим подмножеством, тогда, конечно, возникнет проблема сопоставления. Это должно быть исправлено путем написания правильного SQL с правильным JOIN вместо проблемы уклонения с помощью NOT IN. В этом случае вы можете столкнуться с другими проблемами, используя NOT IN или NOT EXISTS.
Я голосую за верхний, который является обычным способом обновления таблицы на основе другой таблицы путем присоединения к SQL Server. Как я уже сказал, вы не можете использовать две таблицы в одном операторе UPDATE в SQL Server, если сначала не соедините их.
Могу только сказать, что в SQL Server 2017 это работает отлично. Просто на заметку для будущих людей. Не нужно к ним присоединяться.
Общий ответ для будущих разработчиков.
UPDATE
t1
SET
t1.column = t2.column
FROM
Table1 t1
INNER JOIN Table2 t2
ON t1.id = t2.id;
UPDATE
t1
SET
t1.colmun = t2.column
FROM
Table1 t1,
Table2 t2
WHERE
t1.ID = t2.ID;
UPDATE
Table1 t1,
Table2 t2
SET
t1.column = t2.column
WHERE
t1.ID = t2.ID;
Следует отметить, по крайней мере для SQL Server, используйте псевдоним, а не имя таблицы в верхнем предложении обновления (update t1..., а не update Table1...)
попробуй это :
UPDATE
Table_A
SET
Table_A.AccountNumber = Table_B.AccountNumber ,
FROM
dbo.Sales_Import AS Table_A
INNER JOIN dbo.RetrieveAccountNumber AS Table_B
ON Table_A.LeadID = Table_B.LeadID
WHERE
Table_A.LeadID = Table_B.LeadID
Хочу добавить еще одну вещь.
Не обновляйте значение с тем же значением, это приведет к дополнительному ведению журнала и ненужным накладным расходам. См. Пример ниже - он выполнит обновление только для 2 записей, несмотря на ссылку на 3.
DROP TABLE #TMP1
DROP TABLE #TMP2
CREATE TABLE #TMP1(LeadID Int,AccountNumber NVarchar(50))
CREATE TABLE #TMP2(LeadID Int,AccountNumber NVarchar(50))
INSERT INTO #TMP1 VALUES
(147,'5807811235')
,(150,'5807811326')
,(185,'7006100100007267039');
INSERT INTO #TMP2 VALUES
(147,'7006100100007266957')
,(150,'7006100100007267039')
,(185,'7006100100007267039');
UPDATE A
SET A.AccountNumber = B.AccountNumber
FROM
#TMP1 A
INNER JOIN #TMP2 B
ON
A.LeadID = B.LeadID
WHERE
A.AccountNumber <> B.AccountNumber --DON'T OVERWRITE A VALUE WITH THE SAME VALUE
SELECT * FROM #TMP1
Используйте следующий блок запроса для обновления Table1 с помощью Table2 на основе идентификатора:
UPDATE Sales_Import, RetrieveAccountNumber
SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber
where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;
Это Самый простой способ для решения этой проблемы.
Если приведенные выше ответы не работают для вас, попробуйте это
Update Sales_Import A left join RetrieveAccountNumber B on A.LeadID = B.LeadID
Set A.AccountNumber = B.AccountNumber
where A.LeadID = B.LeadID
Вот что у меня сработало в SQL Server:
UPDATE [AspNetUsers] SET
[AspNetUsers].[OrganizationId] = [UserProfile].[OrganizationId],
[AspNetUsers].[Name] = [UserProfile].[Name]
FROM [AspNetUsers], [UserProfile]
WHERE [AspNetUsers].[Id] = [UserProfile].[Id];
Oracle 11g
merge into Sales_Import
using RetrieveAccountNumber
on (Sales_Import.LeadId = RetrieveAccountNumber.LeadId)
when matched then update set Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber;
MS Sql
UPDATE c4 SET Price=cp.Price*p.FactorRate FROM TableNamea_A c4
inner join TableNamea_B p on c4.Calcid=p.calcid
inner join TableNamea_A cp on c4.Calcid=cp.calcid
WHERE c4..Name='MyName';
Oracle 11g
MERGE INTO TableNamea_A u
using
(
SELECT c4.TableName_A_ID,(cp.Price*p.FactorRate) as CalcTot
FROM TableNamea_A c4
inner join TableNamea_B p on c4.Calcid=p.calcid
inner join TableNamea_A cp on c4.Calcid=cp.calcid
WHERE p.Name='MyName'
) rt
on (u.TableNamea_A_ID=rt.TableNamea_B_ID)
WHEN MATCHED THEN
Update set Price=CalcTot ;
Если таблицы находятся в разных базах данных. (MSSQL)
update database1..Ciudad
set CiudadDistrito=c2.CiudadDistrito
FROM database1..Ciudad c1
inner join
database2..Ciudad c2 on c2.CiudadID=c1.CiudadID
обновление из одной таблицы в другую таблицу по совпадению идентификатора
UPDATE
TABLE1 t1,
TABLE2 t2
SET
t1.column_name = t2.column_name
WHERE
t1.id = t2.id;
MYSQL (это мой предпочтительный способ восстановления значений reasonId столбца все на основе эквивалентности первичного ключа id)
UPDATE `site` AS destination
INNER JOIN `site_copy` AS backupOnTuesday
ON backupOnTuesday.`id` = destination.`id`
SET destdestination.`reasonId` = backupOnTuesday.`reasonId`
Это самый простой и лучший вариант для Mysql и Maria DB.
UPDATE table2, table1 SET table2.by_department = table1.department WHERE table1.id = table2.by_id
Примечание. Если вы столкнулись со следующей ошибкой, связанной с версией Mysql / Maria DB. Код ошибки: 1175. Вы используете безопасный режим обновления и пытались обновить таблицу без WHERE, в которой используется столбец KEY. Чтобы отключить безопасный режим, переключите вариант в настройках "
Затем запустите такой код
SET SQL_SAFE_UPDATES=0;
UPDATE table2, table1 SET table2.by_department = table1.department WHERE table1.id = table2.by_id
Возможно, вы захотите использовать псевдоним таблицы в предложении UPDATE, иначе это вызовет проблемы, если вы сами присоединитесь к таблице в любой момент.