SQL Server'da JOIN ile bir UPDATE deyimi nasıl yapabilirim?


1314

SQL Server'da bu tabloyu 'üst' tablosundan verilerle güncellemem gerekiyor , aşağıya bakın:

Tablo: satış

id (int)
udid (int)
assid (int)

Tablo: ud

id  (int)
assid  (int)

sale.assidgüncellenecek doğru değeri içeriyor ud.assid.

Hangi sorgu bunu yapacak? Ben düşünüyorum joinama bunun mümkün olup olmadığından emin değilim.


3
Hangi RDBMS'yi kullanıyorsunuz? MySQL, SQL Server, Oracle, PostgreSQL veya başka bir şey?
Chris J

tablolar arasındaki bazı ilişkiler? Satıştan hangi kaydın ud'dan hangi kayda karşılık geldiğini nasıl bilebiliriz? Her iki tabloda da birincil anahtar olarak kimliğe dayalı mı?
Cătălin Pitiș

UD'yi nasıl güncelleyebilirsiniz? Sadece yardımcısı var ve kendi kimliği var. Varolan gerçek değerler ve komut dosyası sonucunda değiştirilmesini veya eklenmesini istediğiniz kayıtlar hakkında bir örnek verebilir misiniz?
Bernhard Hofmann


Yanıtlar:


2383

Sözdizimi kesinlikle hangi SQL DBMS'yi kullandığınıza bağlıdır. ANSI / ISO (aka herhangi bir SQL DBMS üzerinde çalışması gerekir), MySQL, SQL Server ve Oracle bunu yapmanın bazı yolları. Önerilen ANSI / ISO yöntemimin genellikle diğer iki yöntemden çok daha yavaş olacağına dikkat edin, ancak MySQL, SQL Server veya Oracle dışında bir SQL DBMS kullanıyorsanız, o zaman gitmek için tek yol olabilir (örn. SQL DBMS'niz desteklemiyorsa MERGE):

ANSI / ISO:

update ud 
     set assid = (
          select sale.assid 
          from sale 
          where sale.udid = ud.id
     )
 where exists (
      select * 
      from sale 
      where sale.udid = ud.id
 );

MySQL:

update ud u
inner join sale s on
    u.id = s.udid
set u.assid = s.assid

SQL Server:

update u
set u.assid = s.assid
from ud u
    inner join sale s on
        u.id = s.udid

PostgreSQL:

update ud
  set assid = s.assid
from sale s 
where ud.id = s.udid;

Hedef tablonun FROMPostgres yan tümcesinde tekrarlanmaması gerektiğini unutmayın .

Oracle:

update
    (select
        u.assid as new_assid,
        s.assid as old_assid
    from ud u
        inner join sale s on
            u.id = s.udid) up
set up.new_assid = up.old_assid

SQLite:

update ud 
     set assid = (
          select sale.assid 
          from sale 
          where sale.udid = ud.id
     )
 where RowID in (
      select RowID 
      from ud 
      where sale.udid = ud.id
 );

3
Bana öyle geliyor ki MySQL set assid = s.assidolmalı set u.assid = s.assid.
dotancohen

2
ANSI sözdiziminde, SELECT'ten sonra SELECT =birden fazla satır döndürürse ne olur ?
Deplasman Hesabı

2
@ ThrowawayAccount3Million Büyük olasılıkla başarısız olur. AFAIK, bu tür bir işlem skaler bir değer bekler ve bunun yerine bir sonuç kümesi verilirse bir hata atar.
Francis Lord

6
Ben OP onun tablo ve sütunlar için bazı daha iyi isimler seçmek isterdim !! böyle okunabilir / sezgisel değil ...
S.Serpooshan

4
Postgre 9.3, yalnızcaupdate ud set assid = s.assid
StackUnder

143

Bu SQL Server'da çalışmalıdır:

update ud 
set assid = sale.assid
from sale
where sale.udid = id

98

postgres

UPDATE table1
SET    COLUMN = value
FROM   table2,
       table3
WHERE  table1.column_id = table2.id
       AND table1.column_id = table3.id
       AND table1.COLUMN = value
       AND table2.COLUMN = value
       AND table3.COLUMN = value 

20
Soruda kullanılan tablo / sütun adlarını kullanırsa cevap daha kullanışlı olacaktır. Cevabınızda neden 3 tablo var?
alfonx

50

Standart bir SQL yaklaşımı

UPDATE ud
SET assid = (SELECT assid FROM sale s WHERE ud.id=s.id)

SQL Server'da bir birleştirme kullanabilirsiniz

UPDATE ud
SET assid = s.assid
FROM ud u
JOIN sale s ON u.id=s.id

1
Birincisi ile 2'den fazla sütunla eşleşemezsiniz, ancak katılmak harika çalışır.
makciook

6
@makciook: ha? WHEREEk sütunlarla eşleşmek istiyorsanız , maddeye daha fazla koşul ekleyebilirsiniz .
siride

2
Sadece bir nit ... ama bence OP sale.udid = ud.id demekti. Ve satış değil. İd.
Skippy VonDrake

39

PostgreSQL :

CREATE TABLE ud (id integer, assid integer);
CREATE TABLE sales (id integer, udid integer, assid integer);

UPDATE ud
SET assid = sales.assid
FROM sales
WHERE sales.id = ud.id;

26

Birden çok tablo JOIN kullanarak basitleştirilmiş güncelleştirme sorgusu .

   UPDATE
        first_table ft
        JOIN second_table st ON st.some_id = ft.some_id
        JOIN third_table tt  ON tt.some_id = st.some_id
        .....
    SET
        ft.some_column = some_value
    WHERE ft.some_column = 123456 AND st.some_column = 123456

Not - first_table, second_table, third_table ve 123456 gibi some_column, demo tablosu adları, sütun adları ve kimliklerdir. Bunları geçerli adlarla değiştirin.


16

SQL'in neden taşınabilir olmadığını gösteren başka bir örnek.

MySQL için:

update ud, sale
set ud.assid = sale.assid
where sale.udid = ud.id;

Daha fazla bilgi için çoklu tablo güncellemesini okuyun: http://dev.mysql.com/doc/refman/5.0/en/update.html

UPDATE [LOW_PRIORITY] [IGNORE] table_references
    SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...
    [WHERE where_condition]

2
"SQL neden taşınabilir değil" yorumunda +1! Taşınabilirlik o kadar kırılgandır ki, sadece bir değişken bildirmek, popüler veritabanı motorlarının çoğu arasında taşınabilirliği bozacaktır.
Jeff Moden

8

Teradata Aster, hedefe nasıl ulaşılacağı konusunda başka ilginç bir yol sunuyor:

MERGE INTO ud --what trable should be updated
USING sale -- from what table/relation update info should be taken
ON ud.id = sale.udid --join condition
WHEN MATCHED THEN 
    UPDATE SET ud.assid = sale.assid; -- how to update

8

Her ikisi de T-SQL ama ne yazık ki değil çünkü üst yazı SQL-Server bir Sybase için işe yarayacağını düşünüyordum.

Sybase için güncellemenin takma ad değil, tablo üzerinde olması gerektiğini buldum:

update ud
set u.assid = s.assid
from ud u
    inner join sale s on
        u.id = s.udid

7

FROM anahtar sözcüğüyle aşağıdaki ifade, bir birleştirmeyle birden çok satırı güncellemek için kullanılır

UPDATE users 
set users.DivisionId=divisions.DivisionId
from divisions join users on divisions.Name=users.Division

7

MySQL

Where yan tümcesini unutursanız ve tüm koşulları ON ifadesine yerleştirirseniz en iyi performansı elde edersiniz.

Bence sorgu ilk tablolara katılmak zorunda sonra nerede bu maddeyi çalıştırır, bu yüzden katılmak için gerekenleri azaltabilir sonra sonuç almak / udpate yapmak için oruçlu yolu olduğunu düşünüyorum çünkü.

Misal

senaryo

Bir kullanıcı tablonuz var. Kullanıcı adlarını veya e-postalarını veya hesap_numaralarını kullanarak giriş yapabilirler. Bu hesaplar etkin (1) veya etkin değil (0) olabilir. Bu tabloda 50000 satır var

Daha sonra, bir kerede devre dışı bırakacak bir kullanıcı tablonuz var, çünkü hepsinin kötü bir şey yaptığını öğrendiniz. Ancak bu tabloda kullanıcı adları, e-postalar ve hesap numaralarının karıştırıldığı bir sütun vardır. Ayrıca, çalıştırıldığında 1 (true) olarak ayarlanması gereken bir "has_run" göstergesine de sahiptir.

Sorgu

UPDATE users User
    INNER JOIN
        blacklist_users BlacklistUser
        ON
        (
            User.username = BlacklistUser.account_ref
            OR
            User.email = BlacklistedUser.account_ref
            OR
            User.phone_number = BlacklistUser.account_ref
            AND
            User.is_active = 1
            AND
            BlacklistUser.has_run = 0
        )
    SET
        User.is_active = 0,
        BlacklistUser.has_run = 1;

muhakeme

Sadece OR koşullarına katılmak zorunda kalsaydık, birleştirilip birleştirilmeyeceğini görmek için her satırı 4 kez kontrol etmeliyiz ve potansiyel olarak çok daha fazla satır döndürmeliyiz. Bununla birlikte, daha fazla koşul vererek, katılırken tüm koşulları karşılamazlarsa çok sayıda satırı "atlayabilir".

Bonus

Daha okunabilir. Tüm koşullar tek bir yerde ve güncellenecek satırlar tek bir yerde


4

Ve MS ERİŞİMİNDE:

UPDATE ud 
INNER JOIN sale ON ud.id = sale.udid
SET ud.assid = sale.assid;

1
Dikkatli olarak SET, kayıt kümesi tanımından hemen sonra gelmelidir! Ben sadece bir WHERE yan tümcesi (geçerli bir ON koşulu olarak kabul etmeyecek) gerekli bir Access veritabanında benzer bir senaryo çalışmaya çalışıyorum. Sözdizimi hatalarını önlemek için NEREYE son gelmek zorunda kaldı.
Dodecaphone


3
UPDATE tblAppraisalBasicData
SET tblAppraisalBasicData.ISCbo=1
FROM tblAppraisalBasicData SI INNER JOIN  aaa_test RAN ON SI.EmpID = RAN.ID

3

Bunu dene, bence bu senin için işe yarayacak

update ud

set ud.assid = sale.assid

from ud 

Inner join sale on ud.id = sale.udid

where sale.udid is not null

2

SQLite için güncellemeyi yapmak üzere RowID özelliğini kullanın:

update Table set column = 'NewValue'
where RowID = 
(select t1.RowID from Table t1
join Table2 t2 on t1.JoinField = t2.JoinField
where t2.SelectValue = 'FooMyBarPlease');

1
Bunu biraz açıklayabilir misiniz?
Mohammed Noureldin

1
@MohammedNoureldin Açıklamaya çalışacağım. Sorun, bir tabloyu aynı tabloyu kullanarak bir birleştirme üzerindeki bir sorgudan sonuç ile güncelleştirme. (Sub-select) ifadesi birleştirme gibi davranır ve tablodaki her satır için benzersiz bir sayı olan RowID sistem alanını döndürür. Alt seçim birden çok satır döndürebildiğinden, "burada RowID =" sonuçta elde edilen alt seçimden tek bir doğru satır seçer ve sütuna güncelleme yapar. Daha fazla açıklamaya ihtiyacınız varsa veya bu tema üzerinde bir varyasyon bulmanız gerekiyorsa bana bildirin.
KeithTheBiped
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.