【问题标题】:Auto increment Alphanumeric ID in MSSQLMSSQL 中的自动递增字母数字 ID
【发布时间】:2013-07-16 05:52:48
【问题描述】:

我有一个生成员工 ID 的现有存储过程。员工 ID 的格式为 EPXXXX、EP,然后是 4 个数值。我希望缩短我的存储过程。

给定上面的表 (tblEmployee)。下面是使用新员工编号插入新员工的存储过程。过程是我必须获取最后一个员工 id,获取最后 4 位数字(即数字),将其转换为整数,加 1 以增加,检查数字是否小于 10、100 或 1000 或等于/大于大于 1000,在向表中插入新记录之前添加前缀。

create procedure NewEmployee

@EmployeeName VARCHAR(50)

AS
BEGIN

    SET NOCOUNT ON

    DECLARE @lastEmpID as VARCHAR(6)
    SET @lastEmpID =
    (
        SELECT TOP 1 Employee_ID
        FROM tblEmployee
        ORDER BY Employee_ID DESC
    )

    DECLARE @empID as VARCHAR(4)
    SET @empID = 
    (
        SELECT RIGHT(@lastEmpID, 4)
    )

    DECLARE @numEmpID as INT
    @numEmpID =
    (
        SELECT CONVERT(INT, @empID) + 1
    )

    DECLARE @NewEmployeeID as VARCHAR(6)
    IF @numEmp < 10
        SET @NewEmployee = SELECT 'EP000' + CONVERT(@EmpID)
    IF @numEmp < 100
        SET @NewEmployee = SELECT 'EP00' + CONVERT(@EmpID)
    IF @numEmp < 1000
        SET @NewEmployee = SELECT 'EP0' + CONVERT(@EmpID)
    IF @numEmp >= 1000
        SET @NewEmployee = SELECT 'EP' + CONVERT(@EmpID)

    INSERT INTO tblEmployee(Employee_ID, Name)
    VALUES (@NewEmployeeID, @EmployeeName)

END 

【问题讨论】:

  • 将数字部分单独存储在列中(可能是IDENTITY 列)然后有一个计算列来生成此格式化值会容易得多。在这种情况下,您是否还有一列来存储前缀或只是将其硬编码为 EP 是一个设计决定。

标签: sql sql-server


【解决方案1】:

试试这个 -

CREATE PROCEDURE dbo.NewEmployee

     @EmployeeName VARCHAR(50)

AS BEGIN

SET NOCOUNT ON;

     INSERT INTO dbo.tblEmployee(Employee_ID, Name)
     SELECT 
            'EP' + RIGHT('0000' + CAST(Employee_ID + 1 AS VARCHAR(4)), 4)
          , @EmployeeName
     FROM (
          SELECT TOP 1 Employee_ID = CAST(RIGHT(Employee_ID, 4) AS INT)
          FROM dbo.tblEmployee
          ORDER BY Employee_ID DESC
     ) t

END 

【讨论】:

  • 生成错误:“将 varchar 值 'EP0004' 转换为数据类型 int 时转换失败。”
【解决方案2】:

我不是建议你目前拥有什么,但是,我会这样做。这是我在我的应用程序中实现的方式。我会给你哪个。希望你喜欢这个。这是完全动态的,适用于您可能拥有的所有事务。

我有一张表格,其中包含文件编号:

CREATE TABLE INV_DOC_FORMAT(
    DOC_CODE VARCHAR(10),
    DOC_NAME VARCHAR(100),
    PREFIX VARCHAR(10),
    SUFFIX VARCHAR(10),
    [LENGTH] INT,
    [CURRENT] INT
)

哪一个会保存这样的数据:

INSERT INTO INV_DOC_FORMAT(DOC_CODE,DOC_NAME,PREFIX,SUFFIX,[LENGTH],[CURRENT])
VALUES('01','INV_UNIT','U','',5,0)

INSERT INTO INV_DOC_FORMAT(DOC_CODE,DOC_NAME,PREFIX,SUFFIX,[LENGTH],[CURRENT])
VALUES('02','INV_UNIT_GROUP','UG','',5,0)

而且,我有一个函数或过程,但是,我这里有一个函数,它会生成文档编号。

CREATE FUNCTION GET_DOC_FORMAT(@DOC_CODE VARCHAR(100))RETURNS VARCHAR(100)
AS
BEGIN
    DECLARE @PRE VARCHAR(10)
    DECLARE @SUF VARCHAR(10)
    DECLARE @LENTH INT
    DECLARE @CURRENT INT
    DECLARE @FORMAT VARCHAR(100)
    DECLARE @REPEAT VARCHAR(10)
    IF NOT EXISTS(SELECT DOC_CODE FROM INV_DOC_FORMAT WHERE DOC_CODE=@DOC_CODE)
        RETURN ''

    SELECT @PRE= PREFIX FROM INV_DOC_FORMAT WHERE DOC_CODE=@DOC_CODE
    SELECT @SUF= SUFFIX FROM INV_DOC_FORMAT WHERE DOC_CODE=@DOC_CODE
    SELECT @LENTH= [LENGTH] FROM INV_DOC_FORMAT WHERE DOC_CODE=@DOC_CODE
    SELECT @CURRENT= [CURRENT] FROM INV_DOC_FORMAT WHERE DOC_CODE=@DOC_CODE
    SET @REPEAT=REPLICATE('0',(@LENTH-LEN(CONVERT(VARCHAR, @CURRENT))))
    SET @FORMAT=@PRE + @REPEAT +CONVERT(VARCHAR, @CURRENT+1) + @SUF
    RETURN @FORMAT
END

你可以像这样使用函数:

INSERT INTO     INV_UNIT(UNIT_CODE,UNIT_NAME,UNIT_ALIAS,APPROVED,APPROVED_USER_ID,APPROVED_DATE) 
            VALUES(DBO.GET_DOC_FORMAT('01'),@Unit_Name,@Unit_Alias,@APPROVED,@APPROVED_USER_ID,@APPROVED_DATE)

--After Transaction Successfully complete, You can

UPDATE INV_DOC_FORMAT SET [CURRENT]=[CURRENT]+1 WHERE DOC_CODE='01'

或者,您可以创建一个单独处理所有事情的单一过程。

希望你能找到方法......

因此, 看着你的方式,你犯了一个错误。 你得到 设置@lastEmpID = ( SELECT TOP 1 Employee_ID 来自 tblEmployee ORDER BY Employee_ID DESC )

最后一个员工 ID,然后您正在处理 ID 的其余部分。这将创建或重用之前生成但现在已删除的 ID。 假设 EMP0010 在那里。过了一天,EMP 被删除了。因此,当您下次再次创建 Employeee 时,您将拥有与之前的其他 Employe 相同的 Emp ID,但不会再退出。我不认为那是个好主意。

而且,而不是这个:

DECLARE @NewEmployeeID as VARCHAR(6)
    IF @numEmp < 10
        SET @NewEmployee = SELECT 'EP000' + CONVERT(@EmpID)
    IF @numEmp < 100
        SET @NewEmployee = SELECT 'EP00' + CONVERT(@EmpID)
    IF @numEmp < 1000
        SET @NewEmployee = SELECT 'EP0' + CONVERT(@EmpID)
    IF @numEmp >= 1000
        SET @NewEmployee = SELECT 'EP' + CONVERT(@EmpID)

你曾经重复一个零。您将使用 SQL 的 Replicate Function()。就像上面我的例子一样。

SET @REPEAT=REPLICATE('0',(@LENTH-LEN(CONVERT(VARCHAR, @CURRENT))))

【讨论】:

  • 表已经存在,我没有权限修改结构。仍然感谢您的回复,这可能对将来有用。
  • 您正在创建一个整个过程,该过程将为一个单一的交易生成一个 ID!!!!这听起来不错?为什么您没有一个程序可以为您的应用程序中的所有事务生成一个 ID?如果是这样,那么现在,你可以建议你的前辈那样。不要你!我认为你必须这样做。您正在做的方式是,如果您有 200 种交易类型,例如员工、代理、供应商、客户……什么,您会创建单个过程 foreach 以生成 id 吗?最好你有一个可以管理所有的程序。推荐你的前辈。
【解决方案3】:

我认为您不需要 Stored Procedure ,请尝试使用 Ranking Functions

select 
'EP'+RIGHT('000000'+ CAST(ROW_NUMBER() OVER (ORDER BY Name) AS VARCHAR(6)), 4) 
    AS [emp_code]
,
Name
FROM emp1 WITH(NOLOCK)

SQL Fiddle

编辑

select 
'EP'+RIGHT('000000'+ CAST((ROW_NUMBER() OVER (ORDER BY Name)+10) AS VARCHAR(6)), 4) 
    AS [emp_code]                                        --^Add the last Emp no.
,
Name
FROM emp1 WITH(NOLOCK)

SQL Fiddle

【讨论】:

  • 它正在工作,但流程是什么,表中有现有记录,我需要为员工输入顺序 ID,而不是按姓名。
  • 你的意思是什么这是安排姓名而不是员工ID我没听懂你的意思。如果您可以提供完整的数据,我可以生成完整的证明脚本。
  • 在我的示例表中,安排是 EP0001 John、EP0002 Peter、EP0003 David、EP0004 George。使用 SQL Fiddle 的输出是。 EMP011 大卫 EMP012 乔治 EMP013 约翰 EMP014 彼得
  • @nigel 编辑了答案。
【解决方案4】:

当然,接受的答案工作正常,但如果我们在以前的值中有 numm,它就不起作用。所以修改如下,希望这对其他人也有帮助

CREATE PROCEDURE dbo.NewEmployee

 @EmployeeName VARCHAR(50)
AS BEGIN
SET NOCOUNT ON;

 INSERT INTO dbo.tblEmployee(Employee_ID, Name)
 SELECT 
        'EP' + RIGHT('0000' + CAST(Employee_ID + 1 AS VARCHAR(4)), 4)
      , @EmployeeName
 FROM (
      SELECT TOP 1 Employee_ID = CAST(RIGHT(Employee_ID, 4) AS INT)
      FROM dbo.tblEmployee
      ORDER BY Employee_ID DESC
 ) t
END 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多