如何生成每年重置的自动递增 ID 号

Posted

技术标签:

【中文标题】如何生成每年重置的自动递增 ID 号【英文标题】:How to generate an auto-incrementing ID number that resets yearly 【发布时间】:2021-08-06 13:40:20 【问题描述】:

我有一个基于年份生成学生 ID 的应用程序,例如第一个 ID: 202100001,然后是 202100002,以此类推。基本上需要一年并开始递增计数器。

这很好也很简单,但我的问题是它从数据库中获取最后一个 ID 来生成学生 ID。 当有新的一年时,年份部分会发生变化,但不会重置为零。 我想在 2022 年从 202200001 开始,然后是 202200002,依此类推。 有没有更简单的方法来重置计数器,我应该为此添加一个新列吗?

这是我当前的代码:

//Generate Student Number
string StudentNumber;
private void GenerateStudentNumber()

    DateTime moment = DateTime.Now;
    string year = moment.Year.ToString();
    try
    
        StudentNumber = GenerateID();               
        txtStudentNumber.Text = year + StudentNumber;
    
    catch (Exception ex)
    
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    


private string GenerateID()
    
    string value = "00";
    int IDindex = 0;
    try
            
        using (con = new SqlConnection(databaseConnectionString))
        
            // Fetch the latest ID from the database
            con.Open();
            cmd = new SqlCommand("SELECT TOP 1 StudentID FROM Students order BY StudentID DESC", con);
            rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            if (rdr.HasRows)
            
                rdr.Read();
                IDindex = Convert.ToInt16(rdr["StudentID"]);
            
            rdr.Close();
        
            
        IDindex++;
        // Because incrementing a string with an integer removes 0's
        // we need to replace them. If necessary.
        if (IDindex <= 9)
        
            value = "00" + value + IDindex.ToString();
        
        else if (IDindex <= 99)
        
            value = "0" + value + IDindex.ToString();
        
        else if (IDindex <= 999)
        
            //value = "00" + value + IDindex.ToString();
            value = value + IDindex.ToString();
        
        else if (IDindex <= 9999)
        
            value = "0" + IDindex.ToString();
                
    
    catch (Exception ex)
    
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    
    return value;

这是我的 SQL 表:

CREATE TABLE [dbo].[Students] (
    [StudentID]          INT             IDENTITY (1, 1) NOT NULL,
    [StudentNumber]      NVARCHAR (50)   NOT NULL,
);

非常感谢。

【问题讨论】:

“但我的问题是它从数据库中获取最后一个 ID 来生成学生 ID” 问题不仅在于您需要每年生成它,而且您的代码生成它。这仅是数据库的一项任务,该数据库也负责 ID。否则,这就是你的应用迟早会失败的竞争条件。 大多数数据库,包括 SQL Server,都有一个SEQUENCE 类型可以用于此。 这听起来像是您应该使用 row_number 计算并按年份分区的数据。 什么时候你重置序列?基于什么标准?如果您使用当前时间,使用 SEQUENCE 会更容易很多,将StudentNumber 的默认值设置为NEXT VALUE FOR StudentCounter 并每年重置一次。由于您在谈论 StudentID,因此“年”无论如何都不会是日历年 顺便说一句,你的整个 if 块可以用 IDIndex.ToString("00000") 的一些调整来替换。不要使用 PascalCase 命名局部变量;使用驼峰式 【参考方案1】:

我的建议是设置一个序列:

 CREATE SEQUENCE StudentSequenceWithinYear;

一年一次,您可以运行一个作业来重置该值:

ALTER SEQUENCE StudentSequenceWithinYear RESTART WITH 1 ;  

您可以将其自动设置为在 12 月 31 日/1 月 1 日午夜左右运行。

那么在CREATE TABLE语句中,可以使用:

CREATE TABLE Students (
    StudentID  INT IDENTITY (1, 1) NOT NULL,
    StudentNumber NVARCHAR (50) NOT NULL,
    Year INT DEFAULT YEAR(GETDATE()),
    WithinYearSequence INT DEFAULT NEXT VALUE FOR StudentSequenceWithinYear,
    MyStudentId AS (CONCAT(Year, FORMAT(WithinYearSequence, '00000'))) 
);

话虽如此,我认为您应该只使用身份列来识别学生。尝试在 id 中存储信息通常会导致边缘情况出现问题(例如,学生辍学一年但又返回另一年)。您可以随时在数据库中查找年份,因此无需将其存储为 id 的一部分。

【讨论】:

谢谢戈登。我以前没有使用过序列,但这个选项似乎可以在我的应用程序中使用。我会研究你的建议。

以上是关于如何生成每年重置的自动递增 ID 号的主要内容,如果未能解决你的问题,请参考以下文章

重置自动递增序列 pl-sql

在 Microsoft SQL Server 2008 R2 中重置自动增量

重置自动递增编号

安卓虚拟机,如何重置硬件设备信息

重新排序/重置自动增量主键

重新排序/重置自动增量主键