MySQL'in SQL Server 2005 uygulaması INTO REPLACE?


87

MySQL, bu inanılmaz derecede kullanışlı ancak tescilli REPLACE INTOSQL Komutuna sahiptir.

Bu, SQL Server 2005'te kolayca taklit edilebilir mi?

Yeni İşlem başlayan bir yapıyor Select()ve sonra da UPDATEya INSERTve COMMITuygulamada bunu yapıyor ve bu nedenle her zaman ifadenin 2 sürümlerini tutmak, özellikle her zaman bir acı biraz.

Böyle bir işlevi SQL Server 2005'e uygulamanın kolay ve evrensel bir yolu olup olmadığını merak ediyorum.

Yanıtlar:


60

Bu beni MSSQL hakkında rahatsız eden bir şey ( blogumda rant ). MSSQL'in desteklenmesini diliyorum upsert.

@ Dillie-O'nun kodu, eski SQL sürümlerinde (+1 oy) iyi bir yoldur, ancak yine de temelde iki GÇ işlemidir ( existsve sonra updateveya insert)

Temel olarak bu yazıda biraz daha iyi bir yol var :

--try an update
update tablename 
set field1 = 'new value',
    field2 = 'different value',
    ...
where idfield = 7

--insert if failed
if @@rowcount = 0 and @@error = 0
    insert into tablename 
           ( idfield, field1, field2, ... )
    values ( 7, 'value one', 'another value', ... )

Bu, bir güncelleme ise bir IO işlemine veya bir insert ise ikiye indirir.

MS Sql2008 merge, SQL: 2003 standardını sunar:

merge tablename as target
using (values ('new value', 'different value'))
    as source (field1, field2)
    on target.idfield = 7
when matched then
    update
    set field1 = source.field1,
        field2 = source.field2,
        ...
when not matched then
    insert ( idfield, field1, field2, ... )
    values ( 7,  source.field1, source.field2, ... )

Şimdi gerçekten sadece bir GÇ işlemi, ancak korkunç kod :-(


Çok teşekkürler! Seçimi kaydeder ve Güncelle ve "benim" eki arasında bu anahtar için başka ek olmadığından emin olabildiğim durumlarda genellikle bir işlem yapılmasına bile ihtiyaç duymaz.
Michael Stum

2
@Michael Bu tabloda benzersiz bir dizine sahip olsanız ve bu çözümü kullanacaksanız yinelenen anahtar hatalarını işlemeniz iyi olur.
Sam Saffron

3
@Keith Birleştirme ifadeniz çalışmıyor. MERGEMaddeyi desteklemiyorsa WHERE, bunu USINGve kullanarak yeniden yazmanız gerekir ON. Ayrıca, eklemediğiniz sürece WITH (HOLDLOCK), bir yarış var ve eşzamanlı INSERTs gerçekleşebilir, bunlardan biri anahtar çatışması nedeniyle başarısız olabilir.
Evgeniy Berezovsky

Evet, burada belirtildiği gibi: weblogs.sqlteam.com/dang/archive/2009/01/31/… MERGE atomik değildir. Örtük bir güncelleme kilidi çıkarır, ancak bir ekleme gerçekleştirmeden önce onu serbest bırakır, bu da birincil anahtar ihlallerine neden olabilecek bir yarış durumuna neden olur. İşlemin atomik olması için örtük UPDLOCK'a ek olarak açık bir HOLDLOCK kullanmanız gerekir. Mevcut haliyle, tek bir ifade gibi görünmesine rağmen atomik değildir.
Triynko

1
MERGE sözdizimi yanlış ve aynı yazarın daha yeni bir cevabında düzeltildi: stackoverflow.com/a/243670/24472
Larry

21

Aradığınız işlevselliğe geleneksel olarak UPSERT denir. En azından ne dendiğini bilmek, aradığınızı bulmanıza yardımcı olabilir.

SQL Server 2005'in bunu yapmak için harika bir yolu olduğunu düşünmüyorum. 2008, http://www.databasejournal.com/features/mssql/article.php/3739131 veya http://blogs.conchango.com/davidportas/archive/ adresinde gösterildiği gibi bunu başarmak için kullanılabilecek MERGE ifadesini sunar. 2007/11/14 / SQL-Server-2008-MERGE.aspx

Birleştirme, 2005 beta sürümünde mevcuttu, ancak son sürümde onu kaldırdılar.


18

Yükseltme / birleştirme işleminin yaptığı şey ...

IF EXISTS (SELECT * FROM [Table] WHERE Id = X)
   UPDATE [Table] SET...
ELSE
   INSERT INTO [Table]

Umarım bu makalelerin ve sözde kodun birleşimi işleri harekete geçirebilir.


10

Bu konu hakkında bir blog yazısı yazdım .

Sonuç olarak, ucuz güncellemeler istiyorsanız ve eşzamanlı kullanım için güvenli olmak istiyorsanız, şunu deneyin:

update t
set hitCount = hitCount + 1
where pk = @id

if @@rowcount < 1 
begin 
   begin tran
      update t with (serializable)
      set hitCount = hitCount + 1
      where pk = @id
      if @@rowcount = 0
      begin
         insert t (pk, hitCount)
         values (@id,1)
      end
   commit tran
end

Bu şekilde, güncellemeler için 1 işleminiz ve ekler için maksimum 3 işleminiz olur. Yani, genel olarak güncelleme yapıyorsanız, bu güvenli ve ucuz bir seçenektir.

Eşzamanlı kullanım için güvenli olmayan herhangi bir şeyi kullanmamaya da çok dikkat ederim. Üretimde birincil anahtar ihlallerini veya yinelenen satırları almak gerçekten çok kolay.

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.