Bagaimana cara menghapus 1000 baris teratas dari tabel menggunakan Sql Server 2008?

108

Saya memiliki tabel di SQL Server. Saya ingin menghapus 1000 baris teratas darinya. Namun, saya mencoba ini, tetapi saya alih-alih hanya menghapus 1000 baris teratas, itu menghapus semua baris dalam tabel.

Ini kodenya:

delete from [mytab] 
select top 1000 
a1,a2,a3
from [mytab]
edgarmtze.dll
sumber
8
Anda memerlukan ORDER BY untuk membuat TOP bermakna: lihat jawaban @Martin Smith yang merupakan satu - satunya dari lima yang memiliki ini. Terkadang saya putus asa
gbn
2
Apakah Anda ingin menghapus setiap 1000 baris? Hanya dipilih secara acak? Atau, misalnya, 1000 baris terlama?
Nick Chammas
13
Anda menghapus semua tabel karena delete from [mytab]satu pernyataan, dan select top ...yang lainnya.
Nick Chammas
2
Anda tidak perlu memesan atas, tergantung mengapa Anda melakukan TOP. Jika Anda perlu menghapus 10 juta baris dan memiliki 1 GB ruang log yang tersedia, gunakan Hapus TOP (10000) Dari dbo.myTable (dengan klausa yang Anda pilih) dan terus jalankan hingga tidak ada lagi baris untuk dihapus. Siapa yang peduli jika itu sewenang-wenang. Pengurutan hanya memperlambat kueri.
terpal
1
Saya menyadari bahwa ini adalah pertanyaan kuno (dalam tahun-tahun SO) tetapi menurut saya penting bagi orang-orang untuk mempertimbangkan komentar @gbn . Meskipun komentarnya tidak berlaku untuk situasi yang saya berikan (mencoba menghapus blok catatan tanpa menyebabkan masalah KUNCI tetapi tidak terlalu peduli tentang urutan penghapusannya), komentar tersebut kemungkinan besar berlaku untuk situasi ANDA. Pastikan Anda mempertimbangkannya sebelum menggunakan jawaban di bawah ini secara membabi buta yang tidak menyertakan klausul ORDER BY.
Andrew Steitz

Jawaban:

196

Kode yang Anda coba sebenarnya adalah dua pernyataan. A DELETEdiikuti oleh a SELECT.

Anda tidak mendefinisikan TOP seperti yang diperintahkan oleh apa.

Untuk kriteria pengurutan tertentu, menghapus dari CTE atau ekspresi tabel serupa adalah cara yang paling efisien.

;WITH CTE AS
(
SELECT TOP 1000 *
FROM [mytab]
ORDER BY a1
)
DELETE FROM CTE
Martin Smith
sumber
13
Bagi mereka yang bertanya-tanya mengapa Anda tidak dapat melakukannya DELETE TOP (1000) FROM table ORDER BY column, baca ini : "Baris yang direferensikan dalam ekspresi TOP yang digunakan dengan INSERT, UPDATE, MERGE, atau DELETE tidak diatur dalam urutan apa pun."
Nick Chammas
3
@Yaelah Bukan 2000. Dimungkinkan untuk menggunakan tabel turunan pada tahun 2000. Saya belum memiliki contoh untuk diuji.
Martin Smith
2
Saya telah melakukan cara yang sedikit berbeda (meskipun menurut saya CTE mungkin lebih bagus untuk dilihat): HAPUS T1 DARI (PILIH TOP 1000 * DARI [MYTAB] ORDER BY A1) T1;
Abacus
4
@ Liam - hanya karena jika ada pernyataan sebelumnya sebelum CTE, ini perlu diakhiri dengan titik koma sehingga menambahkannya ke depan WITHmencegah keluhan dari orang-orang yang belum melakukannya.
Martin Smith
86

Mungkin lebih baik untuk sql2005 + untuk digunakan:

DELETE TOP (1000)
FROM [MyTab]
WHERE YourConditions

Untuk Sql2000:

DELETE FROM [MyTab]
WHERE YourIdField IN 
(
  SELECT TOP 1000 
    YourIdField 
  FROM [MyTab]
  WHERE YourConditions
)

TAPI

Jika Anda ingin menghapus tertentu subset baris bukan bagian sewenang-wenang, Anda harus secara eksplisit menentukan untuk subquery:

DELETE FROM [MyTab]
WHERE YourIdField IN 
(
  SELECT TOP 1000 
    YourIdField 
  FROM [MyTab]
  WHERE YourConditions
  ORDER BY ExplicitSortOrder
)

Terima kasih tp @gbn karena telah menyebutkan dan menuntut jawaban yang lebih jelas dan tepat.

Oleg Dok
sumber
3
@gbn Mungkin tidak berguna bagi Anda, tetapi tetap itulah pertanyaan yang diajukan.
Joachim Isaksson
1
@ Joachim Isaksson: pergi dan baca tentang TOP lalu kembali lagi. Tidak ada hal seperti TOP tanpa ORDER BY dalam set. Atau, pergi dan temukan saya referensi kanonik yang membuktikan saya salah ... Untuk menyelamatkan Anda dari pencarian, sqlblog.com/blogs/alexander_kuznetsov/archive/2009/05/20/… dan blogs.technet.com/b/wardpond/archive /
2007/07/19
1
@gbn Tidak ada ketentuan tentang baris MANA yang akan dihapus, jadi ORDER BY di subkueri tidak berguna
Oleg Dok
1
@gbn Apakah Anda menyebutkan WHERE di subquery - Saya memfilter 1000 baris arbitrer di dalam kriteria yang dipilih dan kemudian menghapusnya. Skenario yang valid? Iya. Jika saya menambahkan ORDER BY NEWID () atau apa pun yang tidak mengubah apa pun - saya masih menghapus 1000 baris yang difilter berdasarkan kriteria yang dipilih
Oleg Dok
8
@gbn Jika Anda mencari penggunaan yang valid dari TOP tanpa ORDER BY: yang membawa saya ke sini adalah saya perlu menghapus semua baris yang cocok dengan beberapa kriteria, tetapi karena alasan kinerja, saya tidak ingin menghapus lebih dari 10.000 baris pada suatu waktu. Saya tidak peduli baris mana yang dihapusnya, karena saya akan menjalankan perintah lagi pada beberapa interval sampai semua baris tersebut hilang.
Richiban
6
delete from [mytab]
where [mytab].primarykeyid in
(
select top 1000 primarykeyid
from [mytab]
)
Jason Dam
sumber
4
Useless: TOP without an ORDER BY memberikan baris arbitrer
gbn
4
@gbn Mungkin tidak berguna bagi Anda, tetapi tetap itulah pertanyaan yang diajukan.
Joachim Isaksson
3
@gbn Saya tidak mengklaim bahwa ada jenis urutan default atau bahwa kueri tersebut berguna sama sekali, saya hanya mengingatkan Anda bahwa pertanyaan tersebut tidak meminta, jadi apa saran Anda untuk memesan?
Joachim Isaksson
2
@gbn Saya tidak tahu mengapa Anda begitu memusuhi semua orang karena sesuatu yang merupakan titik awal. Saya tidak mengklaim bahwa jawaban saya adalah akhir dari segalanya, itu hanyalah saran untuk membantu seseorang. Saya pikir pentingnya adalah kunci yang kembali dari sub query di sini.
Jason Dam
2
Mungkin hanya ini yang dicari penanya. Saya hanya akan menambahkan catatan untuk orang lain yang membaca untuk menekankan bahwa baris yang dihapus oleh pernyataan seperti itu tidak dijamin akan berurutan.
Nick Chammas
3
SET ROWCOUNT 1000;

DELETE FROM [MyTable] WHERE .....
Joe Bourne
sumber
2
Ketika berurusan dengan hanya 1000 baris, apakah itu penting ?? Jika itu 100.000.000 baris maka poin Anda mungkin valid, tetapi untuk hanya 1000 baris, ini adalah solusi paling sederhana yang diusulkan sejauh ini untuk SQL 2008.
Joe Bourne
1

Cepat. Cobalah:

DELETE FROM YourTABLE
FROM (SELECT TOP XX PK FROM YourTABLE) tbl
WHERE YourTABLE.PK = tbl.PK

Ganti YourTABLEdengan nama tabel, XXdengan angka, misalnya 1000, pkadalah nama bidang kunci utama tabel Anda.

Hamed elahi
sumber
Anda secara efektif membuat dua tabel dari satu, lalu menghapus tempat bergabung. Ini berfungsi dengan baik saat Anda ingin menghapus rekaman terlama (atau terbaru) dari tabel, karena Anda bisa mengurutkan mereka naik terlebih dahulu. T-sql ini diterima oleh Microsoft (dan cepat).
Tequila