IDの一致に基づく、あるテーブルから別のテーブルへのSQL更新


929

私はデータベースを持っています account numbersありcard numbersます。これらをファイルとupdateアカウント番号のカード番号と照合し、アカウント番号のみを使用するようにします。

テーブルをアカウント/カードデータベースにリンクするビューを作成して、 Table IDと関連するアカウント番号。次に、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 FROMJOINます:

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句でテーブルエイリアスを使用することもできます。そうしないと、テーブルを任意の時点で自己結合すると問題が発生します。
トムH

15
set句では、変更SI.AccountNumberAccountNumberないと失敗します。
AaronLS 2010

1
MS-Accessは、JOINステートメントで異なるUPDATEを使用します。見ている:sql-und-xml.de/sql-tutorial/...を
クリスチャンAmmer

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 [Sales_Lead] RetrieveAccountNumber FROM [DBO] [Sales_Import] .LeadID =
Gutti

289

あるテーブルから別のテーブルにコンテンツをコピーする簡単な方法は次のとおりです。

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

条件を追加して、特定のデータをコピーすることもできます。


2
この作品は、しかし、あなたはUPDATE FROM table2のセットtable2.col1 = table1.col1、table2.col2 = table1.col2にtable2のを必要としない、... FROM TABLE1 WHERE table1.memberid = table2.memberid
Sirentec

2
これは機能しませんでしたが、UPDATE table2、table1 SET table2.col1 = table1.col1、... WHERE table1.memberid = table2.memberid(mysql and phpmyadmin)
Tom Kuschel

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;

残念ながら、どちらを使用するかの選択は、純粋に優先されるスタイルに限定されない場合があります。MERGESQL Serverでのの実装は、さまざまなバグに悩まされてきました。Aaron Bertrandは報告されたもののリストをここにまとめました。


11
に向かいMERGEます。
Jakub Januszkiewicz

2
私はマージ構文を知りませんでした。Update + Joinよりもはるかにクリーンです。
トニーアシュワース

MERGE SQL Serverの実装のレポートのための+1
AFract

1
(を含めMERGE使用するための引数sqlblog.comからポストの上にリンク)は、説得力のあるかもしれませんが、考慮すべき一つのことはあるかもしれないことをMSDNによると2つのテーブルの複雑な混合物を持っている場合... MERGE文は最高の作品特性の一致...別のテーブルの行に基づいて1つのテーブルを単純に更新する場合、基本的なINSERT、UPDATE、およびDELETEステートメントでパフォーマンスとスケーラビリティを改善できます
Tony Pulokas

1
@ jkp1187この質問にはSQL Serverのタグが付けられています。RE:FWIW-ほぼゼロ。
マーティン・スミス

104

将来の開発者のための一般的な答え。

SQLサーバー

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設定すると、同じ問題が発生しました。私はOracleでこのようなことをしました:nullfoobar

fooを更新
set foo.new =(select bar.new
                  バーから 
                  ここで、foo.key = bar.key)
存在する場所(1つ選択)
              バーから
              ここで、foo.key = bar.key)

4
なぜWHERE EXISTSが必要なのですか?
GeorgSchölly10年

6
selectステートメントがnullを生成したため、barに一致しないfooの各行がnullになったためです。これが私の最初の説明よりも明確だったことを願っています。
Kjell Andreassen

以下、この答えをチェックstackoverflow.com/questions/224732/...
バシールAL-MOMANI

@KjellAndreassenあなたは私の問題を解決しました。コードをありがとう。
Bhavin Thummar

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
ここのコードが機能するかどうかにかかわらず、投稿された他の2つのソリューションを確認する必要があります。それらははるかに明確で、エラーが発生しにくく、ほぼ確実に高速です。
トムH

3
このソリューションについての注記、UPDATE ... FROMは独自仕様であるため、SQL 2005以前を使用しているためにMERGEステートメントを使用できない場合、これはMSSQLのテーブルソースで更新を実行するANSI準拠の方法です。出典:sqlblog.com/blogs/hugo_kornelis/archive/2008/03/10/...
pseudocoder

1
標準のSQL更新ステートメント(UPDATE SET WHERE)のため、私にとって唯一有効なソリューションです。ありがとう
ございます

13

テーブルが別のデータベースにある場合。(MSSQL)

update database1..Ciudad
set CiudadDistrito=c2.CiudadDistrito

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

10

次のクエリブロックを使用して、IDに基づいて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 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は推奨されません。OPはデータセット全体を小さいサブセットと比較するため、NULLが表示されますが、当然ながらマッチングの問題があります。これはJOIN、を使用して問題を回避するのではなく、適切なSQLを正しく記述して修正する必要がありますNOT INNOT INまたはを使用して他の問題に遭遇する可能性がありますNOT EXISTSこの場合、。

SQL Serverに参加して別のテーブルに基づいてテーブルを更新する従来の方法である、上位1つに対する私の投票。私が言ったように、UPDATE最初に結合しない限り、SQL Serverの同じステートメントで2つのテーブルを使用することはできません。


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

もう1つ追加したいのですが。

同じ値で値を更新しないでください。追加のロギングと不要なオーバーヘッドが発生します。以下の例を参照してください-3でリンクしているにもかかわらず、2つのレコードでのみ更新を実行します。

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 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.