2013-03-04 68 views
0

我試圖從一個存儲過程得到插入或更新的ID,我嘗試兩種不同的方式的Upsert返回ID

我不能使用使用If exists(select ....)性能原因

1 OUTPUT

@firstName varchar(30), 
    @Telephone int 

     AS 
     BEGIN transaction 
      UPDATE [PHONE_BOOK].[dbo].[USER] 
         SET TELEPHONE= @Telephone 
         output inserted.USERID 
        where FIRST_NAME = @firstName 

    if @@ROWCOUNT = 0 
    begin 
      INSERT INTO [PHONE_BOOK].[dbo].[USER] 
      ([FIRST_NAME] 
      ,[TELEPHONE]) 
      output inserted.USERID -- or output SCOPE_IDENTITY() 
    VALUES 
      (@firstName 
      ,@Telephone) 
    end 

C#代碼

IList<SqlParameter> parameters = new List<SqlParameter>(); 
      parameters.Add(new SqlParameter("@firstName", "Mike")); 
      parameters.Add(new SqlParameter("@Telephone", 9514256)); 

      using (var sqlConnection = new SqlConnection(Config.ConnString)) 
      { 
       sqlConnection.Open(); 
       using (SqlCommand command = sqlConnection.CreateCommand()) 
       { 
        command.CommandType = CommandType.StoredProcedure; 
        command.CommandText = "[dbo].[INSET_USER]"; 
        command.UpdatedRowSource = UpdateRowSource.None; 

        foreach (SqlParameter oPar in parameters) 
         command.Parameters.Add(oPar); 

        object x = command.ExecuteScalar(); 

       } 
      } 
  1. 在更新的情況下==>x是正確
  2. 在刪除==時>x爲空使用OUTPUT參數

2-

@firstName varchar(30), 
@Telephone int, 
@userId int output 

AS 
BEGIN transaction 
    UPDATE [PHONE_BOOK].[dbo].[USER] 
       SET TELEPHONE= @Telephone 
      where FIRST_NAME = @firstName 
      -- i can't find different way to set @userId than doing a select which is not acceptable 
    if @@ROWCOUNT = 0 
    begin 
      INSERT INTO [PHONE_BOOK].[dbo].[USER] 
      ([FIRST_NAME] 
      ,[TELEPHONE]) 
    VALUES 
      (@firstName 
      ,@Telephone) 
      set @userId = SCOPE_IDENTITY() 
     end 

C#代碼:

IList<SqlParameter> parameters = new List<SqlParameter>(); 
      parameters.Add(new SqlParameter("@firstName", "Mike")); 
      parameters.Add(new SqlParameter("@Telephone", 9514256)); 

      using (var sqlConnection = new SqlConnection(Config.ConnString)) 
      { 
       sqlConnection.Open(); 
       using (SqlCommand command = sqlConnection.CreateCommand()) 
       { 
        command.CommandType = CommandType.StoredProcedure; 
        command.CommandText = "[dbo].[INSET_USER]"; 
        command.UpdatedRowSource = UpdateRowSource.None; 

        foreach (SqlParameter oPar in parameters) 
         command.Parameters.Add(oPar); 
        command.Parameters.Add("@userId",0).Direction = ParameterDirection.Output; 

        command.ExecuteNonQuery(); 
        var x = command.Parameters["@userId"].Value; 

       } 
      } 
  1. 在更新==>x的情況下是-1
  2. 在刪除==時>x是正確的

我怎樣才能解決這一問題?由於我不需要將輸出參​​數傳遞給存儲過程,因此我不需要將輸出參​​數傳遞給存儲過程

+1

如何使存儲過程中的ID爲OUTPUT參數? – Melanie 2013-03-04 22:06:34

+0

然後在我的C#代碼中,我必須傳遞一個ID值?如果是的話,我必須通過什麼價值?另外如果我傳遞id作爲參數,那麼在更新的情況下,然後我必須調用select來將id分配給我想要避免的更新值 – Maro 2013-03-04 22:09:38

+0

您是否正在查找更新中影響的行數? – 2013-03-04 22:12:16

回答

0

你沒有得到在這種情況下,你的輸出值的原因是因爲你*選擇*荷蘭國際集團它,而不是*回報*荷蘭國際集團它。如果你不想改變你的proc,你可以從第一個結果集中選擇它 - 但是ExecuteScalar會抑制結果集,所以你需要使用ExecuteReader或類似的東西。然而,這是一個標準模式,你沒有遵循它,所以我會發布它只是爲了好 - 我相信它已被覆蓋其他地方雖然。

標準SP模式 -

create proc UpsertMyTable (
    @parameter int 
) AS 

declare @result int 

if exists (select 1 from MyTable where value = @parameter) begin 
    UPDATE HERE 
end else begin 
    INSERT HERE 
end 

set @result = SCOPE_IDENTITY() 

return @result 

,然後在C#代碼,基本上是你在你的例子是,除非你已經做了參數的方法正確是多餘的,性能問題...

using (var sqlConnection = new SqlConnection(Config.ConnString)) { 
    sqlConnection.Open(); 
    using (SqlCommand command = sqlConnection.CreateCommand()) { 
     command.CommandType = CommandType.StoredProcedure; 
     command.CommandText = "[dbo].[PROC_UPSERT_SHARE]"; 
     command.UpdatedRowSource = UpdateRowSource.None; 

     command.parameters.Add(new SqlParameter("@fullName", "dwfae")); 
     command.parameters.Add(new SqlParameter("@name", "aze")); 
     command.parameters.Add(new SqlParameter("@root", "aze")); 
     command.parameters.Add(new SqlParameter("@creationDate", new DateTime(2000, 10, 10))); 
     command.parameters.Add(new SqlParameter("@lastAccessDate", new DateTime(1999, 11, 11))); 
     command.parameters.Add(new SqlParameter("@lastWriteDate", new DateTime(1990,12,12))); 
     command.parameters.Add(new SqlParameter("@subShareCount", 20)); 
     command.parameters.Add(new SqlParameter("@serverId", "serverx")); 

     object x = command.ExecuteScalar(); 
     Console.WriteLine(x); 
    } 
} 

這樣的事情會快得多。即使您認爲影響可能很小,請考慮這類事情。

+0

正如我在文章中提到,我不想進行選擇「如果選擇」是不是因爲性能原因接受 我要去簡化我的問題, – Maro 2013-03-04 23:15:18

+0

這是可以接受的。如果EXISTS是正確的做法。想一想......比IF EXISTS更快或更慢的失敗更新?你想,以及有時更新將工作,這是更快,如果你的應用程序做了很多更新和小插入的,你可能會看到一個略有改善,但如果EXISTS是相當快的,而且大多數應用程序中插入的方式比他們更更新。是的,發回一個返回參數的網絡數據少於發送帶有一列和一行的結果集的網絡數據。 – Jasmine 2013-03-04 23:38:15

+0

好吧,請嘗試以下,你會明白我的意思 創建一個表有10萬的記錄。然後嘗試插入/使用if(選擇)更新一個記錄和查詢性能 select語句會降低性能 – Maro 2013-03-04 23:51:31