2013-07-16 5 views
3

У меня есть существующая Хранимая процедура, которая генерирует идентификатор сотрудника. Идентификатор сотрудника имеет формат EPXXXX, EP, а затем 4 числовые значения. Я хочу, чтобы моя хранимая процедура была сокращена.Auto increment Alphanumeric ID в MSSQL

enter image description here

приведены в таблице (tblEmployee) выше. Ниже приведена хранимая процедура для ввода нового сотрудника с новым номером сотрудника. Процесс состоит в том, что я должен получить последний идентификатор сотрудника, получить последние 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 
+1

Было бы гораздо легче хранить числовую часть в колонке самого по себе (возможно, 'IDENTITY' столбец) и затем вычисляемый столбец, который производит это отформатированное значение. В таком сценарии, есть ли у вас также столбец для хранения префикса или просто жесткий код, он для «EP» является дизайнерским решением. –

ответ

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 
+0

Это приводит к ошибке: «Ошибка преобразования при преобразовании значения varchar« EP0004 »в тип данных int.» – nigel

+0

Попробуйте обновленный ответ. – Devart

+0

он работает, спасибо :) – nigel

1

Я не думаю, что вам нужно 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

EDIT

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

+0

попробовал, но не увеличил новый сотрудник ID – nigel

+0

Check the Fiddle. – Luv

+0

он работает, но в каком процессе есть существующие записи в таблице, и мне нужно поставить последовательный идентификатор для сотрудника, а не по имени. – nigel

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 [email protected]_CODE) 
     RETURN '' 

    SELECT @PRE= PREFIX FROM INV_DOC_FORMAT WHERE [email protected]_CODE 
    SELECT @SUF= SUFFIX FROM INV_DOC_FORMAT WHERE [email protected]_CODE 
    SELECT @LENTH= [LENGTH] FROM INV_DOC_FORMAT WHERE [email protected]_CODE 
    SELECT @CURRENT= [CURRENT] FROM INV_DOC_FORMAT WHERE [email protected]_CODE 
    SET @REPEAT=REPLICATE('0',(@LENTH-LEN(CONVERT(VARCHAR, @CURRENT)))) 
    SET @[email protected] + @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' 

Или, вы можете создать единую процедуру, которая будет обрабатывать все вещи в одиночку тоже.

Надеется, что вы получили путь ...

Следовательно, Глядя на своем пути, вы делаете ошибку. Вы получаете SET @lastEmpID = ( ВЫБРАТЬ TOP 1 EMPLOYEE_ID ОТ tblEmployee ORDER BY DESC EMPLOYEE_ID )

Последний идентификатор сотрудника, а затем вы манипулируете остальной ID. Это приведет к созданию или повторному использованию идентификатора, который был сгенерирован ранее, но теперь удален. Предположим, что EMP0010 был там. Через какое-то время EMP была удалена. Итак, когда вы снова создадите Employeee в следующий раз, у вас будет тот же самый идентификатор Emp, который у вас был раньше для анонимного Employe, но больше никаких выходов. Я не думаю, что это хорошая идея.

И, вместо этого:

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) 

Что вы использовали, чтобы повторить Зеро. Вы использовали бы функцию Replicate Function() SQL. Как и выше на примере шахты.

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

Таблица уже существует, и я не имею права изменять структуру. все еще спасибо за ответ, это может быть полезно для будущего использования. – nigel

+1

Вы создаете целую процедуру, которая создавала бы идентификатор только для одной транзакции !!! Это звучит хорошо? Почему у вас нет процедуры, которая генерирует идентификатор для всех транзакций, которые будут иметь в вашем приложении? Если так, то, теперь, вы можете предложить своего старшего там таким образом. Не ты! Думаю, вам нужно. Способ, который вы делаете, Если у вас есть 200 видов транзакций, таких как Employee, как агент, поставщик, клиент ... Что, вы создадите Single Procedure foreach для генерации идентификатора? Было бы лучше, если бы у вас была одна процедура, которая могла бы управлять alllll. Предложите своему старшему. –

0

Конечно, принятый ответ работает нормально, но он не работает, если у нас есть 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