Получить сгенерированный идентификатор в MS SQL 2008 - PullRequest
2 голосов
/ 24 февраля 2012

Я преобразовываю проект ColdFusion из Oracle 11 в MS SQL 2008. Я использовал SSMA для преобразования БД, включая триггеры, процедуры и функции.Последовательности были сопоставлены со столбцами IDENTITY.

Я планировал использовать INSERT-операторы, такие как

INSERT INTO mytable (col1, col2)
OUTPUT INSERTED.my_id
values('val1', 'val2')

Это выдает ошибку, поскольку в таблице определен триггер, и AFTER INSERT записывает некоторые из INSERTED.данные в другую таблицу для хранения истории данных.

Microsoft пишет:

Если указано условие OUTPUT без указания ключевого слова INTO, цель операции DML не можетиметь любой включенный триггер, определенный для него для данного действия DML.Например, если предложение OUTPUT определено в операторе UPDATE, в целевой таблице не должно быть никаких включенных триггеров UPDATE.http://msdn.microsoft.com/en-us/library/ms177564.aspx

Теперь мне интересно, как лучше всего сначала получить сгенерированный идентификатор, а затем «сделать резервную копию» ВСТАВЛЕННЫХ данных во второй таблице.

хороший подход для вставки?Это работает, потому что значение INSERTED не просто возвращается, а записывается во временную переменную.Это работает в моих тестах, как описывает Microsoft, не выдавая ошибку относительно триггера.

<cfquery>
DECLARE @tab table(id int);
INSERT INTO mytable (col1, col2)
OUTPUT INSERTED.my_id INTO @tab
values('val1', 'val2');
SELECT id FROM @tab;
</cfquery>

Должен ли я вообще использовать предложение OUTPUT?Когда мне нужно написать несколько предложений в одном блоке cfquery, не лучше ли мне использовать SELECT SCOPE_DENTITY ()?

Спасибо и наилучшим образом, Бернхард

Ответы [ 3 ]

2 голосов
/ 24 февраля 2012

Я думаю, это то, что вы хотите сделать:

<cfquery name="qryInsert" datasource="db" RESULT="qryResults">
   INSERT INTO mytable (col1, col2)
</cfquery>

<cfset id = qryResults.IDENTITYCOL>
1 голос
/ 24 февраля 2012

Кажется, это работает - строка вставляется, вместо триггера возвращается результат, триггер после не вмешивается, а триггер после записывается в таблицу, как и ожидалось:

CREATE TABLE dbo.x1(ID INT IDENTITY(1,1), x SYSNAME);

CREATE TABLE dbo.log_after(ID INT, x SYSNAME, 
  dt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP);
GO

CREATE TRIGGER dbo.x1_after
ON dbo.x1
AFTER INSERT
AS
BEGIN
    SET NOCOUNT ON;

    INSERT dbo.log_after(x) SELECT x FROM inserted;
END
GO

CREATE TRIGGER dbo.x1_before
ON dbo.x1
INSTEAD OF INSERT
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @tab TABLE(id INT);

    INSERT dbo.x1(x)
        OUTPUT inserted.ID INTO @tab
        SELECT x FROM inserted;

    SELECT id FROM @tab;
END
GO

Теперь, если вы напишите это в вашем cfquery, вы должны получить строку обратно в вывод. Я не разбираюсь в CF, так что я не уверен, должен ли он видеть какой-то select, чтобы знать, что он будет возвращать набор результатов (но вы можете попробовать его в Management Studio, чтобы подтвердить, что я не тяну нога):

INSERT dbo.x1(x) SELECT N'foo';

Теперь вам нужно просто переместить логику после вставки в этот триггер.

Имейте в виду, что прямо сейчас вы получите несколько строк назад (что немного отличается от единственного результата, который вы получили бы из SCOPE_IDENTITY()). Это хорошая вещь, я просто хотел указать на это.

0 голосов
/ 24 февраля 2012

Я должен признать, что впервые я видел, как кто-то использует такой объединенный подход вместо простого использования встроенного извлечения PK и разделения его на отдельные запросы к базе данных ( пример ).

...