2015-11-03 44 views
3

問:SQL Server存儲過程 - 檢查是否有任何記錄存在,然後插入如果不是

是否可以發送到SQL Server 2012的單呼,用一段時間指定了一個數組,使數據庫服務器可以檢查這些元素是否存在,如果不存在,將它們插入表中?

問題:

我面臨的問題是,我有一個計劃作業(調用API),返回大約400每次調用時間記錄。這項工作每分鐘都會被調用,而最慢的是,對於每個結果,我正在檢查數據庫是否已經有記錄,如果沒有,那麼我正在執行INSERT。

示例:API返回400人。我希望能夠在一次調用中將每個人的ID以及姓名等發送給數據庫。然後數據庫應該檢查並查看ID是否存在(對於每個人),如果不存在,則執行INSERT。

反饋:

我也想在此是否真的是很好的做法的建議,或有處理這更好的方式。

+0

有沒有可能是許多這樣的調用會同時擊中分貝?如果沒有,那麼你應該將它們加載到暫存表中並運行某種「MERGE」。如果你將有多個調用(意味着你不能使用單個表,因爲它們會覆蓋對方),那麼請看「將數組傳遞給存儲過程」 - http://stackoverflow.com/questions/11102358/how-to -pass-an-array-into-a-sql-server-stored-procedure –

回答

3

按我的理解,這項工作的結果返回給應用程序(C#),那麼這個應用程序在調用數據庫的每個記錄。

答案是肯定的,你可以在一個補丁中發送多個記錄(數據表)到sql服務器,然後sql服務器將處理所有這些數據。

首先在SQL Server中,您必須定義將從應用程序發送到數據庫的格式的表格數據類型。

CREATE TYPE YourDataType AS TABLE(
    [Col1] [int] NULL,    [Col2] [int] NULL,     [Col3] [int] NULL,    [Col4] [nvarchar](255) NULL, 
    [Col5] [nvarchar](255) NULL, [Col6] [nvarchar](255) NULL,  [Col7] [nvarchar](255) NULL, [Col8] [nvarchar](255) NULL, 
    [Col9] [nvarchar](255) NULL, [Col10] [nvarchar](255) NULL,  [Col11] [int] NULL,    [Col12] [nvarchar](255) NULL, 
) 
GO 

然後創建將使用此數據類型

CREATE PROCEDURE YourProcedureName (@TableVariable YourDataType READONLY, @ScalarParameter nvarchar(255)) 
AS 

BEGIN 
INSERT INTO YourTable WITH (ROWLOCK) (Col1,Col2,Col3,Col4,Col5,Col6,Col7,Col8,Col9,Col10,Col11,Col12) 

    SELECT Col1,Col2,Col3,Col4,Col5,Col6,Col7,Col8,Col9,Col10,Col11,Col12 

    FROM @TableVariable t 
     /*Left Join then where ID is null to make sure the record doesn't exists*/ 
     LEFT JOIN YourTable PR WITH (NOLOCK) 
           ON PR.ID = @ScalarParameter 
           AND PR.Col1 = t.Col1  
           AND PR.Col2 = t.Col2 
           ...... 
     WHERE PR.ID IS NULL 
END 

最後使用您的數據應用程序中調用這個程序你的程序。 在這裏,我寫的使用VB.Net,但你可以在C#重寫一遍:

Dim connectionString As StringBuilder = New StringBuilder() 
    connectionString.AppendFormat("Server={0};", ????) 
    connectionString.AppendFormat("Database={0};", ???) 
    connectionString.AppendFormat("User ID={0};", ????) 
    connectionString.AppendFormat("Password={0}", ????) 

    Dim InputTable As DataTable = New DataTable("YourDataType") 
    InputTable = ds.Tables(0).Copy() 
    InputTable.TableName = "YourDataType" 

    Try 
     Using conn As New SqlClient.SqlConnection(connectionString.ToString()) 
      Using comm As New SqlClient.SqlCommand() 
       Dim insertedRecords As Int32 

       comm.Connection = conn 
       comm.CommandText = "YourProcedureName" 
       comm.CommandType = CommandType.StoredProcedure 
       Dim TableVariable As SqlClient.SqlParameter = comm.Parameters.Add("@TableVariable", SqlDbType.Structured) 
       TableVariable.Direction = ParameterDirection.Input 
       TableVariable.Value = InputTable 
       Dim ScalarVariable As SqlClient.SqlParameter = comm.Parameters.Add(@ScalarParameter, SqlDbType.VarChar) 
       ScalarVariable.Direction = ParameterDirection.Input 
       ScalarVariable.Value = ??? 

       conn.Open() 
       insertedRecords = comm.ExecuteNonQuery() 
       If (insertedRecords > 0) Then 
        _Changed = True 
       End If 
       conn.Close() 

       comm.Dispose() 
       conn.Dispose() 
      End Using 
     End Using 
    Catch ex As Exception 
     Return False 
    End Try 
    Return True 
+0

你自己先生也不甘示弱。謝謝! – blgrnboy

+0

在創建過程時,SQL Management Studio在第一行出現錯誤,指出「CREATE PROCEDURE必須是批處理中唯一的語句」。這是否有特定的順序? – blgrnboy

+0

@blgrnboy:在它之前和之後寫入 –

2

您需要一種方法來確定記錄是否已在表格中。這需要進行某種比較。

一旦你有,你可以構造這樣的查詢:

insert into t(. . .) 
    select v.* 
    from values ((v1), (v2), . . .) as v(vcol) 
    where not exists (select 1 from v where v.vcol = t.<whatever>); 
+0

可能合併會更富有表現力,如果存在則使用密鑰 MERGE INTO test AS trg USING(VALUES(@ v1), (@ v3))AS src(Newt) ON trg.t = src.Newt WHEN NOT MATCHED THEN INSERT(t)VALUES(NewT);' – vitalygolub

+0

@vitalygolub。 。 。這可能是我,但我幾乎從未發現「合併」更容易閱讀。 –

相關問題