Приветствую.
Как правильно сделать subj на MS SQL?
Допустим, есть пара таблиц, связанных отношением "многие к одному":
CREATE TABLE [dbo].[Employees] (
[EmployeeID] [int] IDENTITY (1, 1) NOT NULL ,
[LastName] [nvarchar] (20) NOT NULL ,bla-bla-bla )
CREATE TABLE [dbo].[EmployeeTerritories] (
[EmployeeID] [int] NOT NULL ,
[TerritoryID] [nvarchar] (20) NOT NULL
)
Чтобы добавить запись в EmployeeTerritories нужно знать EmployeeID свежедобавленной записи в Employees
А откуда его взять, если он создается автоматически?
В Interbase есть генераторы. И перед записью в главную таблицу я могу получить новый идентификатор из генератора, а потом его использовать и для главной таблицы, и для подчиненной.
____________________________
С уважением,
Stanislav V. Zudin
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте Stanislav V. Zudin, Вы писали:
SVZ>Как правильно сделать subj на MS SQL? SVZ>Допустим, есть пара таблиц, связанных отношением "многие к одному":
SVZ>
SVZ>Чтобы добавить запись в EmployeeTerritories нужно знать EmployeeID свежедобавленной записи в Employees SVZ>А откуда его взять, если он создается автоматически?
В MSSQL есть глобальная переменная @@Identity
т.е. после вставки в Employees @@Identity будет равна IDENTITY последней вставленной записи. Но надо быть осторожным, т.к. если в тригере вставить запись куда-то еще (обычное журналирование), то переменная вернет уже другое значение.
Здравствуйте vav, Вы писали:
vav>Здравствуйте Stanislav V. Zudin, Вы писали:
SVZ>>Как правильно сделать subj на MS SQL?
SVZ>>Чтобы добавить запись в EmployeeTerritories нужно знать EmployeeID свежедобавленной записи в Employees SVZ>>А откуда его взять, если он создается автоматически?
vav>В MSSQL есть глобальная переменная @@Identity vav>т.е. после вставки в Employees @@Identity будет равна IDENTITY последней вставленной записи.
А если другой пользователь в это время что-нибудь добавит, @@Identity изменится?
___________________________
С уважением,
Stanislav V. Zudin
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте Merle, Вы писали:
SVZ>>А если другой пользователь в это время что-нибудь добавит, @@Identity изменится?
M>Нет, не изменится.. M>@@IDENTITY работает в рамках сессии.
Ясно. Спасибо.
Вот как бы еще и с триггерами уладить.
Может глобальную переменную на время сессии создать для каждой таблицы (если возможно)?
Или лучше свой вариант генератора на основе таблицы написать?
__________________
С уважением,
Stanislav V. Zudin
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте vav, Вы писали:
vav>а обычно примерно так: vav>Поле F1 — identity vav>
vav>INSERT INTO T1 (F2,F3) VALUES (V2,V3)
vav>DECLARE @a int
vav>SELECT @a = F1 FROM T1 WHERE F2 = V2 and F3=V3
vav>
Делал подобное на Accesse, но там уникальность записи можно было определить по дате, которая хранилась в одном из полей (да и условие было — база однопользовательская). В общем случае такой метод не сработает. Значения в полях F2 и F3 могут быть не уникальны.
____________________________
С уважением,
Stanislav V. Zudin
_____________________
С уважением,
Stanislav V. Zudin
SVZ>Вот как бы еще и с триггерами уладить.
А ты уверен, что они нужны? Лучше все операции по возможности через процедуры делать, по ряду причин.
SVZ>Может глобальную переменную на время сессии создать для каждой таблицы (если возможно)? SVZ>Или лучше свой вариант генератора на основе таблицы написать?
А ты уверен, что тебе надо в качестве ключа использовать именно int?
Можешь делать например так:
DECLARE @ID uniqueidentifier
SET @ID = NewID()
И пользуй потом этот @ID во всех связанных таблицах как суррогатный ключ.
Этот NewID, по заверениям MS уникален в пределах планеты
Выборка будет немного медленнее, но именно что немного... Зато ты избавляешься от гиганского! геморроя, буде тебе понадобится делать репликацию, сливать несколько баз в одну или наоборот и пр. Вообщем гибкости здорово добавится.
Здравствуйте Stanislav V. Zudin, Вы писали:
SVZ>В общем случае такой метод не сработает. Значения в полях F2 и F3 могут быть не уникальны.
Действительно, такое решение подходит не для всех случаев. Очень часто сурогатные ключи используются одновременно с естественными, в этом случае все будет Ок.
Наличие одинаковых записей, различающихся только ключом, часто (но не всегда) является результатом ошибки при проектировании БД.
M>>@@IDENTITY работает в рамках сессии. SVZ>Ясно. Спасибо.
SVZ>Вот как бы еще и с триггерами уладить. SVZ>Может глобальную переменную на время сессии создать для каждой таблицы (если возможно)? SVZ>Или лучше свой вариант генератора на основе таблицы написать?
Для этого в MSSQL2k есть функция SCOPE_IDENTITY()
MSDN: Returns the last IDENTITY value inserted into an IDENTITY column in the same scope. A scope is a module -- a stored procedure, trigger, function, or batch.
Делать надо примерно так (выдержка хранимой процедуры):
DECLARE @Err INT, @NewID INT
INSERT INTO Employes VALUES ('Vasya')
SELECT @Err=@@ERROR, @NewID=SCOPE_IDENTITY()
IF @@Err <> 0 RETURN @@Err
INSERT INTO [EmployeeTerritories]
SELECT @NewID, [TerritoryID]
FROM [Teritories]
Здравствуйте Дмитрий Михайлов, Вы писали:
ДМ>Для этого в MSSQL2k есть функция SCOPE_IDENTITY()
Ну 2000к!!! Там и тригеры нумеруются и вьюшки с параметрами есть...
Вот только 27 баз на семерке не дают перейти