我尝试使用以下查询和 ado.net ExecuteNonQuery()
方法将多个值作为逗号分隔字符串传递,从而从 SQL Server 数据库表中删除记录。这里我传递表名、列名和逗号分隔值。
string delQuery = "DELETE FROM " + delTblName +
" WHERE " + delColumnName + " IN (" + toDel+ ")";
如果 toDel
中的完整值列表没有问题,则删除过程成功。假设如果外键与任何一个值发生冲突,则整个语句将被终止,并且不会删除任何记录。
由于 toDel
变量中的元素数量很大,我无法使用顺序处理,也无法根据要求使用存储过程。
我需要根据成功的元素进行删除,并从此方法返回错误的元素。任何帮助,将不胜感激。
使用以下代码并使用参数
try
{
using (var sc = new SqlConnection(dbConnString))
using (var cmd = sc.CreateCommand())
{
sc.Open();
cmd.CommandText = "DELETE FROM @delTblName WHERE @delColumnName IN ( @valConcat) ";
cmd.Parameters.AddWithValue("@delTblName", tblName);
cmd.Parameters.AddWithValue("@delColumnName", delColumnName);
cmd.Parameters.AddWithValue("@valConcat", nosConcat);
cmd.CommandType = CommandType.Text;
rowsAffected = rowsAffected + cmd.ExecuteNonQuery();
}
}
catch
{
}
出现此错误 - 必须声明表变量“@delTblName”。
最佳答案
无论是否使用存储过程,您都会有两个相互矛盾的要求:
- 您想要批量删除行,而不是逐行删除。为了速度。
- 您希望删除操作完成时部分忽略可能违反约束的情况。
我不知道如何制作DELETE
声明部分起作用。一条语句是最小原子工作量,因此如果 1000 行中有一行违反了约束,则整个语句将回滚。
这导致了以下通用想法。在尝试 DELETE
之前在影响多行的一条语句中,请确保可以删除受影响行的整个列表。明确检查数据中是否没有任何内容可以阻止您要删除的行被删除。实际检查取决于您的限制。识别那些无法删除的行并将它们从主 DELETE
中删除列表。
示例
两个表 - TestMaster
和TestDetails
具有一对多关系。
CREATE TABLE [dbo].[TestMaster](
[ID] [int] NOT NULL,
[MasterData] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_TestMaster] PRIMARY KEY CLUSTERED
(
[ID] ASC
))
CREATE TABLE [dbo].[TestDetails](
[ID] [int] NOT NULL,
[MasterID] [int] NOT NULL,
[DetailData] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_TestDetails] PRIMARY KEY CLUSTERED
(
[ID] ASC
))
GO
ALTER TABLE [dbo].[TestDetails] WITH CHECK
ADD CONSTRAINT [FK_TestDetails_TestMaster] FOREIGN KEY([MasterID])
REFERENCES [dbo].[TestMaster] ([ID])
GO
ALTER TABLE [dbo].[TestDetails] CHECK CONSTRAINT [FK_TestDetails_TestMaster]
GO
一些示例数据:
INSERT INTO [dbo].[TestMaster] ([ID],[MasterData]) VALUES
(1, 'Master1'),
(2, 'Master2'),
(3, 'Master3'),
(4, 'Master4');
INSERT INTO [dbo].[TestDetails] ([ID],[MasterID],[DetailData]) VALUES
(10, 1, 'Detail10'),
(11, 1, 'Detail11'),
(20, 2, 'Detail20');
简单尝试DELETE
项目(1, 2, 3, 4)
:
DELETE FROM [dbo].[TestMaster]
WHERE ID IN (1, 2, 3, 4);
这失败了:
Msg 547, Level 16, State 0, Line 13
The DELETE statement conflicted with the REFERENCE constraint "FK_TestDetails_TestMaster". The conflict occurred in database "AdventureWorks2014", table "dbo.TestDetails", column 'MasterID'.
The statement has been terminated.
我们只能删除那些没有相应详细信息的主行。在这个例子中它只是 3, 4
.
查找MasterID
不能先删除:
SELECT DISTINCT [dbo].[TestDetails].MasterID
FROM [dbo].[TestDetails]
WHERE [dbo].[TestDetails].MasterID IN (1, 2, 3, 4);
返回结果:
MasterID
1
2
编辑您的原始 ID 列表并从中删除冲突的 ID,然后您可以运行最终的 DELETE
:
DELETE FROM [dbo].[TestMaster]
WHERE ID IN (3, 4);
单个查询
而不是运行单独的 SELECT
,通过网络向客户端检索冲突ID列表,调整原始ID列表,运行最终的DELETE
您可以进行一个查询来完成这一切。对于这个简单的示例,它可以如下所示:
DELETE FROM [dbo].[TestMaster]
WHERE
[dbo].[TestMaster].ID IN (1, 2, 3, 4)
AND [dbo].[TestMaster].ID NOT IN
(
SELECT [dbo].[TestDetails].MasterID
FROM [dbo].[TestDetails]
WHERE [dbo].[TestDetails].MasterID IN (1, 2, 3, 4)
);
此查询将仅删除 ID 为 3 和 4 的两行。
关于c# - 通过传递逗号分隔值删除记录 SQL Server 和 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35314913/