Come eliminare le prime 1000 righe da una tabella utilizzando Sql Server 2008?


108

Ho una tabella in SQL Server. Vorrei eliminare le prime 1000 righe da esso. Tuttavia, ho provato questo, ma invece di eliminare solo le prime 1000 righe, ho eliminato tutte le righe nella tabella.

Ecco il codice:

delete from [mytab] 
select top 1000 
a1,a2,a3
from [mytab]

8
Hai bisogno di un ORDER BY per rendere TOP significativo: vedi la risposta di @Martin Smith che è l' unica di cinque ad avere questo. A volte mi dispero
gbn

2
Vuoi eliminare eventuali 1000 righe? Solo selezionati casualmente? O, ad esempio, le prime 1000 righe più vecchie?
Nick Chammas

13
Hai cancellato tutta la tabella perché delete from [mytab]è un'istruzione ed select top ...è un'altra.
Nick Chammas

2
Non hai bisogno di ordinare per il top, dipende dal motivo per cui stai facendo TOP. Se è necessario rimuovere 10 milioni di righe e si dispone di 1 GB di spazio di registro disponibile, utilizzare Elimina TOP (10000) da dbo.myTable (con la clausola select) e continuare a eseguirlo finché non ci sono più righe da eliminare. Chi se ne frega se è arbitrario. L'ordinamento rallenta solo la query.
tvanharp

1
Mi rendo conto che questa è una domanda antica (negli anni SO) ma penso che sia importante che le persone considerino i commenti di @gbn . Sebbene i suoi commenti non si applichino alla mia situazione specifica (cercando di eliminare blocchi di record senza causare problemi di BLOCCO ma non preoccuparsi davvero dell'ordine in cui vengono eliminati), potrebbero molto probabilmente applicarsi alla TUA situazione. Assicurati di considerarli prima di utilizzare ciecamente le risposte seguenti che non includono una clausola ORDER BY.
Andrew Steitz

Risposte:


196

Il codice che hai provato è in realtà due dichiarazioni. A DELETEseguito da a SELECT.

Non definisci TOPcome ordinato da cosa.

Per uno specifico criterio di ordinamento, l'eliminazione da un'espressione di tabella CTE o simile è il modo più efficiente.

;WITH CTE AS
(
SELECT TOP 1000 *
FROM [mytab]
ORDER BY a1
)
DELETE FROM CTE

13
Per coloro che si chiedono perché non puoi farlo DELETE TOP (1000) FROM table ORDER BY column, leggi questo : "Le righe a cui si fa riferimento nell'espressione TOP utilizzata con INSERT, UPDATE, MERGE o DELETE non sono disposte in alcun ordine."
Nick Chammas

3
@Magnus yes. Non nel 2000 però. Potrebbe essere possibile utilizzare una tabella derivata nel 2000. Non ho un'istanza in giro con cui testare.
Martin Smith


2
Avevo fatto un modo leggermente diverso (anche se penso che il CTE potrebbe essere più bello da guardare): DELETE T1 FROM (SELECT TOP 1000 * FROM [MYTAB] ORDER BY A1) T1;
Abaco

4
@Liam - solo perché se c'è una dichiarazione precedente prima del CTE, questa deve essere terminata con un punto e virgola, quindi aggiungerla all'inizio delle WITHlamentele anticipate da parte di persone che non l'hanno fatto.
Martin Smith

86

Potrebbe essere meglio per sql2005 + usare:

DELETE TOP (1000)
FROM [MyTab]
WHERE YourConditions

Per Sql2000:

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

MA

Se desideri eliminare un sottoinsieme specifico di righe invece di un sottoinsieme arbitrario, devi specificare esplicitamente l'ordine per la sottoquery:

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

Grazie a @gbn per aver menzionato e richiesto la risposta più chiara ed esatta.


3
@gbn Forse è inutile per te, ma è esattamente quello che chiede la domanda.
Joachim Isaksson

1
@ Joachim Isaksson: vai a leggere su TOP e poi torna. Non esiste TOP senza ORDER BY nei set. In alternativa, vai a trovarmi un riferimento canonico che dimostri che mi sbaglio ... Per risparmiare la ricerca, sqlblog.com/blogs/alexander_kuznetsov/archive/2009/05/20/… e blogs.technet.com/b/wardpond/archive /
2007/07/19

1
@gbn Nessuna condizione su QUALI righe eliminare, quindi ORDER BY nella sottoquery è inutile
Oleg Dok

1
@gbn Hai menzionato WHERE nella sottoquery: filtro 1000 righe arbitrarie all'interno dei criteri scelti e poi elimino. Scenario valido? Sì. Se aggiungo ORDER BY NEWID () o qualsiasi altra cosa non cambia nulla, elimino comunque 1000 righe filtrate in base ai criteri scelti
Oleg Dok

8
@gbn Nel caso tu stia cercando un uso valido di TOP senza ORDER BY: ciò che mi ha portato qui è che devo eliminare tutte le righe che corrispondono ad alcuni criteri ma, per motivi di prestazioni, non voglio che cancelli più di 10.000 righe Al tempo. Non mi interessa quali righe cancella, poiché eseguirò di nuovo il comando a un certo intervallo fino a quando tutte queste righe non saranno sparite.
Richiban


6
delete from [mytab]
where [mytab].primarykeyid in
(
select top 1000 primarykeyid
from [mytab]
)

4
Inutile: TOP senza ORDER BY fornisce righe arbitrarie
gbn

4
@gbn Forse è inutile per te, ma è esattamente quello che chiede la domanda.
Joachim Isaksson

3
@gbn Non ho affermato che ci sia un ordinamento predefinito o che la query sia anche in qualche modo utile, ti ho solo ricordato che la domanda non ne chiedeva uno, quindi su cosa suggeriresti di ordinare?
Joachim Isaksson

2
@gbn Non so perché sei così ostile a tutti per qualcosa che è un punto di partenza. Non pretendo che la mia risposta sia la fine di tutto, è solo un suggerimento per aiutare qualcuno. Penso che l'importanza siano le chiavi che stanno tornando dalla sottoquery qui.
Jason Dam

2
Questo potrebbe essere tutto ciò che il richiedente sta cercando. Vorrei solo aggiungere una nota per gli altri che leggono per sottolineare che non è garantito che le righe eliminate da tale istruzione siano in qualsiasi ordine.
Nick Chammas

3
SET ROWCOUNT 1000;

DELETE FROM [MyTable] WHERE .....

2
Quando si ha a che fare con solo 1000 righe, è davvero importante? Se fossero 100.000.000 di righe, i tuoi punti potrebbero essere validi, ma per sole 1000 righe, questa è di gran lunga la soluzione più semplice proposta finora per SQL 2008.
Joe Bourne

1

È veloce. Provalo:

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

Sostituire YourTABLE con il nome della tabella, XXcon un numero, ad esempio 1000, pkè il nome del campo della chiave primaria della tabella.


Stai effettivamente creando due tabelle da una e quindi cancellando dove unite. Funziona bene quando si desidera eliminare i record più vecchi (o più recenti) da una tabella, poiché è possibile ordinarli per primi in ordine crescente. Questo t-sql è accettato da Microsoft (ed è veloce).
Tequila
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.