sqlserver - update sql 結合 oracle




SQL ServerのSELECTからどのように更新するのですか? (20)

SQL Serverでは、 SELECT文を使用してテーブルにinsertすることがinsertます。

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

  1. 内部結合の使用

UPDATE A SET A.col1 = B.col1、A.col2 = B.col2 From Some_Table from内部結合Other_Table AS B ON A.id = B.id WHERE A.col3 = 'cool'

  1. Co関連のサブクエリ

UPDATEテーブルSET Col1 = B.Col1、Col2 = B.Col2 FROM(SELECT ID、Col1、Col2 FROM other_table)B WHERE B.ID = table.ID


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;

SQL Serverの代わりにMySQLを使用する場合、構文は次のようになります。

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

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

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

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

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

この投稿の返信が多すぎるので、最も重大な投票が行われているので、私はここでも私の提案を提供すると考えていました。 質問は非常に面白いですが、私は多くのフォーラムサイトで見てきましたが、スクリーンショット付きのINNER JOINを使用したソリューションを作成しました。

最初は、 教科書で名前を付けられたテーブルを作成し、列名に関してレコードをいくつか挿入して実行しました。

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

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

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

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

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

INNER JOINをUPDATEステートメントで使用して、テーブルスクールボールドの第3レコードと第4レコードが簡単にテーブルスクールニューに置き換えられた様子を確認できます。


これは、更新を実行するためのニッチな理由(例えば、主にプロシージャで使用される)、または他者には明らかかもしれませんが、joinを使用せずに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

これを行う簡単な方法は次のとおりです。

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

さまざまなアプローチをすべてここに集約します。

  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);

そして、あなた自身とテーブルに参加したい場合(あまり頻繁に起こることはありません):

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

まだ言及されていない別の可能性は、 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ステートメントを独自に実行するのは簡単ですが、ソーステーブルとターゲットテーブルで同じ名前が付けられている場合は、上記のように別名を付ける必要があります。

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


もう1つの便利な構文があります:

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かどうかをチェックします。


エイリアスの使用:

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

レコード(と私がそうであったように他のものを検索する)のために、あなたはこのようにMySQLでそれを行うことができます:

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

以下のソリューションはMySQLデータベースで動作します:

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

受け入れられた答えでは、

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

私は追加します:

OUTPUT deleted.*, inserted.*

私が通常やっているのは、ロールバックされたトランザクションと"OUTPUT"を使ってすべてを実行することです。このようにして、起こりそうなことがすべて見えます。 私が見るものに満足したら、 ROLLBACKCOMMITに変更しROLLBACK

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


私はRobinの優れた答えを次のように変更します。

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句がなければ、影響を受ける必要のない行であっても、実際には起動してはならないインデックスの再計算や起動トリガーが発生する可能性があります。


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'

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

UPDATE table AS a
INNER JOIN table2 AS b
ON a.col1 = b.col1
INNER JOIN ... AS ...
ON ... = ...
SET ...
WHERE ...




select