基本上我有一个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
答案 0 :(得分: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
命名为源。我发现它可以更容易地跟踪哪个是哪个。
答案 1 :(得分:-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