Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
tixon917
Member

Откуда:
Сообщений: 7
Здравствуйте!
Помогите, пожалуйста с проблемой задвоения серийного номера.
Есть процедура которая при каждом вызове создает новый серийный номер.
Каждый день создается тысячи серийных номеров. Вообщем-то все нормально работает. Делается продукция, создается новый серийный номер. Но бывает раз в неделю или раз в месяц получаются пару или больше одинаковые номера, что не допустимо. Не могу разобраться в чем проблема. Похоже что параллельный вызове хранимой процедуры с разных компов, функция Max() выдает одинаковый максимальный серийник.
Привожу саму процедуру:

SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[proce_insert_box]
@Param_id_worker int =0,
@Param_id_type_product int,
@Param_site varchar(50),
@Param_Atrib int=0,
@Param_Lev int=0,
@Param_DateIzgot datetime
AS
BEGIN
DECLARE @m as int,@r as int=0;
set @m=(SELECT MAX(serial) FROM Part_box);

SET NOCOUNT ON;
INSERT INTO [PrdSerials].[dbo].[Part_box]
([serial]
,[id_dealers]
,[id_worker]
,[status]
,[date]
,[DateIzgot]
,[id_type_product]
,[Lev]
,[site]
,[Atrib])
VALUES
(@m+1,NULL ,@Param_id_worker,0, getdate(),@Param_DateIzgot ,@Param_id_type_product,@Param_Lev,@Param_site,@Param_Atrib );

SELECT @m+1 as [newserial];
--RETURN SCOPE_IDENTITY();--ограничена сеансом
RETURN IDENT_CURRENT('Part_box');--не ограничена сеансом и областью

END
28 апр 16, 09:22    [19115727]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
_djХомяГ
Guest
Если надо определить значения только что вставленныых полей типа IDENTITY то используйте клаузу OUTPUT (версия сервера >=2005)
28 апр 16, 09:25    [19115738]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
Glory
Member

Откуда:
Сообщений: 104751
tixon917
Не могу разобраться в чем проблема. Похоже что параллельный вызове хранимой процедуры с разных компов, функция Max() выдает одинаковый максимальный серийник.

Потому что set @m=(SELECT MAX(serial) FROM Part_box); могут начать выполнять все сразу.
И все сразу получат одно и тоже значение. Потому что ничто этому не препятствует.
Сюрприз ?
28 апр 16, 09:26    [19115741]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
tixon917
Member

Откуда:
Сообщений: 7
Glory
Посоветуйте пожалуйста, направьте на правильный способ создания аналогичной процедуры.
28 апр 16, 09:57    [19115863]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
Glory
Member

Откуда:
Сообщений: 104751
tixon917
Посоветуйте пожалуйста, направьте на правильный способ создания аналогичной процедуры.

Зачем вы формируете значение serial сами, если у вас в таблице уже есть identity ?
28 апр 16, 09:59    [19115876]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6802
tixon917,

Почему дубли вполне понятно MAX ваш для всех один. Почему такая модель - непонятно, и при чём здесь варианты с идентити тоже.
переделайте свой serial хоть под ваш текущий identity, хоть под sequence
Текущее положение можно спасти чем то типа:

BEGIN

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

BEGIN TRAN 

INSERT INTO dbo.TestSerial
(
	Serial
)
SELECT ISNULL(MAX(Serial),0) + 1 FROM dbo.TestSerial with (tablockx, holdlock, updlock)

COMMIT

END
28 апр 16, 10:09    [19115930]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
tixon917
Member

Откуда:
Сообщений: 7
TaPaK,

(tablockx, holdlock, updlock)
скажите, когда включены эти параметры у таблицы и к ней обращается одна сессия и еще она не завершилась и в этот момент пытается обратится другая сессия у нее возникнет ошибка ?
28 апр 16, 10:59    [19116210]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
Glory
Member

Откуда:
Сообщений: 104751
tixon917
скажите, когда включены эти параметры у таблицы и к ней обращается одна сессия и еще она не завершилась и в этот момент пытается обратится другая сессия у нее возникнет ошибка ?

Нет. Но у клиента может произойти ошибка превышения его собственного таймаута ожидания завершения команды.
28 апр 16, 11:02    [19116236]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
invm
Member

Откуда: Москва
Сообщений: 9785
TaPaK
Текущее положение можно спасти чем то типа:

...
SELECT ISNULL(MAX(Serial),0) + 1 FROM dbo.TestSerial with (tablockx, holdlock, updlock)
...
Это шутка? Или на полном серьезе?


tixon917,

Если по-прежнему желаете работать через MAX, то
set @m=(SELECT MAX(serial) FROM Part_box with (serializable));
Плюс индекс на столбец serial.
28 апр 16, 11:11    [19116296]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
invm
Member

Откуда: Москва
Сообщений: 9785
Поправочка
set @m=(SELECT MAX(serial) FROM Part_box with (serializable, xlock));
28 апр 16, 11:20    [19116364]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6802
invm
TaPaK
Текущее положение можно спасти чем то типа:

...
SELECT ISNULL(MAX(Serial),0) + 1 FROM dbo.TestSerial with (tablockx, holdlock, updlock)
...
Это шутка? Или на полном серьезе?


tixon917,

Если по-прежнему желаете работать через MAX, то
set @m=(SELECT MAX(serial) FROM Part_box with (serializable));
Плюс индекс на столбец serial.

и что же вас смешит?

автор
set @m=(SELECT MAX(serial) FROM Part_box with (serializable));
и задавить всех deadlock-ами
28 апр 16, 11:20    [19116365]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
invm
Member

Откуда: Москва
Сообщений: 9785
TaPaK
и что же вас смешит?
Смешно указывать tablockx и что-то еще
28 апр 16, 11:21    [19116375]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
LockLock
Guest
invm, а зачем нужен xlock В смысле может можно обойтись updlock (естественно речь идет о выставленном до этого serializable)
Я действительно не оч понимаю Спасибо
28 апр 16, 11:30    [19116449]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
iap
Member

Откуда: Москва
Сообщений: 47107
Главное, чтобы никто не прочитал, пока один не закончит вставлять новое значение.
serializable для этого достаточно?
28 апр 16, 11:38    [19116520]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
invm
Member

Откуда: Москва
Сообщений: 9785
LockLock
invm, а зачем нужен xlock В смысле может можно обойтись updlock (естественно речь идет о выставленном до этого serializable)
Я действительно не оч понимаю Спасибо
Не нужен, но предотвращает лишнее действие - потому что все равно будет вставка новой строки и U на диапазон ключа будет сконвертирован в X.

iap
serializable для этого достаточно?
Для этого достаточно serializable + xlock(updlock)
28 апр 16, 11:44    [19116574]     Ответить | Цитировать Сообщить модератору
 Re: SCOPE_IDENTITY() или IDENT_CURRENT(' ')  [new]
invm
Member

Откуда: Москва
Сообщений: 9785
LockLock, хотя вы правы - в случае U, X будет накладываться только на вставляемое значение ключа.
28 апр 16, 11:56    [19116665]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить