Löschen Sie den 'ersten' Datensatz aus einer Tabelle in SQL Server ohne eine WHERE-Bedingung


73

Ist es möglich, den 'ersten' Datensatz aus einer Tabelle zu löschen SQL Server, ohne eine WHEREBedingung zu verwenden und ohne einen Cursor zu verwenden?


Möchten Sie Ihre Anforderungen qualifizieren?
CJK

@Quassnoi: SQL Server gemäß Titel.
Stanislav Kniazev

14
Werden wir ernsthaft hier sitzen und darüber streiten, wie mehrdeutig SQL Server ist? Ich denke, die Terminologie der wichtigsten RDBMS ist seit einiger Zeit Standard (SQL Server, MySQL, Postgres, Oracle, SQLite usw.) und es ist nicht so verwirrend.
TheTXI

6
FoxPro nicht vergessen! Es ist eine Datenbank. Ein sehr pelziger.
belgariontheking

2
@TheTXI Zum Zeitpunkt meines Beitrags war kein solches Tag vorhanden. Es wurde später von einer anderen Person hinzugefügt (siehe Bearbeitungsprotokoll). Und ohne es ich tun es mehrdeutige finden , und ich tun diese Leute wie ärgerlich die denken , Microsoft die einzige Software - Entwickler in der Welt;)
soulmerge

Antworten:


145
WITH  q AS
        (
        SELECT TOP 1 *
        FROM    mytable
        /* You may want to add ORDER BY here */
        )
DELETE
FROM    q

Beachten Sie, dass

DELETE TOP (1)
FROM   mytable

wird auch funktionieren, aber wie in der Dokumentation angegeben :

Die Zeilen, auf die in dem TOPAusdruck verwiesen wird, der mit oder verwendet INSERTwird UPDATE, DELETEsind in keiner Reihenfolge angeordnet.

Daher ist es besser, WITHeine ORDER BYKlausel zu verwenden, mit der Sie genauer angeben können, welche Zeile Sie als erste betrachten.


2
Beachten Sie, dass bei Verwendung WITHin Ausdruck die vorherige SQL-Anweisung mit einem Semikolon (;) beendet werden sollte
Alexander

Die Verwendung ORDER BY 1würde eine subtile Verbesserung der Tabellen vieler Benutzer in SQL Server bieten: Sie würden die Zeile mit dem niedrigsten Primärschlüsselwert erhalten, wahrscheinlich die erste Zeile. (Richtig, einige Tabellen haben nicht die PK als erste Spalte, aber es 1ist meine Lieblingsverknüpfung und ich wollte sie teilen.)
Magnus Smith

@MagnusSmith: Verbesserung gegenüber was?
Quassnoi

Es war nur ein kleiner Punkt. Ihre Antwort enthielt keine spezifische ORDER BY-Klausel, und mir wurde klar, dass das Originalposter nach der 'ersten' Zeile gefragt hatte, obwohl es anscheinend nicht möglich war, einen Spaltennamen anzugeben. Das brachte mich dazu, darüber nachzudenken 1.
Magnus Smith

@MagnusSmith: ah ok, obwohl es immer besser ist, die angegebene Spalte explizit anzugeben.
Quassnoi

43

hängt von Ihrem DBMS ab (die Leute scheinen nicht zu wissen, was das heutzutage ist)

-- MYSql:
DELETE FROM table LIMIT 1;
-- Postgres:
DELETE FROM table LIMIT 1;
-- MSSql:
DELETE TOP(1) FROM table;
-- Oracle:
DELETE FROM table WHERE ROWNUM = 1;

Oracle verstößt gegen die Einschränkung "ohne ... wo" (was auch immer der Zweck dieser Einschränkung ist).
Stanislav Kniazev

6

Nein, AFAIK, es ist nicht möglich, es portabel zu machen.

Es gibt sowieso keinen definierten "ersten" Datensatz - auf verschiedenen SQL-Engines ist es durchaus möglich, dass " SELECT * FROM table" die Ergebnisse jedes Mal in einer anderen Reihenfolge zurückgibt.


3

"Zuerst" definieren? Wenn die Tabelle eine PK hat, wird sie danach sortiert, und Sie können danach löschen:

DECLARE @TABLE TABLE
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Data NVARCHAR(50) NOT NULL
)

INSERT INTO @TABLE(Data)
SELECT 'Hello' UNION
SELECT 'World' 

SET ROWCOUNT 1
DELETE FROM @TABLE
SET ROWCOUNT 0

SELECT * FROM @TABLE

Wenn der Tisch keine PK hat, kann die Bestellung nicht garantiert werden ...


Was ist, wenn ich einen Clustered-Index habe, der nicht mit meiner PK identisch ist?
Tag, wenn

Ah natürlich, mein schlechtes - Dann wird es durch die erste Zeile im Clustered-Index sein, da das die Zeilen physisch ordnet, nicht die PK. Entschuldigung für die Verwirrung.
Meff

Selbst dann ist es nicht garantiert, dass es das "erste" ist, das vom Clustered-Index geordnet wird. SQL Server übernimmt hierfür keine Garantie.
Damien_The_Unbeliever


Ich mag diese PPT, vielen Dank. LOL bei "NoLock ist ein cooler Hinweis" - Ich habe an einem Ort gearbeitet, der das glaubte und nichts anderes akzeptieren würde. Ich ging weg.
Meff

1

Ist das wirklich sinnvoll?
Es gibt keinen "ersten" Datensatz in einer relationalen Datenbank. Sie können nur einen zufälligen Datensatz löschen.


1
Es ist sinnvoll, wenn Sie "order by" einmischen. Frage erwähnt nicht, nicht "order by" zu verwenden, nur nicht "where" und Cursor
dance2die

Nur wenn Sie nach einer eindeutigen Spalte bestellen. Wenn es nicht eindeutig ist, wissen Sie immer noch nicht genau, welchen Datensatz Sie löschen.
Christian Specht

1

Was meinst du mit «'erste' Aufzeichnung von einer Tabelle»? Ich denke, es gibt kein Konzept wie "First Record" in einer relationalen Datenbank.

Wenn Sie unter MS SQL Server 2005 beabsichtigen, den "Top-Datensatz" zu löschen (den ersten, der angezeigt wird, wenn Sie ein einfaches "* select * from tablename *" ausführen), können Sie " delete top (1) from tablename " verwenden. ... aber beachten Sie, dass dies nicht sicherstellt, welche Zeile aus dem Recordset gelöscht wird, da nur die erste Zeile entfernt wird, die angezeigt wird, wenn Sie den Befehl " select top (1) from tablename " ausführen .


Welche Zeile zuerst angezeigt wird, kann jedoch zwischen der Ausführung dieser Auswahl und der Ausführung des nachfolgenden Löschvorgangs variieren. Es gibt keine Garantie für Bestellungen ohne eine Bestellung per Klausel.
Damien_The_Unbeliever

Ja, du hast Recht. Ich glaube, ich habe das in meinem Beitrag unterstrichen. Der "Top-Rekord" kann variieren. Vielen Dank für Ihre Antwort, da mein Englisch nicht das beste ist und ich in meiner Antwort möglicherweise nicht klar war.
XpiritO

0

Ähnlich wie bei der ausgewählten Antwort kann eine Tabellenquelle verwendet werden, in diesem Fall eine abgeleitete Abfrage:

delete from dd
from (
    select top 1 *
    from my_table
) dd

Fühlen Sie sich frei, Bestellungen und Bedingungen hinzuzufügen.

Für das nächste Beispiel gehe ich davon aus, dass die Einschränkung für 'wo' darauf zurückzuführen ist, dass eine Zeile nicht anhand ihrer Werte ausgewählt werden soll. Angenommen, wir möchten eine Zeile basierend auf der Position löschen (in diesem Fall die erste Position):

delete from dd
from (
    select
        *,
        row = row_number() over (order by (select 1))
    from my_table
) dd
where row = 1

Beachten Sie, dass (Auswahl 1) die Sortierreihenfolge festlegt, in der sich die Tabellen oder Indizes befinden. Sie können diese durch eine neue ID ersetzen, um ziemlich zufällige Zeilen zu erhalten.

Sie können auch eine Partition hinzufügen, indem Sie beispielsweise die oberste Zeile jeder Farbe löschen.


-1

SQL-92:

DELETE Field FROM Table WHERE Field IN (SELECT TOP 1 Field FROM Table ORDER BY Field DESC)

TOPist kein Standard-SQL-92. Und ich sehe definitiv eine whereBedingung in Ihrer Antwort.
Martin Smith
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.