Как использовать несколько идентификационных номеров в одной таблице? - PullRequest
0 голосов
/ 04 мая 2010

У меня есть веб-приложение, которое создает печатные формы, эти формы имеют уникальный номер, проблема в том, что у меня есть 2 формы, для которых необходимо создать отдельные номера. т.е.)

Форма 1 - пронумерована 2000000-2999999
Форма 2 - пронумерована 3000000-3999999

dbo.test2 - это таблица сведений о моей форме
Цел - это мой автоинк стол для номеров серии 3000000
Tadv - это моя таблица автоинкеров для номеров серии 2000000

Я создал две таблицы с одной строкой autoinc (одна для номеров серии 2000000 и одна для номеров серии 3000000), затем я создал триггер для добавления записи в таблицу ответов на ядро, считал номер autoinc и добавил это моя таблица, в которой хранится информация о форме, включая только что созданный номер autoinc для правильной серии форм.

Хотя это работает, я обеспокоен тем, что числа будут испорчены под нагрузкой. Я не уверен, что @@ IDENTITY всегда будет возвращать правильное значение, когда многие люди используют систему. (У меня не может быть дубликатов, и мне нужно использовать форму нумерации, показанную выше.

См. Код ниже. **** ТРИГГЕР ****

CREATE TRIGGER MAKEANID2 ON dbo.test2
AFTER INSERT
AS
SET NOCOUNT ON
declare @someid int
declare @someid2 int
declare @startfrom int
declare @test1 varchar(10)

select @someid=@@IDENTITY

select @test1 = (Select name1 from test2 where sysid = @someid )
if @test1 = 'select'
begin
 insert into Tsel Default values
 select @someid2 = @@IDENTITY
end

if @test1 = 'adv'
begin
 insert into Tadv Default values
 select @someid2 = @@IDENTITY
end

update test2
set name2=(@someid2) where sysid = @someid
SET NOCOUNT OFF

Ответы [ 2 ]

1 голос
/ 04 мая 2010

Лучший способ синхронизировать два идентификатора - создать постоянный вычисляемый столбец на основе фактического столбца идентификаторов. Где Col1 - столбец идентификаторов, а Col2 - постоянный вычисляемый столбец, который является результатом некоторой формулы на основе Col1. Затем вы даже можете Создать индексы для вычисляемых столбцов .

проверить это:

CREATE TABLE YourTable
(Col1 int not null identity(2000000,1)
,Col2 AS (Col1-2000000+3000000) PERSISTED
,Col3  varchar(5)
)
GO

insert into YourTable (col3) values ('a')
insert into YourTable (col3) SELECT 'b' UNION SELECT 'c'

SELECT * FROM YourTable

ВЫВОД:

Col1        Col2        Col3
----------- ----------- -----
2000000     3000000     a
2000001     3000001     b
2000002     3000002     c

(3 row(s) affected)

РЕДАКТИРОВАТЬ После комментариев ОП я все еще не уверен на 100%, что вы после.

Я никогда не использовал SQL Server 2000 (мы пропустили эту версию), и я действительно не хочу искать, как сделать все в этой версии, он настолько ограничен без предложения OUTPUT и ROW_NUMBER (), CTE и т. Д. .

Я могу придумать три способа сделать:

1) Вы можете просто создать таблицу последовательности, в которой у вас есть 2 строки, одна для A и одна для B, каждый раз, когда вам нужно вставить одну, искать, увеличивать и сохранять значение нужного вам типа seq а затем вставить с этим значением. например, если вы вставляете строку типа «A», сделайте следующее:

INSERT INTO test2
        (col1, col2, col3,...)
    SELECT
        ISNULL(MAX(NextSeq),0)+1, col2, col3,...
        FROM YourSequenceTable WITH (UPDLOCK, HOLDLOCK)
        WHERE SequenceType='A'

UPDATE YourSequenceTable 
    SET NextSeq=ISNULL(NextSeq,0)+1
    WHERE SequenceType='A'

2) измените структуру таблицы, чтобы просто сохранить данные в Tsel или Tadv, и вставьте триггер в третью общую таблицу таблиц, где вы можете иметь дополнительную «общую» идентификацию. общая таблица будет выглядеть как

CommonTable
ID      int not null indentity(1,1) primary key
TselID  int null FK to Tsel.PK 
TadvID  int null FK to Tadv.PK

3) если вам нужна одна таблица, попробуйте это, что является настоящим хаком. Измените таблицы Tsel и Tadv так, чтобы они содержали все необходимые столбцы и из приложения INSERT INTO Tsel, когда значение равно select, и триггер захватывает это значение идентификатора, а затем вставляет его в test2, затем удаляет данные из tsel. Затем из приложения, когда значение равно adv, просто INSERT INTO Tadv, есть триггер для этой таблицы, вставьте данные в test2 и удалите данные из Tadv. Вам нужно иметь все столбцы данных в Tsel и Tadv, чтобы триггер мог скопировать значения в test2, но триггер удалит строки оттуда (идентичность будет последовательной, даже если исходные строки будут удалены).

Ваш триггер Tsel будет выглядеть так:

CREATE Trigger  MAKEANID2_Tsel ON dbo.Tsel
AFTER INSERT
AS

--copy data from Tsel into test2., test2 can still have its own identity value
INSERT INTO test2
        (PK, col1, col2, col3,...)
    SELECT
        col0, col1, col2, col3,....
        FROM INSERTED

--remove rows from Tsel, which were just copied and not needed anymore.
DELETE Tsel
    WHERE PK IN (SELECT PK FROM INSERTED)

GO
0 голосов
/ 08 мая 2010

Вы правы, что беспокоитесь о @@ identity, это не рекомендуемая часть кода, если кто-то еще добавит триггер difnet, который вставляет тождество и который запускает первый, то есть значение, которое вы получите.

Но у вас гораздо большие проблемы. Ваш триггер предназначен для работы только на одной записи одновременно. Это очень-очень плохая вещь, связанная с триггером. Триггеры работают с наборами данных и должны ВСЕГДА, даже если вы думаете, что никогда не будет вставлено более одной записи за раз), должны обрабатывать наборы данных, а не одну запись. Кроме того, вам не нужно запрашивать идентификационные данные, у вас есть идентификационные данные всех записей, вставленных в пакетном режиме в доступном триггере, называемом вставленным.

Теперь, читая один из ваших комментариев, вы говорите, что вообще не можете иметь пропущенные значения. В этом случае вы не можете ни при каких обстоятельствах использовать столбец идентификаторов, поскольку в нем будет пробел, если откат какой-либо транзакции будет выполнен. Вам нужно будет написать свой собственный процесс для создания чисел на основе последнего номера и следить за условиями гонки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...