【问题标题】:Return rows in the exact order they were inserted按照插入的确切顺序返回行
【发布时间】:2013-06-27 14:21:20
【问题描述】:

我有一个简单的连接表,在 SQL Server 中有两个 id 列。 有没有办法按照插入的确切顺序选择所有行?

如果我尝试创建一个 SELECT *,即使我没有指定 ORDER BY 子句,这些行也不会按照它们插入的顺序返回,而是按第一个键列排序。

我知道这是一个奇怪的问题,但这张表很大,我需要准确检查奇怪行为何时开始,不幸的是我的表中没有时间戳列。

更新 #1

我将尝试解释为什么当我在没有 ORDER BY 子句的情况下 SELECT * FROM 表时,行没有按“自然”顺序返回。

我的桌子是这样的:

id1     id2
---------------
  1       1
  2       2
  3       3
  4       4
  5       5
  5       6

... and so on, with about 90.000+ rows

现在,我不知道为什么(可能是软件错误插入了这些行),但我的表有 450 万行,看起来像这样:

id1     id2
---------------
1       1
1       35986
1       44775
1       60816
1       62998
1       67514
1       67517
1       67701
1       67837
...
1       75657 (100+ "strange" rows)

2       2
2       35986
2       44775
2       60816
2       62998
2       67514
2       67517
2       67701
2       67837
...
2       75657 (100+ "strange" rows)

疯了,我的表现在有数百万行。我必须看看这种情况何时发生(插入行时),因为我必须删除它们,但我不能只使用 *WHERE id2 IN (strange_ids)* 删除,因为有“正确”的 id1 列属于这些 id2 列,我不能删除它们,所以我想看看这些行是什么时候被插入来删除它们的。

当我 SELECT * FROM 表时,它返回我按 id1 排序,如上表,并且 这些行没有按此顺序插入我的表中。我认为我的表没有损坏,因为这种奇怪的行为第二次以同样的方式发生,但现在我有很多行可以像第一次一样手动删除。为什么行没有按照插入的顺序返回?这些“奇怪的行”是昨天明确插入的,如果我在没有 ORDER BY 的情况下执行 SELECT *,应该在我的表末尾附近返回,不是吗?

【问题讨论】:

  • 您的 ID 列是否自动递增?
  • 不,它们只是两个外键
  • 您将不得不尝试找到某种方法将数据链接到另一个具有时间戳的表,或者为了了解行为何时开始表现出来。跨度>

标签: sql sql-server


【解决方案1】:

没有order byselect 查询不会以任何特定顺序检索行。您必须拥有order by 才能获得订单。

SQL Server 没有任何按插入顺序检索的默认方法。如果您有行中的信息,您可以这样做。最好的方法是主键标识列:

TableId int identity(1, 1) not null primary key

这样的列随着每一行的插入而递增。

您还可以有一个CreatedAt 列:

CreatedAt datetime default getdate()

但是,对于同时插入,这可能会有重复。

不过,关键点是没有 order by 子句的 select 会返回一组无序的行。

【讨论】:

  • 我们称之为确定性与非确定性
【解决方案2】:

正如其他人已经写的那样,您将无法按照插入顺序将行从链接表中取出。

如果此链接表加入的一个或两个表中的行存在某种内部排序,那么您可以使用它来尝试找出链接表行的时间已创建。基本上,它们不可能在之前创建包含 PK:s 的两行。

但另一方面,您将无法知道 创建它们之后的时间

如果您有不错的备份,您可以尝试恢复一个或几个不同年龄的备份,然后尝试查看这些备份是否也包含这种奇怪的行为。它至少可以为您提供一些关于奇怪何时开始的线索。

但最重要的是,只使用一个选择,现在可以按照插入的顺序将行从表中取出。

【讨论】:

    【解决方案3】:

    如果 SELECT * 没有以“自然”顺序返回它们,并且您没有使用时间戳或自动递增 ID 插入它们,那么我相信您已经沉没了。如果您有一个 IDENTITY 字段,请按此排序。 但是我的问题是,你怎么知道 SELECT * 没有按照插入的顺序返回它们?

    更新: 根据您的更新,似乎没有任何方法可以按您的意愿返回记录,我猜您在 ID1 上有一个聚集索引?

    【讨论】:

      【解决方案4】:
      Select *, %%physloc%% as pl from table
      order by pl desc
      

      【讨论】:

      • 单独的代码块并不能提供好的答案。请添加说明。
      猜你喜欢
      • 2022-06-11
      • 1970-01-01
      • 2019-04-25
      • 1970-01-01
      • 1970-01-01
      • 2018-04-17
      • 2014-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多