2012-02-23 4 views
2

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

Я планировал использовать Вставки-заявление как

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

Это выдает ошибку, поскольку таблица имеет триггер, определенные, что ПОСЛЕ INSERT записывает некоторые из вставленных данных в другую таблицу, чтобы сохранить историю данных ,

Microsoft пишет:

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

Я теперь интересно, что это лучшая практика Ф.О. во-первых, получить сгенерированный идентификатор и во-вторых, «резервное копирование» вставленного данных во второй таблице.

Является ли это хорошим подходом для INSERT? Он работает, потому что значение INSERTED не просто возвращается, а записывается в временную переменную INTO. Он работает в моих тестах, как описывает 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()?

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

+0

Что вам нужно делать с '@ tab' после вставки? Просто верните «ID» в CF? Вы пытались использовать 'SCOPE_IDENTITY()' вместо 'OUTPUT'? Пробовали ли вы использовать хранимую процедуру, чтобы сделать то же самое, вместо того, чтобы набивать ad hoc SQL в 'cfquery'? –

+0

Я не использую @tab для большего, чем возврат сгенерированного идентификатора. Я не хочу много кода/для многих операторов в одном блоке CFQUERY. Если я использую 'SCOPE_IDENTITY', мне больше не нужны' DECLARE' и 'OUTPUT'. Если бы у меня была процедура, мне все равно пришлось извлекать сгенерированный идентификатор, не отключая триггер. Поэтому я предполагаю 'SELECT SCOPE_DENTITY()' это. –

+0

@Bardware - Моим первым вопросом было бы попытаться использовать атрибут ccquery ['result'] (http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7fae.html) и' result. Вместо переменной IDENTITYCOL? cfquery использует SCOPE_IDENTITY внутренне последнее, что я проверил. – Leigh

ответ

1

Это похоже на работу - строка получает вставлен, а триггер возвращает результат, то после того, как триггер не мешает, а после запуска журналов в таблице, как ожидалось :

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()). Это хорошо, я просто хотел указать на это.

2

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

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

<cfset id = qryResults.IDENTITYCOL> 
+0

Поскольку [cfquery] (http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7fae.html) поддерживает автоматическое извлечение значений идентичности, вот что я хотел бы попробовать в первую очередь. – Leigh

+0

Мне определенно нравится это лучше, если 'INSERT' всегда будет гарантированно быть одной строкой. Что, если это 'INSERT INTO mytable SELECT 1,2 UNION ALL SELECT 2,3;'? –

+0

Предложение 'OUTPUT' будет возвращать множество записей в этом случае, хорошая точка. –

0

Я должен признать, что это первый раз, когда я видел кого-то использовать слитый подход, как, что вместо того, чтобы просто с помощью встроенного поиска П.К. и разбиение его на отдельные запросы к базе данных (example).

+1

Поскольку ссылки могут прерываться со временем, вам может потребоваться обновить сообщение, чтобы включить фрагмент кода или два. – Leigh

Смежные вопросы