2016-08-14 5 views
0

基本的には、データテーブルを作成してストアドプロシージャとして渡すC#アプリケーションがあります。しかし、それはすべて動作します。私がしたいのは、渡されたデータテーブルにロジックを追加することです。ストアドプロシージャのWHERE句でデータ型を使用する方法

たとえば、以下のテストでは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 

答えて

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


私は常にターゲットとソースのsのための私のテーブルt名前を付けます。私はそれがどれがどれであるかを把握しやすくする。

-1

動作しないものですそれを処理する。 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 
+0

誰かがdownvoteを説明したいですか? – JL1

関連する問題