在SQL INSERT命令期间/之后返回标识列的值

时间:2010-04-08 03:20:10

标签: c# .net sql-server

使用VS 2010,ASP.NET,.NET 3.0和C#...

当我使用System.Web.UI.WebControls.SqlDataSource并调用其Insert()方法插入一个新行,并且该表有一个标识列时,我希望我的方法返回该列的值

例如,在我的SQL 2005表中,我有:

  • Customer.Id
  • Customer.FirstName
  • Customer.LastName

Customer.Id是身份列。

当我调用我的方法InsertNewCustomerRecord(“John”,“Smith”)时,我希望能够返回在数据库中自动生成的Customer.Id。

很抱歉这个粗略提出的问题。如果我能添加更好的细节,请告诉我。感谢。

3 个答案:

答案 0 :(得分:5)

如果您使用的是SQL Server 2005或更高版本,则可以使用OUTPUT子句在单个语句中执行此操作:

Create Table Foo    (
                    Id int not null identity(1,1)
                    , Name varchar(50) null
                    , ....
                    )

Insert Foo(Name)
    Output inserted.Id, inserted.Name
Select 'Foo'
Union All Select 'Bar'
....

如果您使用的是SQL Server 2000,则应使用SCOPE_IDENTITY,如下所示:

Insert Foo(Name)
Select 'Foo'

Select SCOPE_IDENTITY()

请注意,我只能使用此方法一次执行一次插入,因为我们想在Insert语句后立即调用SCOPE_IDENTITY

如果您使用的是SQL Server 2000之前的版本,则需要使用@@IDENTITY

Insert Foo(Name)
Select 'Foo'

Select @@Identity

问题是,如果桌面上有触发器,@@ Identity会做一些时髦的事情。

编辑您询问了如何在C#中使用此信息。您可以像调用SELECT查询一样使用它:

var connString = ConfigurationManager.ConnectionStrings["MyConnectionStringName"].ConnectionString;
DataTable newData;

using ( var conn = new SqlConnection( connString ) )
{
    conn.Open();
    const string sql = "Insert Foo(Name) Output inserted.Id, inserted.Name Values(@Name)";
    using ( var cmd = new SqlCommand( sql, conn ) )
    {
        cmd.Parameters.AddWithValue("@Name", "bar");
        using ( var da = new SqlDataAdapter( cmd ) )
        {
            da.Fill( newData );
        }
    }
}

这里我假设您的配置文件中有MyConnectionStringName的connectionStrings条目。此外,您需要添加对System.Configuration的引用才能使用ConfigurationMananager类。我没有检查这段代码,但它应该非常接近你需要的。在这种情况下,我正在直接编写查询。还有其他解决方案,例如使用DataSource控件并设置SelectCommand

答案 1 :(得分:3)

我宁愿选择SCOPE_IDENTITY (Transact-SQL)

  

SCOPE_IDENTITY和@@ IDENTITY返回   最后的标识值   在当前的任何表中生成   会话。但是,SCOPE_IDENTITY   返回仅在其中插入的值   目前的范围; @@ IDENTITY不是   仅限于特定范围。

请注意,@@ IDENTITY可能无法返回您期望的内容

  

例如,有两个表,T1   和T2,以及INSERT触发器   在T1上定义。插入行时   到T1,触发器触发并插入一个   排在T2。这个场景说明了   两个范围:T1上的插入和   通过触发器在T2上插入。

     

假设T1和T2都有   身份栏,@ @ IDENTITY和   SCOPE_IDENTITY将返回不同的内容   INSERT末尾的值   关于T1的声明。 @@ IDENTITY会   返回最后一个标识列值   插入到任何范围内   本届会议。这是价值   插入T2。 SCOPE_IDENTITY()会   返回插入的IDENTITY值   T1。这是最后一次插入   发生在同一范围内。该   SCOPE_IDENTITY()函数将返回   如果函数是null值   在任何INSERT语句之前调用   进入一个标识列出现在   范围。

答案 2 :(得分:1)

Insert方法使用InsertCommand属性...

因此将InsertCommand修改为

INSERT Mytable (col1, col2) VALUES (@param1, @parame);SELECT SCOPE_IDENTITY();

或(对于SQL Server 2005 +)

INSERT Mytable (col1, col2) OUTPUT INSERTED.IDCol VALUES (@param1, @param2);