返回用sql存储过程插入的行的标识

时间:2015-10-20 09:11:45

标签: asp.net sql-server

我正在处理一个遗留项目,需要插入一行并返回该行或它的标识。

使用正确的值插入新行,当数据集返回.net时,数据集中不会返回任何内容。

我已尝试选择@@identityRETURNOUTPUT,但我尝试的所有数据集都是空的(但不是空的)。

这不是MyUtils.DBHelper.GetDataSet的错误,因为它在其他地方使用并执行并返回ok。

USE [dbname]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER Procedure [dbo].[DuplicateOrder]
(
    @sourceid int,
    @var1 int,
    @var2 decimal(10,2),
)
AS

INSERT INTO OrderHeader (
    Users_ID,
    Stores_ID,
    )
SELECT 
    @var1,
    @var2
FROM Order
WHERE id = @sourceid
GO

我用来执行存储过程的代码是:

Using cmd As New SqlCommand("DuplicateOrder") With {.CommandType = CommandType.StoredProcedure}
                    cmd.Parameters.AddWithValue("@sourceid", sourceId)
                    cmd.Parameters.AddWithValue("@var1 ", var1 )
                    cmd.Parameters.AddWithValue("@var2 ", var2 )
                    ds = MyUtils.DBHelper.GetDataSet(cmd)
End Using

3 个答案:

答案 0 :(得分:1)

这应该可以解决问题:

ALTER Procedure [dbo].[DuplicateOrder]
(
    @sourceid int,
    @var1 int,
    @var2 decimal(10,2)
)
AS

INSERT INTO OrderHeader (
    Users_ID,
    Stores_ID
    )
SELECT 
    @var1,
    @var2

SELECT @@IDENTITY AS ident
GO

我在SQL服务器上测试了它,它返回了一行ident

答案 1 :(得分:0)

您是否尝试过执行此SELECT IDENT_CURRENT ('Table') AS Current_Identity;它应该返回当前会话和范围中最后生成的标识

答案 2 :(得分:0)

@@ identity和return不会工作(如果你打算一次插入多行,SCOPE_IDENT(),IDENT_CURRENT()也不会工作)。

您最好的选择是使用OUTPUT,但我在代码中看不到任何OUTPUT。下面是一个示例(代码部分在C#中,但您可以轻松转换它,比如使用Telerik转换器或自己编写 - 有N种方式传递数据,我在此示例中选择了XML):

生成示例表和过程的SQL代码:

USE [Test];
GO

CREATE TABLE IdentityTest
  (
    Id INT IDENTITY
           NOT NULL
           PRIMARY KEY ,
    FirstName VARCHAR(20) ,
    LastName VARCHAR(20)
  );
GO

CREATE PROCEDURE InsertTestData
  (
    @XML VARCHAR(MAX) ,
    @NodeName VARCHAR(1000)
  )
AS
  BEGIN

    DECLARE @myIDTable TABLE ( theID INT );

    DECLARE @hDoc INT;
    DECLARE @tbl TABLE
      (
        fName VARCHAR(20) ,
        lName VARCHAR(20)
      );
    EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML;
    INSERT  @tbl
    SELECT  *
    FROM    OPENXML(@hDoc, @NodeName, 1) WITH (fName VARCHAR(20), lName VARCHAR(20));
    EXEC sp_xml_removedocument @hDoc;

    INSERT  INTO [IdentityTest] ( [FirstName], [LastName] )
    OUTPUT  [Inserted].[Id]
            INTO @myIDTable
    SELECT  t.[fName], t.[lName]
    FROM    @tbl AS t;

    SELECT  *
    FROM    @myIDTable AS [mit];

  END;
GO

这是使用SP并插入多行并获取其ID的C#代码(可能已返回完整的行数据):

void Main()
{
  List<Person> people = new List<Person> {
    new Person { FName = "Sam", LName="Jones"},
    new Person { FName = "Cetin", LName="Basoz"},
    new Person { FName = "John", LName="Doe"},
    new Person { FName = "Steven", LName="Smith"},
    new Person { FName = "Bob", LName="Carpenter"},
  };

  for (int i = 0; i < 100; i++)
  {
    people.Add(new Person
    {
      FName = string.Format("FName#{0}", i),
      LName = string.Format("LName#{0}", i)
    });
  }

  var peopleAsXML = new XElement("People",
     from p in people
     select new XElement("Person",
       new XAttribute("fName", p.FName),
       new XAttribute("lName", p.LName)));

  string sql = @"InsertTestData";
  DataTable result = new DataTable();
  using (SqlConnection con = new SqlConnection(@"server=.\SQLExpress2012;Trusted_Connection=yes;Database=Test"))
  {
    SqlCommand cmd = new SqlCommand(sql, con);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@XML", peopleAsXML.ToString());
    cmd.Parameters.AddWithValue("@NodeName", "/People/Person");
    con.Open();
    result.Load(cmd.ExecuteReader());
    con.Close();
  }
  // check top 5 returned
  for (int i = 0; i < 5; i++)
  {
    Console.WriteLine((int)result.Rows[i]["theID"]);
  }
}

public class Person
{
  public string FName { get; set; }
  public string LName { get; set; }
}