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


929

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

Ответы:


1369

Я верю 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;

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

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

1
MS-Access использует другое ОБНОВЛЕНИЕ с оператором JOIN. Взгляните на: sql-und-xml.de/sql-tutorial/…
Кристиан Аммер

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

7
Я думаю, что нет необходимости во внутреннем соединении. Vonki решение ниже работ: UPDATE [Sales_Lead] [DBO] [Sales_Import] SET [AccountNumber] = RetrieveAccountNumber.AccountNumber FROM RetrieveAccountNumber WHERE [Sales_Lead] [DBO] [Sales_Import] .LeadID = RetrieveAccountNumber.LeadID....
Gutti

289

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

UPDATE table2 
SET table2.col1 = table1.col1, 
table2.col2 = table1.col2,
...
FROM table1, table2 
WHERE table1.memberid = table2.memberid

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


2
Это работает, но вам не нужно table2 в ОБНОВЛЕНИИ ОТ ОБНОВЛЕНИЯ table2 SET table2.col1 = table1.col1, table2.col2 = table1.col2, ... ИЗ table1 WHERE table1.memberid = table2.memberid
Sirentec

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

156

Для 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 была связана с различными ошибками. Аарон Бертран составил список зарегистрированных здесь .


11
Направляется на MERGE.
Якуб Янушкевич

2
Я никогда не знал о синтаксисе слияния. Это намного чище, чем Update + Join.
Тони Эшворт

+1 за отчет о реализации
MERGE

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

1
@ jkp1187 Этот вопрос помечен SQL Server. Итак, RE: FWIW - примерно ноль.
Мартин Смит

104

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

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;

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

2
Версия Oracle не работает. Получение ORA-00933
ka3ak

35

Для PostgreSQL:

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

34

Кажется, вы используете MSSQL, тогда, если я правильно помню, это делается так:

UPDATE [Sales_Lead].[dbo].[Sales_Import] SET [AccountNumber] = 
RetrieveAccountNumber.AccountNumber 
FROM RetrieveAccountNumber 
WHERE [Sales_Lead].[dbo].[Sales_Import].LeadID = RetrieveAccountNumber.LeadID

33

У меня была такая же проблема с foo.newнастройкой nullдля строк, в fooкоторых не было соответствующего ключа bar. Я сделал что-то подобное в Oracle:

обновить фу
set foo.new = (выберите bar.new
                  из бара 
                  где foo.key = bar.key)
где существует (выберите 1
              из бара
              где foo.key = bar.key)

4
Почему ГДЕ СУЩЕСТВУЕТ ?
Георг Шолли

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

проверьте этот ответ ниже stackoverflow.com/questions/224732/…
Basheer AL-MOMANI

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

27

Для MySql, который работает нормально:

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

26

Вот что сработало для меня в SQL Server:

UPDATE [AspNetUsers] SET

[AspNetUsers].[OrganizationId] = [UserProfile].[OrganizationId],
[AspNetUsers].[Name] = [UserProfile].[Name]

FROM [AspNetUsers], [UserProfile]
WHERE [AspNetUsers].[Id] = [UserProfile].[Id];

18

Спасибо за ответы. Я нашел решение, хотя.

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)  

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

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

1
единственное решение, которое работает для меня, потому что это стандартная инструкция обновления SQL (UPDATE SET WHERE), большое спасибо
Basheer AL-MOMANI

13

В случае, если таблицы находятся в разных базах данных. (MSSQL)

update database1..Ciudad
set CiudadDistrito=c2.CiudadDistrito

FROM database1..Ciudad c1
 inner join 
  database2..Ciudad c2 on c2.CiudadID=c1.CiudadID

10

Используйте следующий блок запроса для обновления таблицы Table1 на основе идентификатора:

UPDATE Sales_Import, RetrieveAccountNumber 
SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber 
where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;

Это самый простой способ решения этой проблемы.


8

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  ;

3

обновить в той же таблице:

  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

3

Ниже 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, если сначала не присоединитесь к ним.


2
Я могу только сказать, что в SQL Server 2017 это работает на отлично. Так же, как записка для будущих людей. Нет необходимости присоединяться к ним.
SharpShade

3

это работает с 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
);

1

Я подумал, что это простой пример, может кому-то будет легче,

        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

0

Oracle 11g

merge into Sales_Import
using RetrieveAccountNumber
on (Sales_Import.LeadId = RetrieveAccountNumber.LeadId)
when matched then update set Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber;

-1

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

    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
    )

-1

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

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

Я хотел бы добавить еще одну вещь.

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

-3

Если приведенные выше ответы не работают, попробуйте это

Update Sales_Import A left join RetrieveAccountNumber B on A.LeadID = B.LeadID
Set A.AccountNumber = B.AccountNumber
where A.LeadID = B.LeadID 
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.