C# 存储过程合并(插入或更新)和返回ID问题

C# 存储过程合并(插入或更新)和返回ID问题,c#,stored-procedures,C#,Stored Procedures,因此,我正在尝试学习如何使用存储过程,在大多数情况下,除了这个合并过程之外,我对如何使用存储过程有些了解 我试图做的是,如果一行不存在,使用合并过程插入并返回ID;如果不存在,则返回ID 这是我目前所拥有的 CREATE PROCEDURE dbo.authors_InsertOrUpdate -- Add the parameters for the stored procedure here @FirstName nvarchar(50), @LastName nvarchar(50),

因此,我正在尝试学习如何使用存储过程,在大多数情况下,除了这个合并过程之外,我对如何使用存储过程有些了解

我试图做的是,如果一行不存在,使用合并过程插入并返回ID;如果不存在,则返回ID

这是我目前所拥有的

CREATE PROCEDURE dbo.authors_InsertOrUpdate
-- Add the parameters for the stored procedure here
@FirstName nvarchar(50), 
@LastName nvarchar(50),
@id int = NULL OUTPUT
AS
MERGE Authors AS target
USING (SELECT @FirstName, @LastName) AS source (FirstName, LastName)
ON target.FirstName = source.FirstName AND target.LastName = source.LastName
WHEN MATCHED THEN
    UPDATE 
    SET @id = SCOPE_IDENTITY()
WHEN NOT MATCHED THEN INSERT 
    (FirstName, LastName) VALUES (source.FirstName, source.LastName);
    SET @id = SCOPE_IDENTITY()
只要将值/信息输入数据库并找到一个现有值,一切都正常,但我没有正确地获取ID值。这是我使用它的方法

private static int storeAuthors(string firstName, string lastName)
        {
            String commandText = "dbo.authors_InsertOrUpdate";
            using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["AmazonCrawler.Properties.Settings.database"].ToString()))
            {
                using (SqlCommand command = new SqlCommand(commandText, connection))
                {
                    command.CommandType = CommandType.StoredProcedure;
                    command.Parameters.Add(new SqlParameter("@FirstName", firstName));
                    command.Parameters.Add(new SqlParameter("@LastName", lastName));
                    SqlParameter authorId = new SqlParameter("@id", SqlDbType.Int);
                    authorId.Direction = ParameterDirection.Output;
                    command.Parameters.Add(authorId);

                    connection.Open();
                    command.ExecuteNonQuery();
                    connection.Close();

                    return Convert.ToInt32(authorId.Value);
                }
            }
        }
请帮我修好这个

提前谢谢

---------编辑------------

将过程更新为此,但当我尝试返回值时,代码中仍然收到空值

CREATE PROCEDURE dbo.authors_InsertOrUpdate
    -- Add the parameters for the stored procedure here
    @FirstName nvarchar(50), 
    @LastName nvarchar(50),
    @id int OUTPUT
AS
MERGE Authors AS target
USING (SELECT @id, @FirstName, @LastName) AS source (id, FirstName, LastName)
ON target.FirstName = source.FirstName AND target.LastName = source.LastName
WHEN NOT MATCHED THEN 
    INSERT (FirstName, LastName) VALUES (source.FirstName, source.LastName);
    SET @id = SCOPE_IDENTITY()
编辑参考文献1

编辑参考文献2

编辑参考文献3

ALTER PROCEDURE dbo.authors_InsertOrUpdate
    -- Add the parameters for the stored procedure here
    @FirstName nvarchar(50), 
    @LastName nvarchar(50),
    @id int OUTPUT

AS
MERGE Authors AS target
USING (SELECT @id, @FirstName, @LastName) AS source (ID, FirstName, LastName)
ON target.FirstName = source.FirstName AND target.LastName = source.LastName
WHEN MATCHED THEN 
    UPDATE SET @id = target.ID
WHEN NOT MATCHED THEN 
    INSERT (FirstName, LastName) VALUES (source.FirstName, source.LastName);
    SET @id = SCOPE_IDENTITY()

SELECT @id
仍然收到参考文献2中列出的相同错误。 =(还没有解决方案

这是我传入的值,返回的id为零

这是我的数据库

编辑参考文献4

在将值输入到该值时尝试更改参数,因为我认为在获取值之前关闭它可能会导致问题,但运气不佳

private static int storeAuthors(string firstName, string lastName)
        {
            String commandText = "dbo.authors_InsertOrUpdate";
            using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["AmazonCrawler.Properties.Settings.database"].ToString()))
            {
                using (SqlCommand command = new SqlCommand(commandText, connection))
                {
                    command.CommandType = CommandType.StoredProcedure;
                    command.Parameters.Add(new SqlParameter("@FirstName", firstName));
                    command.Parameters.Add(new SqlParameter("@LastName", lastName));
                    SqlParameter authorId = new SqlParameter("@id", SqlDbType.Int);
                    authorId.Direction = ParameterDirection.Output;
                    command.Parameters.Add(authorId);

                    connection.Open();
                    command.ExecuteNonQuery();
                    int value = Convert.ToInt32(authorId.Value);
                    connection.Close();

                    return value;
                }
            }
        }

在更新案例中,您没有生成新标识,您只是在查询,因此SCOPE_IDENTITY()不会返回正确的值。在更新案例中,SCOPE_IDENTITY()一开始可能看起来有效,但它实际上返回了SCOPE中最后一次插入(我认为)的值,这可能是存储过程的最后一次执行

我建议使用OUTPUT子句。我尝试使用您的方法和@usr的建议使某些东西起作用,但我唯一能起作用的是使用OUTPUT子句。请参见以下内容:

CREATE PROCEDURE dbo.authors_InsertOrUpdate
    -- Add the parameters for the stored procedure here
    @FirstName nvarchar(50), 
    @LastName nvarchar(50),
    @id int OUTPUT
AS BEGIN
   DECLARE @MergeOutput table
   ( 
     ACTION VARCHAR(10),
     ID INT
   );

   MERGE Authors AS target
     USING (SELECT @id, @FirstName, @LastName) AS source (id, FirstName, LastName)
       ON target.FirstName = source.FirstName AND target.LastName = source.LastName
     WHEN NOT MATCHED THEN
       INSERT (FirstName, LastName) VALUES (source.FirstName, source.LastName)
     WHEN MATCHED THEN UPDATE
       SET @Id = target.Id
     OUTPUT $action, INSERTED.ID INTO @MergeOutput;

   SELECT @Id = Id FROM @MergeOutput

END
GO

DECLARE @id2 INT
exec dbo.authors_InsertOrUpdate 'Melvin', 'Smith', @id = @id2 OUTPUT
SELECT @id2
GO

我尝试使用SCOPE_IDENTITY()和@usr的答案中的SET@Id=target.Id使某些功能正常工作,但我一直得到返回的最后一个插入值,即使对于更新也是如此。

在更新的情况下,您并没有生成新的标识,您只是在查询,所以SCOPE_IDENTITY()不会返回正确的值。在更新的情况下,SCOPE_IDENTITY()一开始可能看起来有效,但它实际上返回了SCOPE中最后一次插入的值(我认为),这可能是存储过程的最后一次执行

SELECT * INTO #o FROM sys.objects

DECLARE @id INT

MERGE #o AS target
USING (SELECT OBJECT_ID('tempdb..#o') AS object_id) AS source (object_id)
ON target.object_id = source.object_id
WHEN MATCHED THEN UPDATE SET @id = target.object_id;

SELECT @id
我建议使用OUTPUT子句。我尝试使用您的方法和@usr的建议使某些东西起作用,但我唯一能起作用的是使用OUTPUT子句。请参见以下内容:

CREATE PROCEDURE dbo.authors_InsertOrUpdate
    -- Add the parameters for the stored procedure here
    @FirstName nvarchar(50), 
    @LastName nvarchar(50),
    @id int OUTPUT
AS BEGIN
   DECLARE @MergeOutput table
   ( 
     ACTION VARCHAR(10),
     ID INT
   );

   MERGE Authors AS target
     USING (SELECT @id, @FirstName, @LastName) AS source (id, FirstName, LastName)
       ON target.FirstName = source.FirstName AND target.LastName = source.LastName
     WHEN NOT MATCHED THEN
       INSERT (FirstName, LastName) VALUES (source.FirstName, source.LastName)
     WHEN MATCHED THEN UPDATE
       SET @Id = target.Id
     OUTPUT $action, INSERTED.ID INTO @MergeOutput;

   SELECT @Id = Id FROM @MergeOutput

END
GO

DECLARE @id2 INT
exec dbo.authors_InsertOrUpdate 'Melvin', 'Smith', @id = @id2 OUTPUT
SELECT @id2
GO

我尝试使用SCOPE_IDENTITY()和@usr的答案中的SET@Id=target.Id使某些功能正常工作,但我一直得到返回的最后一个插入值,即使对于更新也是如此。

在更新的情况下,您并没有生成新的标识,您只是在查询,所以SCOPE_IDENTITY()不会返回正确的值。在更新的情况下,SCOPE_IDENTITY()一开始可能看起来有效,但它实际上返回了SCOPE中最后一次插入的值(我认为),这可能是存储过程的最后一次执行

SELECT * INTO #o FROM sys.objects

DECLARE @id INT

MERGE #o AS target
USING (SELECT OBJECT_ID('tempdb..#o') AS object_id) AS source (object_id)
ON target.object_id = source.object_id
WHEN MATCHED THEN UPDATE SET @id = target.object_id;

SELECT @id
我建议使用OUTPUT子句。我尝试使用您的方法和@usr的建议使某些东西起作用,但我唯一能起作用的是使用OUTPUT子句。请参见以下内容:

CREATE PROCEDURE dbo.authors_InsertOrUpdate
    -- Add the parameters for the stored procedure here
    @FirstName nvarchar(50), 
    @LastName nvarchar(50),
    @id int OUTPUT
AS BEGIN
   DECLARE @MergeOutput table
   ( 
     ACTION VARCHAR(10),
     ID INT
   );

   MERGE Authors AS target
     USING (SELECT @id, @FirstName, @LastName) AS source (id, FirstName, LastName)
       ON target.FirstName = source.FirstName AND target.LastName = source.LastName
     WHEN NOT MATCHED THEN
       INSERT (FirstName, LastName) VALUES (source.FirstName, source.LastName)
     WHEN MATCHED THEN UPDATE
       SET @Id = target.Id
     OUTPUT $action, INSERTED.ID INTO @MergeOutput;

   SELECT @Id = Id FROM @MergeOutput

END
GO

DECLARE @id2 INT
exec dbo.authors_InsertOrUpdate 'Melvin', 'Smith', @id = @id2 OUTPUT
SELECT @id2
GO

我尝试使用SCOPE_IDENTITY()和@usr的答案中的SET@Id=target.Id使某些功能正常工作,但我一直得到返回的最后一个插入值,即使对于更新也是如此。

在更新的情况下,您并没有生成新的标识,您只是在查询,所以SCOPE_IDENTITY()不会返回正确的值。在更新的情况下,SCOPE_IDENTITY()一开始可能看起来有效,但它实际上返回了SCOPE中最后一次插入的值(我认为),这可能是存储过程的最后一次执行

SELECT * INTO #o FROM sys.objects

DECLARE @id INT

MERGE #o AS target
USING (SELECT OBJECT_ID('tempdb..#o') AS object_id) AS source (object_id)
ON target.object_id = source.object_id
WHEN MATCHED THEN UPDATE SET @id = target.object_id;

SELECT @id
我建议使用OUTPUT子句。我尝试使用您的方法和@usr的建议使某些东西起作用,但我唯一能起作用的是使用OUTPUT子句。请参见以下内容:

CREATE PROCEDURE dbo.authors_InsertOrUpdate
    -- Add the parameters for the stored procedure here
    @FirstName nvarchar(50), 
    @LastName nvarchar(50),
    @id int OUTPUT
AS BEGIN
   DECLARE @MergeOutput table
   ( 
     ACTION VARCHAR(10),
     ID INT
   );

   MERGE Authors AS target
     USING (SELECT @id, @FirstName, @LastName) AS source (id, FirstName, LastName)
       ON target.FirstName = source.FirstName AND target.LastName = source.LastName
     WHEN NOT MATCHED THEN
       INSERT (FirstName, LastName) VALUES (source.FirstName, source.LastName)
     WHEN MATCHED THEN UPDATE
       SET @Id = target.Id
     OUTPUT $action, INSERTED.ID INTO @MergeOutput;

   SELECT @Id = Id FROM @MergeOutput

END
GO

DECLARE @id2 INT
exec dbo.authors_InsertOrUpdate 'Melvin', 'Smith', @id = @id2 OUTPUT
SELECT @id2
GO
我试图使用SCOPE_IDENTITY()和@usr的答案中的SET@Id=target.Id使某些东西起作用,但我一直得到返回的最后一个插入值,即使对于更新也是如此

SELECT * INTO #o FROM sys.objects

DECLARE @id INT

MERGE #o AS target
USING (SELECT OBJECT_ID('tempdb..#o') AS object_id) AS source (object_id)
ON target.object_id = source.object_id
WHEN MATCHED THEN UPDATE SET @id = target.object_id;

SELECT @id
您可以非常自由地使用
MERGE
查询的列。这是一个非常强大的语句

您可以非常自由地使用
MERGE
查询的列。这是一个非常强大的语句

您可以非常自由地使用
MERGE
查询的列。这是一个非常强大的语句



您可以非常自由地使用
MERGE
查询的列。这是一个非常强大的语句。

在更新案例中,您使用的是
SCOPE\u IDENTITY()
这似乎是一个c&p错误。当我尝试运行它时,进行了更改,但代码中仍然接收到空值。您做了什么更改?我没有提出任何建议。那么,您对该更改有何期望?您刚刚删除了更新案例。因此,在更新的情况下,什么都不会发生。到目前为止,我尝试使用just when MATCHED然后设置@Id=target.ID,但这给了我一个不正确的语法这似乎是一个c&p错误。当我尝试运行它时,进行了更改,但代码中仍然接收到空值。您做了什么更改?我没有提出任何建议。那么,您对该更改有何期望?您刚刚删除了更新案例。因此,在更新的情况下,什么都不会发生。到目前为止,我尝试使用just when MATCHED然后设置@Id=target.ID,但这给了我一个不正确的语法这似乎是一个c&p错误。当我尝试运行它时,进行了更改,但代码中仍然接收到空值。您做了什么更改?我没有提出任何建议。那么,您对该更改有何期望?您刚刚删除了更新案例。因此,在更新的情况下,什么都不会发生。到目前为止,我尝试使用just when MATCHED然后设置@Id=target.ID,但这给了我一个不正确的语法