Увеличить поле идентификатора с помощью цикла while - PullRequest
0 голосов
/ 02 декабря 2018

Я пытаюсь сгенерировать идентификатор, формат которого 000H-Y, где цифры идут от 000 до 019. Мой код генерирует только с 010H-Y до 019H-Y.Есть ли проблема с форматированием или ошибка в цикле while?

if exists(select * from sysobjects where name = 'Bikes')
    drop table Bikes
go

create table Bikes
(
    BikeID nchar(6) not null,
        constraint pk_Bikes_BikeID primary key(BikeID),
        constraint chk_Bikes_BikeID check(BikeID like ('0[0-19][HYS]-[AP]')),
    StableDate date not null
        default getdate()
)
go

if exists(select * from sysobjects where name = 'PopulateBikes')
    drop procedure PopulateBikes
go

create procedure PopulateBikes
@outcome as nvarchar(12) output
as
declare @min as int = 0, 
@max as int = 19
    if @@ERROR <> 0
        return -1
    while(@min < @max)
    begin
        set @min+=1
        insert into Bikes(BikeID)
        values ('0'+ cast(@min as nvarchar(2))+ 'H-A')

    end
go

declare @retVal as int = 0
exec @retVal = PopulateBikes 'SPName:OK'
if @retVal = -1
    print 'Error encountered!'
go

select * from Bikes go

Ответы [ 2 ]

0 голосов
/ 02 декабря 2018

Решение:

Рассмотрим, как вы генерируете значения для BikeID.

С помощью этой строки:

select ('0'+ cast(@min as nvarchar(2))+ 'H-Y')

вы будете генерировать значенияот 01H-Y до 019H-Y.

Попробуйте с этим:

select RIGHT('000'+ cast(@min as nvarchar(2)), 3) + 'H-Y'

Также вам нужно изменить проверочное ограничение на:

constraint chk_Bikes_BikeID check(BikeID LIKE '0[0-9][0-9][HYS]-[AYP]')
0 голосов
/ 02 декабря 2018

Вы можете использовать рекурсивный CTE

WITH CTE AS
(
  SELECT 1 N
  UNION ALL
  SELECT N + 1
  FROM CTE
  WHERE N <= 18
)

SELECT CAST(N AS VARCHAR(10)) + 'H-Y'
       -- or SELECT '0' + CAST(N AS VARCHAR(10)) + 'H-Y'
FROM CTE;

Нет необходимости использовать WHILE цикл, и это убивает производительность.

Также ваше ограничение CHECK нарушено, онодолжно быть похоже на

CONSTRAINT CH_Bikes_BikeID CHECK(BikeID LIKE '0[0-9]H-Y' OR BikeID LIKE '0[0-9][0-9]H-Y')

Итак, вот ваша таблица и запрос на ее заполнение

CREATE TABLE Bikes
(
  BikeID VARCHAR(10) NOT NULL,
  StableDate DATE NOT NULL DEFAULT GetDate(),
  CONSTRAINT CH_Bikes_BikeID CHECK(BikeID LIKE '0[0-9]H-Y' OR BikeID LIKE '0[0-9][0-9]H-Y'),
  CONSTRAINT PK_Bikes_BikeID PRIMARY KEY (BikeID)
);

WITH CTE AS
(
  SELECT 1 N
  UNION ALL
  SELECT N + 1
  FROM CTE
  WHERE N <= 18
)

INSERT INTO Bikes (BikeID)
SELECT '0' + CAST(N AS VARCHAR(10)) + 'H-Y'
FROM CTE;

SELECT *
FROM Bikes
ORDER BY CASE WHEN LEN(BikeID) = 5
          THEN 0
          ELSE 1
          END;

Демо


ОБНОВЛЕНИЕ

Исходя из кода, который вы предоставляете для создания таблицы, я предполагаю, что вы ошибаетесь, потому что я думаю, что эти символы являются возможными значениями, поэтому вы можете создать свою таблицу как

CREATE TABLE Bikes
(
  BikeID VARCHAR(10) NOT NULL,
  StableDate DATE NOT NULL CONSTRAINT DF_Bikes_StableDate DEFAULT GetDate(),
  CONSTRAINT PK_Bikes_BikeID PRIMARY KEY (BikeID),
  CONSTRAINT CH_Bikes_BikeID 
  CHECK(BikeID LIKE '0[0-9][H,Y,S]-[A,P]' OR BikeID LIKE '0[0-9][0-9][H,Y,S]-[A,P]')
);

А вот пример вставки данных в него

WITH CTE AS
(
  SELECT 1 N
  UNION ALL
  SELECT N + 1
  FROM CTE
  WHERE N <= 18
)

INSERT INTO Bikes (BikeID)
SELECT '0' + CAST(N AS VARCHAR(10)) + 
       CASE WHEN N % 3 = 1
            THEN 'H-A'
            ELSE 'Y-P'
            END
FROM CTE
ORDER BY N;

SELECT *
FROM Bikes
ORDER BY CASE WHEN LEN(BikeID) = 5
              THEN 0
              ELSE 1
              END;

В строке CHECK(BikeID LIKE '0[0-9][H,Y,S]-[A,P]' OR BikeID LIKE '0[0-9][0-9][H,Y,S]-[A,P]') проверьте возможные значения, например:

  • H-A разрешено
  • Y-P разрешено
  • S-P разрешено
  • K-A запрещено
  • AB-AP запрещено
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...