Обновление SQL из одной таблицы в другую на основе совпадения идентификатора

У меня есть база данных с 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.

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1 005
0
1 967 805
25

Ответы 25

Я считаю, что UPDATE FROM с JOIN поможет:

MS SQL

UPDATE
    Sales_Import
SET
    Sales_Import.AccountNumber = RAN.AccountNumber
FROM
    Sales_Import SI
INNER JOIN
    RetrieveAccountNumber RAN
ON 
    SI.LeadID = RAN.LeadID;

MySQL и MariaDB

UPDATE
    Sales_Import SI,
    RetrieveAccountNumber RAN
SET
    SI.AccountNumber = RAN.AccountNumber
WHERE
    SI.LeadID = RAN.LeadID;

Возможно, вы захотите использовать псевдоним таблицы в предложении UPDATE, иначе это вызовет проблемы, если вы сами присоединитесь к таблице в любой момент.

Tom H 23.10.2008 00:38

В предложении set вы должны изменить SI.AccountNumber на просто AccountNumber, иначе он выйдет из строя.

AaronLS 27.04.2010 21:52

MS-Access использует другое UPDATE с оператором JOIN. Посмотрите: sql-und-xml.de/sql-tutorial/…

Christian Ammer 22.07.2010 16:56

Вы не можете использовать псевдоним таблицы в предложении обновления. Однако я обновил образец, чтобы напрямую ссылаться на обновленную таблицу.

Mark S. Rasmussen 30.08.2011 16:39

кажется, это нормально для mssql, но, похоже, не работает в mysql. Хотя, похоже, это работает: UPDATE Sales_Import, RetrieveAccountNumber SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;. Немного не по теме, но может быть полезно

Edd 22.02.2012 19:10

Думаю, во внутреннем соединении нет необходимости. Решение Vonki, приведенное ниже, работает: UPDATE [Sales_Lead]. [Dbo]. [Sales_Import] SET [AccountNumber] = RetrieveAccountNumber.AccountNumber FROM RetrieveAccountNumber WHERE [Sales_Lead]. [Dbo]. [Sales_Import] .LeadID = RetrieveLeadIDNumber].

Gutti 29.11.2013 20:08

@Gutti По крайней мере, в простых случаях план объяснения тот же: сканирование таблиц -> совпадение хэша -> сортировка -> обновление

Stephen Lloyd 03.07.2014 19:50

@Edd: Я добавил ваше решение MySQL в ответ.

Mr. Polywhirl 23.03.2016 18:22

@ MarkS.Rasmussen Фактически вы можете использовать псевдоним как в предложениях update, так и в set. "обновить псевдоним установить alias.column = alias2.column из таблицы1 как псевдоним, присоединиться к таблице2 как псевдоним2 ..." работает.

DCShannon 19.10.2016 21:42

Вы также можете использовать JOIN в MySQL UPDATE Sales_Import JOIN RetrieveAccountNumber ON Sales_Import.LeadID = RetrieveAccountNumber.LeadID SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber

Jugali Lakota 09.11.2016 19:26

Это работает лучше, чем ответ ниже, поскольку INNER JOIN решает ошибку «необходимо объявить скалярную переменную» при использовании определенного пользователем типа таблицы в качестве параметра для хранимой процедуры.

Luke Alderton 13.12.2016 18:59

Набор должен находиться под соединением на

Keutelvocht 08.03.2018 17:55

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

user734028 22.08.2019 10:57

Это просто спасло мне день! Спасибо.

MrrMan 03.09.2019 12:43

Кажется, вы используете 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)  

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

Tom H 23.10.2008 00:40

Замечание об этом решении, UPDATE ... FROM является проприетарным, поэтому, если вы не можете использовать оператор MERGE, потому что вы используете SQL 2005 или более раннюю версию, это ANSI-совместимый метод выполнения обновлений с источником таблицы в MSSQL. Источник: sqlblog.com/blogs/hugo_kornelis/archive/2008/03/10/…

pseudocoder 18.09.2012 00:18

единственное решение, которое работает для меня, потому что это стандартный оператор обновления SQL (UPDATE SET WHERE), большое спасибо

Basheer AL-MOMANI 09.07.2018 10:47

У меня была такая же проблема с 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)

Почему требуется ГДЕ СУЩЕСТВУЕТ?

Georg Schölly 07.09.2010 19:31

Поскольку каждая строка в foo, не имеющая соответствия в bar, оказалась нулевой, потому что оператор select произвел null. Надеюсь, это было яснее, чем моя первая попытка объяснить это.

Kjell Andreassen 07.01.2011 20:43

отметьте этот ответ ниже stackoverflow.com/questions/224732/…

Basheer AL-MOMANI 09.07.2018 22:56

@KjellAndreassen Вы решили мою проблему. Спасибо за ваш код.

Bhavin Thummar 13.02.2019 14:51

Простой способ скопировать содержимое из одной таблицы в другую:

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

Sirentec 24.10.2016 18:25

Это не сработало, но ОБНОВЛЕНИЕ table2, table1 SET table2.col1 = table1.col1, ... WHERE table1.memberid = table2.memberid (mysql и phpmyadmin)

Tom Kuschel 02.02.2017 15:56

Для 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.

Tony Ashworth 12.10.2012 19:13

+1 для отчета о реализации MERGE SQL Server

AFract 06.12.2013 13:37

Большое спасибо, Мартин! Я искал это с тех пор, как много дней, наконец, заработал :)

InfantPro'Aravind' 29.04.2014 17:07

MERGE - это здорово, но стоит отметить, что он не будет работать, если вы используете связанный сервер The target of a MERGE statement cannot be a remote table, a remote view, or a view over remote tables..

Charles Clayton 17.06.2015 19:26

Аргументы в пользу использования MERGE (включая те, что указаны в сообщение с sqlblog.com, ссылка на которые приведена выше) могут быть убедительными, но нужно учитывать, что согласно MSDN: ... Оператор MERGE работает лучше всего, когда две таблицы имеют сложную смесь совпадающих характеристик ... При простом обновлении одной таблицы на основе строк другой таблицы улучшенная производительность и масштабируемость могут быть достигнуты с помощью базовых операторов INSERT, UPDATE и DELETE.

Tony Pulokas 27.10.2016 19:20

Я понимаю, что сейчас он устарел, но связанный пост Бертрана говорит: «Однако изначально MERGE поставлялся с несколькими «неверными результатами» и другими ошибками ... некоторые из которых продолжают существовать даже в ранних предварительных версиях SQL Server 2014 ... Я рекомендовал, чтобы - пока - люди придерживались своих проверенных и верных методов отдельных утверждений.» (эмф мой) См. Также его комментарий к January 26, 2014 - 8:28:58 PM. @MartinSmith - Есть ли основания подозревать, что сейчас дела обстоят лучше?

ruffin 08.11.2017 18:02

FWIW не работает с Access, поставляемым с MS Office 365 Pro Plus.

jkp1187 22.12.2017 22:17

@ jkp1187 Этот вопрос помечен тегом SQL Server. Так что RE: FWIW - примерно ноль.

Martin Smith 24.12.2017 14:29

@MartinSmith Для людей с ограниченным опытом, которые попали на эту страницу благодаря результатам поисковой системы, это ненулевое значение.

jkp1187 11.05.2018 20:55

Для 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? Кто-нибудь может объяснить?

Karan Arora 08.07.2020 22:34

Это позволит вам обновить таблицу на основе значения столбца, не найденного в другой таблице.

    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 это работает отлично. Просто на заметку для будущих людей. Не нужно к ним присоединяться.

SharpShade 14.11.2018 18:35

Общий ответ для будущих разработчиков.

SQL Server

UPDATE 
     t1
SET 
     t1.column = t2.column
FROM 
     Table1 t1 
     INNER JOIN Table2 t2 
     ON t1.id = t2.id;

Oracle (и SQL Server)

UPDATE 
     t1
SET 
     t1.colmun = t2.column 
FROM 
     Table1 t1, 
     Table2 t2 
WHERE 
     t1.ID = t2.ID;

MySQL

UPDATE 
     Table1 t1, 
     Table2 t2
SET 
     t1.column = t2.column 
WHERE
     t1.ID = t2.ID;

Следует отметить, по крайней мере для SQL Server, используйте псевдоним, а не имя таблицы в верхнем предложении обновления (update t1..., а не update Table1...)

gordon 25.04.2017 18:58

попробуй это :

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

Другие вопросы по теме