Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Perbarui semua kecuali satu catatan duplikat dalam tabel di SQL Server

Anda dapat memecahkan masalah ini tanpa bergabung, yang berarti harus memiliki kinerja yang lebih baik. Idenya adalah untuk mengelompokkan data berdasarkan object_id Anda, menghitung nomor baris dari setiap object_id. Inilah yang dilakukan "partisi oleh". Kemudian Anda dapat memperbarui di mana row_num> 1. Ini akan memperbarui semua objek_id yang digandakan kecuali yang pertama!

update t set t.status_val = 'some_status' 
from (
    select *, row_number() over(partition by object_id order by (select null)) row_num  
    from foo
) t 
where row_num > 1 

Pada tabel pengujian yang terdiri dari 82944 catatan, kinerjanya seperti itu (jarak tempuh Anda mungkin berbeda!):Tabel 'tes'. Hitungan pemindaian 5, pembacaan logis 82283, pembacaan fisik 0, pembacaan ke depan 0, pembacaan logika lob 0, pembacaan fisik lob 0, pembacaan depan pembacaan lob 0.CPU time =141 md, waktu berlalu =150 md.

Kami juga dapat memecahkan masalah ini dengan menggunakan gabungan dalam, namun, secara umum ini akan menghasilkan pembacaan yang lebih logis dan CPU yang lebih tinggi:

Tabel 'tes'. Hitungan pindai 10, pembacaan logis 83622, pembacaan fisik 0, pembacaan depan membaca 0, pembacaan logika lob 0, pembacaan fisik lob 0, pembacaan depan pembacaan lob 0.Tabel 'Workfile'. Hitungan pemindaian 0, pembacaan logis 0, pembacaan fisik 0, pembacaan ke depan 0, pembacaan logika lob 0, pembacaan fisik lob 0, pembacaan ke depan lob membaca 0.Tabel 'Meja Kerja'. Hitungan pemindaian 4, pembacaan logis 167426, pembacaan fisik 0, pembacaan ke depan 0, pembacaan logika lob 0, pembacaan fisik lob 0, pembacaan ke depan lob membaca waktu 0.CPU =342 md, waktu yang berlalu =233 md.

Untuk mengulang hasil dan memperbarui dalam batch yang lebih kecil:

declare @rowcount int = 1;
declare @batch_size int = 1000;

while @rowcount > 0 
begin
    update top(@batch_size) t set t.status_val = 'already updated'
    from (
        select *, row_number() over(partition by object_id order by (select null)) row_num  
        from foo
        where status_val <> 'already updated' 
    ) t 
    where row_num > 1 
    set @rowcount = @@rowcount;
end

Ini akan membantu tetap mengunci jika sesi bersamaan lainnya mencoba mengakses tabel ini.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Apakah MS SQL Server antara menyertakan batas jangkauan?

  2. Dapatkan ID Objek dari Namanya di SQL Server:OBJECT_ID()

  3. ADO.Net SQLCommand.ExecuteReader() melambat atau hang

  4. Bagaimana cara menggunakan variabel tabel dalam pernyataan sql dinamis?

  5. Cara mengambil nama bidang dari tabel sementara (SQL Server 2008)