Оновлення 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

Відповіді:


1368

Я вірю, 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
У встановленому пункті ви повинні змінити 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;. Трохи поза темою, але може бути корисною
Едд

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 у таблиці ВІД ОНОВЛЕННЯ2 SET SET2.2.l1 = table1.col1, table2.col2 = table1.col2, ... З таблиці1, звідки 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 SQL Server
AFract

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

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...)
gordon

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:

оновити foo
встановити foo.new = (виберіть bar.new
                  з бару 
                  де foo.key = bar.key)
де існує (виберіть 1
              з бару
              де foo.key = bar.key)

4
Чому потрібні ДЕ Є ?
Георг Шоллі

6
Оскільки кожен рядок у foo, що не має відповідності у рядку, закінчувався нульовим, оскільки оператор select став нульовим. Сподіваюся, це було зрозуміліше, ніж моя перша спроба пояснити це.
Kjell Andreassen

перевірити цю відповідь нижче stackoverflow.com/questions/224732 / ...
Башир 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 (ОНОВЛЮВАННЯ
ДЕЙСТВІ

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 з Table2 на основі ідентифікатора:

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 11г

        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не рекомендуються. NULLs з'являються, оскільки 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 11г

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.