【问题标题】:Return identity of row inserted with sql stored procedure返回使用 sql 存储过程插入的行的标识
【发布时间】:2015-10-20 17:53:24
【问题描述】:

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

使用正确的值插入新行,当它返回到 .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

【问题讨论】:

  • 您如何尝试选择@@identity?除非您处于多连接环境中,否则这通常效果很好

标签: asp.net sql-server


【解决方案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 列。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      @@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; }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-07-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多