【问题标题】:Ordering a database table then numbering a column对数据库表排序,然后对列编号
【发布时间】:2018-02-05 09:52:55
【问题描述】:

我有一个为会计文件制作的 mysql 表。表格如下:

  id  | doc_number |    doc_date
------|------------|-----------------
  24  |     24     |    1501061817
  25  |     25     |    1501750532
  26  |     26     |    1501750457

假设我们删除了一个 doc_number 为 25 的记录。所以现在 doc_numbers 是 ..,21,22,23,24,26,27,... 24 之后我们有 26 而不是25.

随着时间的推移,会计文件将被添加到表中和从表中删除,并且 doc_number 必须是连续的。

由于某些原因,我必须编写一个同步 doc_numbers 的 php 方法。答案很简单:

public function sync(){
  $sql = "SELECT id FROM acc_docs ORDER BY doc_date ASC, id DESC";
  $array = DB::run_query($sql); //a method that runs a query and returns the result as an array of objects
  foreach($array as $key => $object){
    $sql = "UPDATE acc_docs SET doc_number=".($key+1)." WHERE id=".$object->id;
    DB::execute_query($sql); // a method that executes sql queries
  }
}



很明显,这不是一个好习惯。为此目的的最佳做法是什么?编写对表进行排序然后对列进行编号的方法的最佳方法是什么?我搜索了它并找到了像this 这样的好问题,但我找不到任何既可以订购又可以更新专栏的东西。

【问题讨论】:

  • 我看不出存储这些信息的意义
  • 如果id 是主键,那么重新索引将来会给你带来很大的问题(当其他一些表将使用这个id 作为foreign key 时)
  • 这里有矛盾。 doc_number 可能出于某种原因必须是连续的,检查是否没有删除或添加任何文档。现在你想故意打破这个? PS:如果你想要 doc_number,你可以简单地问:SELECT COUNT(*) FROM acc_docs WHERE id <= targetId。日期似乎与订购无关?
  • 答案在您发布的链接中。也阅读 cmets。但就像草莓说的那样,这有什么意义呢? @AlivetoDie 这不是关于 id,而是关于 doc_number。
  • 这里有一个选项:删除文档记录时只需进行软删除。现在,一切都是连续的,但你仍然知道删除了什么。或者,在查询时使用会话变量生成序列。

标签: php mysql


【解决方案1】:

听起来你想要的只是表格 ID 的连续数字顺序。这引出了一个问题,为什么您将其存储在数据库中而不是在您选择时生成它,从而始终正确?

SET @doc_number=0;
SELECT ID, @doc_number:=@doc_number+1 AS doc_number, doc_date
  FROM acc_docs
  GROUP BY ID
  ORDER BY ID DESC;

【讨论】:

    【解决方案2】:

    正如@KIKO Software 所说,doc_number 需要永久链接到原始源文档,以便为内部控制目的提供清晰的审计跟踪。原因如下:

    1. 如果记录被删除doc_numbers 中的“间隙”显示记录不连续并且存在问题。

    2. 列名 doc_number 还表明它链接到另一个文档,该文档可能是数据库外的业务流程的一部分。更新 doc_number 将使这种关系失效。简而言之,不要更改 doc_number。

    3. 如果在源文档的制作过程中出现错误,则不要删除它,而是提出另一个反对文档来扭转错误,从而维护审计跟踪并反映'正常的商业惯例。

    另请参阅下面与@ADyson 的有益讨论。

    【讨论】:

    • 是的...尽管在示例中“id”与 doc_number 相同,并且可能是表的主键。如果您认为 doc_number 被用作唯一标识符,那么它实际上是多余的,因为“id”已经是并且也是表的主键,因此应该用于此目的。
    • 我不想深入会计,但相信我需要这样的方法来更新数据库中的此类列。其背后的整个逻辑是会计师希望按原样查看文件编号。突然有一天,他们决定重组 acc_numbers。事实是它们必须是不连续的,除非他们希望它们是。
    • @ADyson,从数据库的角度我同意,但是 doc_number 很可能在业务流程中使用并且 id 被忽略,因此审计跟踪将显示为连续的。此外,即使 id 显示有差距,我们也不知道删除了什么或原因。
    • “这个doc_number很可能会在业务流程中使用”……那么就删除id列,把doc_number作为主键。这只是一个字段名称。做同样事情的两个领域是没有意义的。而如果在业务流程中使用了doc_number,则每次都需要一致地标识同一个文档,这使得它成为唯一的标识符,这意味着它应该被用作主键。
    • @ADyson 会的,谢谢,我喜欢讨论并认为这对 OP 会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-27
    • 1970-01-01
    • 2017-04-19
    • 1970-01-01
    • 1970-01-01
    • 2019-12-22
    相关资源
    最近更新 更多