簡體   English   中英

如何在存儲過程的WHERE子句中使用類型數據表

[英]How to use a type datatable in WHERE clause of a stored procedure

基本上,我有一個C#應用程序,它將創建一個數據表並將該數據表作為存儲過程傳遞。 一切都可以,但是; 我想做的是向傳入的數據表添加邏輯。

例如,在下面的測試中,您將看到一個名為RealInsertNewRecords的過程; 這個試圖確保不會發生重復的主鍵沖突,但是我得到了錯誤

必須聲明標量變量“ @dataTable”

以下是一個完整的測試,感謝您的幫助。 謝謝!

澄清存儲過程RealInsertNewRecords是行不通的

C#

using System;
using System.Data;
using System.Data.SqlClient;

namespace testApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string SQLServer = @"";
            SqlConnection sqlCon = new SqlConnection("Data Source=" + SQLServer + ";Initial Catalog=myTestDB;Integrated Security=SSPI;");

            sqlCon.Open();
            InsertNewRecords(sqlCon, testTable1());
            InsertNewRecords(sqlCon, testTable2());
            sqlCon.Dispose();
        }

        public static DataTable testTable1()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("myTestPK");

            string[] items = new string[] { "apples", "pears" };

            for (int i = 0; i < items.Length; i++)
            {
                DataRow dr = dt.NewRow();
                dr[0] = items[i];
                dt.Rows.Add(dr);
            }

            return dt;
        }

        public static DataTable testTable2()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("myTestPK");

            string[] items = new string[] { "apples", "pears", "grapes" };

            for (int i = 0; i < items.Length; i++)
            {
                DataRow dr = dt.NewRow();
                dr[0] = items[i];
                dt.Rows.Add(dr);
            }

            return dt;
        }

        public static void InsertNewRecords(SqlConnection sqlCon, DataTable parameterTable)
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "InsertNewRecords";
            cmd.Parameters.AddWithValue("dataTable", parameterTable);
            cmd.Connection = sqlCon;
            cmd.CommandType = CommandType.StoredProcedure;

            cmd.ExecuteNonQuery();
        }
    }
}

的SQL

if exists (select 'x' from sys.databases where [name] = 'myTestDB')
begin
     drop database myTestDB;
end

Create database myTestDB;
GO

USE [myTestDB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[myTable]
(
    [myTestPK] [nvarchar](50) NOT NULL,

    CONSTRAINT [PK_myTable] 
        PRIMARY KEY CLUSTERED ([myTestPK] ASC)
           WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                 IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                 ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

create Type [dbo].myTableParameters as table
(
    myTestPK nvarchar(10)
)
go

create procedure InsertNewRecords(@dataTable [dbo].myTableParameters readonly)
as
begin
    insert into myTable
        select * from @dataTable;
end
go

--This is what i really want to do!
create procedure RealInsertNewRecords(@dataTable [dbo].myTableParameters readonly)
as
begin
    insert into myTable
        select * 
        from @dataTable
        where not exists (select 'x' 
                          from myTable m 
                          where m.myTestPK = @dataTable.myTestPK)
end

您的問題與使用表值參數無關。 相反,您的SQL只是錯誤的。

insert into myTable
    select * 
    from @dataTable
    where not exists (select 'x' 
                      from myTable m 
                      where m.myTestPK = @dataTable.myTestPK) <-- this line isn't legal

您應該使用MERGE語句。

MERGE INTO MyTable t USING @dataTable s ON t.myTestPK = s.myTestPK
WHEN NOT MATCHED THEN INSERT (myTestPK) VALUES (s.myTestPK)
; <-- the semicolon is required

https://msdn.microsoft.com/zh-CN/library/bb510625.aspx


我總是將表t命名為target,將s命名為source。 我發現它使跟蹤哪個是更容易。

這不是最好的方法,但我只是想出了一種處理方法。 無需訪問DataTable,而是直接插入到臨時表中。

create procedure InsertNewRecords(@dataTable [dbo].myTableParameters readonly)
as
begin
select * into #InsertNewRecords
from @dataTable;

insert into myTable
select * from #InsertNewRecords
where not exists (select 'x' from [myTable] where [myTable].myTestPK = #InsertNewRecords.myTestPK);
end
go

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM