2015-11-03 138 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。 。 。这可能是我,但我几乎从未发现“合并”更容易阅读。 –

相关问题