SQL Update else插入并选择Identity,如果Insert已执行

时间:2014-02-11 13:17:12

标签: c# sql sql-server c#-4.0

我有一个SQL查询,其中我更新表记录,如果记录不存在,那么我创建一个新记录。

我的问题是,如何选择Inserted行或Updated行的Identity列?

我有以下查询:

UPDATE ProductsRoomsOrderLog 
SET OrdersID = @OrdersID, 
    RoomID = @RoomID, 
    ProductID = @ProductID, 
    ProductDocumentDate = @ProductDocumentDate, 
    CreatedBy = @CreatedBy, 
    CreatedDate = @CreatedDate 
WHERE ID = @ID 

IF @@ROWCOUNT = 0 
    INSERT INTO ProductsRoomsOrderLog 
        (OrdersID, 
         RoomID, 
         ProductID, 
         ProductDocumentDate, 
         CreatedBy, 
         CreatedDate) 
    VALUES 
        (@OrdersID, 
         @RoomID, 
         @ProductID, 
         @ProductDocumentDate, 
         @CreatedBy, 
         @CreatedDate)

然后在C#中执行查询:

SqlCommand command = new SqlCommand(statement, connection);

try
{
    connection.Open();

    foreach (ProductsRoomsOrderLog logItem in log)
    {
        //Set Created Date
        logItem.CreatedDate = createdDate;

        command.Parameters.Clear();
        if (logItem.ID == null)
        {
            command.Parameters.AddWithValue("@ID", DBNull.Value);
        }
        else
        {
            command.Parameters.AddWithValue("@ID", logItem.ID);
        }

        command.Parameters.AddWithValue("@OrdersID", logItem.OrdersID);
        command.Parameters.AddWithValue("@RoomID", logItem.RoomID);
        command.Parameters.AddWithValue("@ProductID", logItem.ProductID);

        if (logItem.ProductDocumentDate == null)
        {
            command.Parameters.AddWithValue("@ProductDocumentDate", DBNull.Value);
        }
        else
        {
            command.Parameters.AddWithValue("@ProductDocumentDate", logItem.ProductDocumentDate);
        }

        command.Parameters.AddWithValue("@CreatedBy", logItem.CreatedBy);
        command.Parameters.AddWithValue("@CreatedDate", logItem.CreatedDate);


        command.ExecuteNonQuery();

        //Get Identity column of inserted item
        string selectIdentityStatement = "SELECT IDENT_CURRENT('ProductsRoomsOrderLog') FROM ProductsRoomsOrderLog";
        SqlCommand selectIdentityCommand = new SqlCommand(selectIdentityStatement, connection);
        logItem.ID = Convert.ToInt64(selectIdentityCommand.ExecuteScalar());
    } 
}

现在请注意,我有一个获取Identity列的select Query。不幸的是,这不能正常工作,因为它总是读取我表中最后一行的标识而不是当前有问题的行(无论是更新的行还是插入的行)。简单地说,只有在插入行时才更新行。

任何人都可以告诉我如何执行更新/插入查询并选择正确的行标识?老实说,如果我要插入行,我只关心检索标识列。

非常感谢,我非常感谢您花时间阅读本文。

2 个答案:

答案 0 :(得分:1)

您必须在与INSERT相同的SQL命令中执行SELECT IDENT_CURRENT('ProductsRoomsOrderLog')

UPDATE ProductsRoomsOrderLog 
SET OrdersID = @OrdersID, 
    RoomID = @RoomID, 
    ProductID = @ProductID, 
    ProductDocumentDate = @ProductDocumentDate, 
    CreatedBy = @CreatedBy, 
    CreatedDate = @CreatedDate 
WHERE ID = @ID 

IF @@ROWCOUNT = 0 BEGIN
    INSERT INTO ProductsRoomsOrderLog 
        (OrdersID, 
         RoomID, 
         ProductID, 
         ProductDocumentDate, 
         CreatedBy, 
         CreatedDate) 
    VALUES 
        (@OrdersID, 
         @RoomID, 
         @ProductID, 
         @ProductDocumentDate, 
         @CreatedBy, 
         @CreatedDate)

    SELECT IDENT_CURRENT('ProductsRoomsOrderLog')
END

然后使用ExecuteScalar代替ExecuteNonQuery来获取结果。

command.ExecuteNonQuery();

变为

object identity = command.ExecuteScalar();  
if (identity is int)
    logItem.ID = (int)identity;

答案 1 :(得分:1)

可能会将您的查询更改为

UPDATE ProductsRoomsOrderLog 
SET OrdersID = @OrdersID, 
    RoomID = @RoomID, 
    ProductID = @ProductID, 
    ProductDocumentDate = @ProductDocumentDate, 
    CreatedBy = @CreatedBy, 
    CreatedDate = @CreatedDate 
WHERE ID = @ID 

IF @@ROWCOUNT = 0 
  BEGIN
    INSERT INTO ProductsRoomsOrderLog 
        (OrdersID, 
         RoomID, 
         ProductID, 
         ProductDocumentDate, 
         CreatedBy, 
         CreatedDate) 
    VALUES 
        (@OrdersID, 
         @RoomID, 
         @ProductID, 
         @ProductDocumentDate, 
         @CreatedBy, 
         @CreatedDate);

   SELECT IDENT_CURRENT('ProductsRoomsOrderLog') FROM ProductsRoomsOrderLog
  END
ELSE
   SELECT @ID

然后将其作为返回值的查询执行?

顺便说一句:您还可以查看SQL MERGE statement,这使得INSERT / UPDATE逻辑更加直接。