如何生成每年重置的自动递增 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 号的主要内容,如果未能解决你的问题,请参考以下文章