SQL ServerでSELECTから更新するにはどうすればよいですか?


3695

ではSQL Serverの、それはすることが可能であるINSERT使用してテーブルへのSELECT文を:

INSERT INTO Table (col1, col2, col3)
SELECT col1, col2, col3 
FROM other_table 
WHERE sql = 'cool'

を介して更新することもできSELECTますか?値を含む一時テーブルがあり、それらの値を使用して別のテーブルを更新したいと考えています。おそらくこのようなもの:

UPDATE Table SET col1, col2
SELECT col1, col2 
FROM other_table 
WHERE sql = 'cool'
WHERE Table.id = other_table.id

回答:


5372
UPDATE
    Table_A
SET
    Table_A.col1 = Table_B.col1,
    Table_A.col2 = Table_B.col2
FROM
    Some_Table AS Table_A
    INNER JOIN Other_Table AS Table_B
        ON Table_A.id = Table_B.id
WHERE
    Table_A.col3 = 'cool'

16
テーブル間のリンクを編集している場合(SET Table.other_table_id = @NewValue)、ONステートメントを次のように変更しますON Table.id = @IdToEdit AND other_table.id = @NewValue
Trisped

11
@RogerRay、この質問はMicrosoft SQL Serverに関するものです。残念ながら、さまざまなSQL実装間の構文は異なる場合があります。
Charles Wood

2
@CharlesWoodええ。MySQLでも同じ質問があります。誰かがそれをMySQLに実装し、みんなと共有する方法を知っているなら、それは素晴らしいことです。多くの人がMySQLバージョンのソリューションを探していると思います
Roger Ray

1
セットでエイリアスを使用するにはどうすればよいですか?テーブルセットa.col1 = b.col2をテーブルa内部結合table2 bからa.id = b.idに更新します。代わりに、更新テーブルセットtable.col1 = b.col2をテーブルa内部結合table2 bからa.id = b.idに使用する必要があります。
ThinkCode、2014年

11
多少関連がありますが、UPDATEクエリを最初にSELECTステートメントとして記述して、実行前に更新されるデータを確認できるようにすることがよくあります。Sebastianは最近のブログ投稿でこの手法を取り上げています:sqlity.net/en/2867/update-from-select
dennislloydjr '21

777

SQL Server 2008(またはそれ以上)では、 MERGE

MERGE INTO YourTable T
   USING other_table S 
      ON T.id = S.id
         AND S.tsql = 'cool'
WHEN MATCHED THEN
   UPDATE 
      SET col1 = S.col1, 
          col2 = S.col2;

または:

MERGE INTO YourTable T
   USING (
          SELECT id, col1, col2 
            FROM other_table 
           WHERE tsql = 'cool'
         ) S
      ON T.id = S.id
WHEN MATCHED THEN
   UPDATE 
      SET col1 = S.col1, 
          col2 = S.col2;

123
MERGE「Upserting」レコードにも使用できます。つまり、UPDATE一致するレコードが存在するINSERT場合、一致が見つからない場合は新しいレコード
brichins

16
これは、同等のupdate ... joinステートメントよりも約10倍高速でした。
Paul Suart 2013

17
MERGEはDELETEにも使用できます。ただし、TARGETテーブルをリモートテーブルにすることはできないため、MERGEには注意してください。
Möoz


16
@SimonD:SQL Serverキーワードを選択すると、バグが見つかります。あなたのポイント?私は、関連付けられたより多くのバグ(とあまりにももっと根本的なもの)がある賭けるUPDATEよりもMERGE、人々はちょうど彼らと一緒に暮らすことを学んだが、彼らは景観(「機能」)の一部となります。UPDATE新しい子供がブロックにいたとき、ブログは存在しなかったと考えてください。
2014年

673
UPDATE YourTable 
SET Col1 = OtherTable.Col1, 
    Col2 = OtherTable.Col2 
FROM (
    SELECT ID, Col1, Col2 
    FROM other_table) AS OtherTable
WHERE 
    OtherTable.ID = YourTable.ID

7
はるかに簡単です!ただし、内部SELECTからIDフィールドが欠落しています。WHERE句を機能させるには、これが必要になります
John Doherty

12
これは、ほぼすべてのDBMSで機能する傾向があります。つまり、一度学習すればどこでも実行できます。パフォーマンスよりもそれが重要である場合は、特に、一部のデータを修正するための更新が1回限りの場合は、この回答をお勧めします。
アランマクドナルド2016

2
最初のテーブルに2番目のテーブルの集計を設定する必要がある場合は、集計SET Table_A.col1 = SUM(Table_B.col1)(または他の集計関数)を実行できないので、selectサブクエリに集計を配置できます。このため、ロビンデーの回答よりも優れています。
Jason S

280

私は以下に対するロビンの優れた答えを修正します:

UPDATE Table
SET Table.col1 = other_table.col1,
 Table.col2 = other_table.col2
FROM
    Table
INNER JOIN other_table ON Table.id = other_table.id
WHERE
    Table.col1 != other_table.col1
OR Table.col2 != other_table.col2
OR (
    other_table.col1 IS NOT NULL
    AND Table.col1 IS NULL
)
OR (
    other_table.col2 IS NOT NULL
    AND Table.col2 IS NULL
)

WHERE句がないと、影響を受ける必要のない行にも影響を及ぼし、(おそらく)インデックスの再計算や、実際には起動されるべきではないトリガーが起動される可能性があります。


7
ただし、これは、どの列もnull入力可能ではないことを前提としています。
マーティン・スミス

4
あなたが正しい、私は手で例をタイプしていました。それを処理するために、whereステートメントに3番目と4番目の句を追加しました。
キルブレーカー、2011

46
WHERE EXISTS(SELECT T1.Col1, T1.Col2 EXCEPT SELECT T2.Col1, T2.Col2))より簡潔です。
マーティンスミス

5
ステートメントのwhere句にもこれら2つを含めないでください。(other_table.col1はnullであり、table.col1はnullではない)または(other_table.col2はnullであり、table.col2はnullでない)
Barka

4
宛先のヌルをソースのヌルで置き換えるかどうかに依存します。多くの場合、私はしません。しかし、もしそうなら、マーティンのwhere句の構成が最も適しています。
キルブレーカー、2013年

204

一方通行

UPDATE t 
SET t.col1 = o.col1, 
    t.col2 = o.col2
FROM 
    other_table o 
  JOIN 
    t ON t.id = o.id
WHERE 
    o.sql = 'cool'

165

まだ言及されていない別の可能性は、SELECTステートメント自体をCTEにチャックして、CTEを更新することです。

;WITH CTE
     AS (SELECT T1.Col1,
                T2.Col1 AS _Col1,
                T1.Col2,
                T2.Col2 AS _Col2
         FROM   T1
                JOIN T2
                  ON T1.id = T2.id
         /*Where clause added to exclude rows that are the same in both tables
           Handles NULL values correctly*/
         WHERE EXISTS(SELECT T1.Col1,
                             T1.Col2
                       EXCEPT
                       SELECT T2.Col1,
                              T2.Col2))
UPDATE CTE
SET    Col1 = _Col1,
       Col2 = _Col2

これには、SELECT最初にステートメントを実行して結果を正常性チェックするのが簡単であるという利点がありますが、ソーステーブルとターゲットテーブルで同じ名前が付けられている場合は、上記のように列にエイリアスを設定する必要があります。

これにUPDATE ... FROMは、他の4つの回答に示されている独自の構文と同じ制限があります。ソーステーブルが1対多の結合の多側にある場合、一致する可能性のある結合されたレコードのどれがで使用されるかは不確定ですUpdateMERGE更新しようとするとエラーが発生して回避される問題同じ行が複数回)。


3
名前の意味はCTE何ですか?
ラプター

19
@ShivanRaptor- 共通テーブル式の頭字語です。この場合は任意のエイリアスです。
マーティン・スミス

3
これは、複数のCTEとうまく動作します:;WITH SomeCompexCTE AS (...), CTEAsAbove AS (SELECT T1.Col1,... FROM T1 JOIN SomeComplexCTE...) UPDATE CTEAsAbove SET Col1=_Col1, ...
VeeTheSecond

117

レコード(および他の人が私と同じように検索)の場合、MySQLで次のように実行できます。

UPDATE first_table, second_table
SET first_table.color = second_table.color
WHERE first_table.id = second_table.foreign_id

最も簡単ですか?ありがとう...
MarcoZen

96

エイリアスを使用:

UPDATE t
   SET t.col1 = o.col1
  FROM table1 AS t
         INNER JOIN 
       table2 AS o 
         ON t.id = o.id

73

簡単な方法は次のとおりです。

UPDATE
    table_to_update,
    table_info
SET
    table_to_update.col1 = table_info.col1,
    table_to_update.col2 = table_info.col2

WHERE
    table_to_update.ID = table_info.ID

2
あなたのものはよりよくフォーマットされています。また、副選択を使用する場合、ユーザー(およびエイドリアン)は他の形式よりも確実に機能します。回答を投稿していただきありがとうございます。
ベンウェスト

20
これはSQL Server構文ではなく、SQLサーバーでは機能しません
HLGEM 2013

これはSQL Alchemyでうまく機能しました。たぶん、質問の内容は違うかもしれませんが、確かに私には役立ちました。:)
JGTaylor

61

これは、更新を実行するためのニッチな理由かもしれません(たとえば、主にプロシージャで使用される)、または他の人には明白かもしれませんが、結合を使用せずにupdate-selectステートメントを実行できることも明記する必要があります(更新しているテーブルに共通のフィールドはありません)。

update
    Table
set
    Table.example = a.value
from
    TableExample a
where
    Table.field = *key value* -- finds the row in Table 
    AND a.field = *key value* -- finds the row in TableExample a

59

次に、別の便利な構文を示します。

UPDATE suppliers
SET supplier_name = (SELECT customers.name
                     FROM customers
                     WHERE customers.customer_id = suppliers.supplier_id)
WHERE EXISTS (SELECT customers.name
              FROM customers
              WHERE customers.customer_id = suppliers.supplier_id);

「WHERE EXIST」を使用して、nullかどうかをチェックします。


52

これを追加するのは、更新を行う前に更新内容を確認できるように、簡単に記述できるようにするためです。

UPDATE Table 
SET  Table.col1 = other_table.col1,
     Table.col2 = other_table.col2 
--select Table.col1, other_table.col,Table.col2,other_table.col2, *   
FROM     Table 
INNER JOIN     other_table 
    ON     Table.id = other_table.id 

52

SQL Serverの代わりにMySQLを使用する場合、構文は次のとおりです。

UPDATE Table1
INNER JOIN Table2
ON Table1.id = Table2.id
SET Table1.col1 = Table2.col1,
    Table1.col2 = Table2.col2

50

SQLデータベースのINNER JOINを使用したSELECTからのUPDATE

この投稿に対する返信の数が多すぎて、投票数が最も多いので、ここでも提案を提示したいと思いました。質問は非常に興味深いですが、私は多くのフォーラムサイトで見て、スクリーンショットでINNER JOINを使用してソリューションを作成しました。

最初に、schoololdという名前のテーブルを作成し、その列名に関していくつかのレコードを挿入して実行しました。

次に、SELECTコマンドを実行して、挿入されたレコードを表示しました。

次に、schoolnewという名前の新しいテーブルを作成し、同様に上記のアクションを実行しました。

次に、挿入されたレコードを表示するには、SELECTコマンドを実行します。

ここで、3行目と4行目にいくつか変更を加えます。このアクションを完了するには、INNER JOINを指定してUPDATEコマンドを実行します。

変更を表示するには、SELECTコマンドを実行します。

あなたは、テーブルの第三及び第四のレコードをどのように見ることができますschoololdが簡単にテーブルに置き換えschoolnew INNERがUPDATE文でJOINを使用することによって。


43

また、テーブルをそれ自体と結合したい場合(あまり頻繁には発生しません):

update t1                    -- just reference table alias here
set t1.somevalue = t2.somevalue
from table1 t1               -- these rows will be the targets
inner join table1 t2         -- these rows will be used as source
on ..................        -- the join clause is whatever suits you

8
1しかし、あなたは、関連するエイリアス名などの使用している必要がありますtargett1sourcet1いうより(または同様に)コメントを。
Mark Hurd、2014年

42

次の例では、派生テーブル、FROM句の後のSELECTステートメントを使用して、さらに更新するために古い値と新しい値を返します。

UPDATE x
SET    x.col1 = x.newCol1,
       x.col2 = x.newCol2
FROM   (SELECT t.col1,
               t2.col1 AS newCol1,
               t.col2,
               t2.col2 AS newCol2
        FROM   [table] t
               JOIN other_table t2
                 ON t.ID = t2.ID) x

41

ここでの更新CTEは、他の回答よりも読みやすくなっています。

;WITH cte
     AS (SELECT col1,col2,id
         FROM   other_table
         WHERE  sql = 'cool')
UPDATE A
SET    A.col1 = B.col1,
       A.col2 = B.col2
FROM   table A
       INNER JOIN cte B
               ON A.id = B.id

39

SQL Serverを使用している場合は、結合を指定せずに1つのテーブルを別のテーブルから更新し、where句から2つをリンクするだけです。これにより、はるかに単純なSQLクエリが作成されます。

UPDATE Table1
SET Table1.col1 = Table2.col1,
    Table1.col2 = Table2.col2
FROM
    Table2
WHERE
    Table1.id = Table2.id

25

ここでさまざまなアプローチをすべて統合します。

  1. 更新を選択
  2. 共通テーブル式で更新する
  3. マージ

サンプルのテーブル構造は以下のとおりで、Product_BAKからProductテーブルに更新されます。

製品

CREATE TABLE [dbo].[Product](
    [Id] [int] IDENTITY(1, 1) NOT NULL,
    [Name] [nvarchar](100) NOT NULL,
    [Description] [nvarchar](100) NULL
) ON [PRIMARY]

Product_BAK

    CREATE TABLE [dbo].[Product_BAK](
        [Id] [int] IDENTITY(1, 1) NOT NULL,
        [Name] [nvarchar](100) NOT NULL,
        [Description] [nvarchar](100) NULL
    ) ON [PRIMARY]

1.更新を選択します

    update P1
    set Name = P2.Name
    from Product P1
    inner join Product_Bak P2 on p1.id = P2.id
    where p1.id = 2

2.共通のテーブル式で更新する

    ; With CTE as
    (
        select id, name from Product_Bak where id = 2
    )
    update P
    set Name = P2.name
    from  product P  inner join CTE P2 on P.id = P2.id
    where P2.id = 2

3.マージ

    Merge into product P1
    using Product_Bak P2 on P1.id = P2.id

    when matched then
    update set p1.[description] = p2.[description], p1.name = P2.Name;

このMergeステートメントでは、ターゲットで一致するレコードが見つからなくても、ソースには存在し、構文を見つければ挿入を行うことができます。

    Merge into product P1
    using Product_Bak P2 on P1.id = P2.id;

    when matched then
    update set p1.[description] = p2.[description], p1.name = P2.Name;

    WHEN NOT MATCHED THEN
    insert (name, description)
    values(p2.name, P2.description);

23

もう1つの方法は、派生テーブルを使用することです。

UPDATE t
SET t.col1 = a.col1
    ,t.col2 = a.col2
FROM (
SELECT id, col1, col2 FROM @tbl2) a
INNER JOIN @tbl1 t ON t.id = a.id

サンプルデータ

DECLARE @tbl1 TABLE (id INT, col1 VARCHAR(10), col2 VARCHAR(10))
DECLARE @tbl2 TABLE (id INT, col1 VARCHAR(10), col2 VARCHAR(10))

INSERT @tbl1 SELECT 1, 'a', 'b' UNION SELECT 2, 'b', 'c'

INSERT @tbl2 SELECT 1, '1', '2' UNION SELECT 2, '3', '4'

UPDATE t
SET t.col1 = a.col1
    ,t.col2 = a.col2
FROM (
SELECT id, col1, col2 FROM @tbl2) a
INNER JOIN @tbl1 t ON t.id = a.id

SELECT * FROM @tbl1
SELECT * FROM @tbl2

23
UPDATE TQ
SET TQ.IsProcessed = 1, TQ.TextName = 'bla bla bla'
FROM TableQueue TQ
INNER JOIN TableComment TC ON TC.ID = TQ.TCID
WHERE TQ.IsProcessed = 0

必要なものを更新していることを確認するには、最初に選択します

SELECT TQ.IsProcessed, 1 AS NewValue1, TQ.TextName, 'bla bla bla' AS NewValue2
FROM TableQueue TQ
INNER JOIN TableComment TC ON TC.ID = TQ.TCID
WHERE TQ.IsProcessed = 0

22

さらに短い方法があり、それはあなたにとって驚くべきことかもしれません:

サンプルデータセット:

CREATE TABLE #SOURCE ([ID] INT, [Desc] VARCHAR(10));
CREATE TABLE #DEST   ([ID] INT, [Desc] VARCHAR(10));

INSERT INTO #SOURCE VALUES(1,'Desc_1'), (2, 'Desc_2'), (3, 'Desc_3');
INSERT INTO #DEST   VALUES(1,'Desc_4'), (2, 'Desc_5'), (3, 'Desc_6');

コード:

UPDATE #DEST
SET #DEST.[Desc] = #SOURCE.[Desc]
FROM #SOURCE
WHERE #DEST.[ID] = #SOURCE.[ID];

1
YES-意図的なJOINはありません。NO-これはテーブル変数には適用できません。
Bartosz X 2017

1
#SOURCEで[_id]を#DESTINATIONと同じではなく[ID]で使用すると、JOINができるようになると思います。"on#DESTINATION.ID =#SOURCE._id。または、@ tblなどのテーブル変数を使用する場合" on PermTable.ID=@memorytbl._id "。 。
ジェナリーフ

2
これはSELECTからの更新と何が関係していますか?
マーティン・スミス

2
これは同じアイデアですが、別の方法です-updateステートメントでJOINとWHEREを達成するために「select」をまったく配置する必要はありません-これはSELECTを書かなくてもSELECTタイプのクエリです
Bartosz X

19

使用する:

drop table uno
drop table dos

create table uno
(
    uid int,
    col1 char(1),
    col2 char(2)
)
create table dos
(
    did int,
    col1 char(1),
    col2 char(2),
    [sql] char(4)
)
insert into uno(uid) values (1)
insert into uno(uid) values (2)
insert into dos values (1,'a','b',null)
insert into dos values (2,'c','d','cool')

select * from uno 
select * from dos

どちらか:

update uno set col1 = (select col1 from dos where uid = did and [sql]='cool'), 
col2 = (select col2 from dos where uid = did and [sql]='cool')

または:

update uno set col1=d.col1,col2=d.col2 from uno 
inner join dos d on uid=did where [sql]='cool'

select * from uno 
select * from dos

ID列名が両方のテーブルで同じ場合、更新するテーブルの前にテーブル名を置き、選択したテーブルのエイリアスを使用します。

update uno set col1 = (select col1 from dos d where uno.[id] = d.[id] and [sql]='cool'),
col2  = (select col2 from dos d where uno.[id] = d.[id] and [sql]='cool')

14

受け入れられた回答では、後に:

SET
Table_A.col1 = Table_B.col1,
Table_A.col2 = Table_B.col2

追加します:

OUTPUT deleted.*, inserted.*

私が通常行うことは、ロールバックされたトランザクションにすべてを入れて、"OUTPUT":を使用することです。自分が見たものに満足したら、をに変更ROLLBACKCOMMITます。

通常、何をしたかを文書化する必要があるため"results to Text"、ロールバックされたクエリを実行するときにこのオプションを使用し、スクリプトとOUTPUTの結果の両方を保存します。(もちろん、変更した行が多すぎる場合、これは実用的ではありません)



12

以下のソリューションは、MySQLデータベースで機能します。

UPDATE table1 a , table2 b 
SET a.columname = 'some value' 
WHERE b.columnname IS NULL ;

12

selectステートメントから更新するもう1つの方法:

UPDATE A
SET A.col = A.col,B.col1 = B.col1
FROM  first_Table AS A
INNER JOIN second_Table AS B  ON A.id = B.id WHERE A.col2 = 'cool'

5
selectステートメントから更新する別の方法他の回答との違いは何ですか?答えを詳しく説明してください。留意点:良い答えは、OPだけでなく、SOへの将来の訪問者にとっても、何が行われ、なぜそのように行われたのかを説明するものです。
B001ᛦ2016

この答えは低品質のレビューキューで判明しました。おそらくコードの説明を提供していないためです。このコードが質問に回答する場合は、回答にコードを説明するテキストを追加することを検討してください。このようにして、あなたはより多くの賛成票を獲得し、質問者が何か新しいことを学ぶのを助ける可能性がはるかに高くなります。
lmo 2016

8

オプション1:内部結合の使用:

UPDATE
    A
SET
    A.col1 = B.col1,
    A.col2 = B.col2
FROM
    Some_Table AS A
    INNER JOIN Other_Table AS B
        ON A.id = B.id
WHERE
    A.col3 = 'cool'

オプション2:共同関連のサブクエリ

UPDATE table 
SET Col1 = B.Col1, 
    Col2 = B.Col2 
FROM (
    SELECT ID, Col1, Col2 
    FROM other_table) B
WHERE 
    B.ID = table.ID

うまくいきましたか?まったく同じクエリを使用しましたが、内部結合を使用するとエラーが発生しました。エイリアスは解決できません。ただし、相互に関連するサブクエリは完全に機能しました。
Pratyush Raizada

@PratyushRaizadaどんなエラーが出た?
Santhana

正確なエラーログはありませんが、割り当ての前にエイリアスAが参照されていたため、エラーが発生しました。
Pratyush Raizada

相関
サブクエリ

3
UPDATE table1
SET column1 = (SELECT expression1
               FROM table2
               WHERE conditions)
[WHERE conditions];

1つのテーブルをSQL Serverの別のテーブルのデータで更新するときのUPDATEステートメントの構文


1

あなたはこれからSQLサーバーの更新に使用できます

UPDATE
    T1
SET
   T1.col1 = T2.col1,
   T1.col2 = T2.col2
FROM
   Table1 AS T1
INNER JOIN Table2 AS T2
    ON T1.id = T2.id
WHERE
    T1.col3 = 'cool'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.