【问题标题】:How to use a type datatable in WHERE clause of a stored procedure如何在存储过程的 WHERE 子句中使用类型数据表
【发布时间】:2016-08-14 15:05:25
【问题描述】:

基本上我有一个 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

【问题讨论】:

    标签: c# sql-server stored-procedures datatable


    【解决方案1】:

    您的问题与使用表值参数无关。而是您的 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/en-us/library/bb510625.aspx


    我总是将我的表命名为 t 为目标,s 为源。我发现它更容易跟踪哪个是哪个。

    【讨论】:

      【解决方案2】:

      这不是最好的方法,但我只是想出了一种方法来处理它。而不是直接访问 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
      

      【讨论】:

        猜你喜欢
        • 2021-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-08
        • 2018-08-10
        • 2018-08-27
        • 1970-01-01
        相关资源
        最近更新 更多