从SQL Server中的表中删除“第一”记录,而没有WHERE条件


73

是否可以在SQL Server不使用任何WHERE条件且不使用游标的情况下从中的表中删除“第一条”记录?


您想满足您的要求吗?
cjk

@Quassnoi:按照标题的SQL Server。
Stanislav Kniazev

14
我们是否真的要坐在这里争论SQL Server的模棱两可?我认为主要RDBMS的术语已经有一段时间是标准的了(SQL Server,MySQL,Postgres,Oracle,SQLite等),并且没有那么令人困惑。
TheTXI

6
不要忘记FoxPro!这是一个数据库。非常毛茸茸的
belgariontheking

2
@TheTXI我发帖时没有这样的标签,它是其他人后来添加的(请看编辑日志)。没有它,我确实会感到模棱两可,而且我确实喜欢惹恼那些认为微软是世界上唯一的软件开发人员的人;)
soulmerge 2009年

Answers:


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

注意

DELETE TOP (1)
FROM   mytable

也可以使用,但是,如文档中所述:

在所引用的行TOP表达与所用INSERTUPDATEDELETE不按任何顺序排列。

因此,最好使用WITHORDER BY子句,它可以让您更准确地指定您认为第一行。


2
请注意,WITH在表达式中使用时,以前的sql语句应以分号(;)终止
Alexander Alexander

使用ORDER BY 1将对SQL Server中许多人的表提供微妙的改进:您将获得具有最低主键值的行,很可能是“第一”行。(是的,有些表没有PK作为第一列,但它1是我最喜欢的惰性快捷方式,我想与他人分享。)
Magnus Smith

@MagnusSmith:改善了什么?
Quassnoi

这只是一个小问题。您的回答没有给出特定的ORDER BY子句,我意识到原始张贴者要求输入“第一”行,但似乎无法指定列名。这使我想到了使用1
Magnus Smith

@MagnusSmith:好的,尽管指定显式命名的列总是更好。
Quassnoi

43

取决于您的DBMS(当今人们似乎不知道那是什么)

-- 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违反了“无...何处”限制(无论该限制的目的是什么)。
Stanislav Kniazev

6

不,AFAIK,无法随身携带。

无论如何,都没有定义的“第一”记录-在不同的SQL引擎上,极有SELECT * FROM table可能每次都以不同的顺序返回结果。


3

定义“第一”?如果表中有一个PK,那么它将按该顺序排序,您可以按此删除:

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

如果表格没有PK,则无法保证订购...


如果我的聚集索引与我的PK不同怎么办?
当日,2009年

啊,当然,我的错-那将是聚集索引的第一行,因为它实际上是对行进行排序,而不是PK。抱歉造成混乱。
Meff

即使这样,也不能保证它是聚簇索引排序的“第一个”。SQL Server对此不做任何保证。
Damien_The_Unbeliever


我喜欢那个PPT,非常感谢。大声笑在“ NoLock是一个很酷的提示”-我在一个认为不会接受的地方工作。我离开了。
Meff

1

这真的有意义吗?
关系数据库中没有“第一”记录,您只能删除一个随机记录。


1
当您按“ order by”混合时,这很有意义;问题没有提到不要使用“ order by”,而不能使用“ where”和光标
dance2die

仅当您按唯一列排序时。如果不是唯一的,则您仍然不完全知道要删除的记录。
Christian Specht

1

“表中的“第一个”记录”是什么意思?我认为,在关系数据库中没有“第一记录”这样的概念。

使用MS SQL Server 2005,如果要删除“最高记录”(执行简单的“ * select * from tablename *”时显示的第一个记录),则可以使用“ delete from tablename top(1) ” ...但是要注意,这不能确保从记录集中删除哪一行,因为它只是删除了如果您运行命令“ select from tablename(select top(1)from tablename) ”将显示的第一行。


但是,最先出现的行可能在运行该选择和运行后续删除之间有所不同。有没有对排序保证没有order by子句。
Damien_The_Unbeliever

你是对的。我想我在帖子中强调了这一点。“最高记录”可能会有所不同。多谢您的回覆,因为我的英语水平不是最好,而且我的回覆可能不清楚。
XpiritO

0

类似于所选答案,可以使用表源,在这种情况下,可以使用派生查询:

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

随时添加orderbys和条件。

对于下一个示例,我假设对“ where”的限制是由于不想基于其值选择行。因此,假设我们要基于位置(在本例中为第一个位置)删除行:

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

请注意,(选择1)使其成为表或索引所在的排序顺序。您可以将其替换为newid,以获得相当随机的行。

例如,您还可以通过删除每个颜色的第一行来添加分区。


-1

SQL-92:

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

TOP不是标准的SQL-92。我肯定会where在您的回答中看到一个条件。
马丁·史密斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.