在MS SQL 2008中检索生成的ID

时间:2012-02-23 20:25:52

标签: sql-server-2008 coldfusion triggers

我正在将ColdFusion项目从Oracle 11转换为MS SQL 2008.我使用SSMA转换数据库,包括触发器,过程和函数。序列映射到IDENTITY列。

我计划使用像

这样的INSERT语句
INSERT INTO mytable (col1, col2)
OUTPUT INSERTED.my_id
values('val1', 'val2')

这会抛出一个错误,因为该表定义了一个触发器,AFTER INSERT会将一些INSERTED数据写入另一个表以保存数据的历史记录。

微软写道:

  

如果指定了OUTPUT子句而未指定INTO   关键字,DML操作的目标不能有任何启用   针对给定的DML操作在其上定义的触发器。例如,如果   OUTPUT子句在UPDATE语句(目标表)中定义   不能有任何启用的UPDATE触发器。   http://msdn.microsoft.com/en-us/library/ms177564.aspx

我现在想知道首先检索生成的id的最佳做法是什么,其次是在第二个表中“备份”INSERTED数据。

这是INSERT的好方法吗?它的工作原理是因为INSERTED值不是简单地返回而是写入INTO临时变量。它可以在微软描述的测试中运行,而不会引发有关触发器的错误。

<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-block中编写多个子句时,我不应该更好地使用SELECT SCOPE_DENTITY()吗?

谢谢,最好的, 哈德

3 个答案:

答案 0 :(得分:2)

我认为这就是你想要做的事情:

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

<cfset id = qryResults.IDENTITYCOL>

答案 1 :(得分: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 :(得分:0)

我必须承认,这是我第一次看到有人使用这样的合并方法而不是简单地使用内置PK检索并将其拆分为单独的数据库请求(example)。