Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SQL表值参数仅在其数据复制到临时表时有效_C#_Sql_Stored Procedures_Table Valued Parameters - Fatal编程技术网

C# SQL表值参数仅在其数据复制到临时表时有效

C# SQL表值参数仅在其数据复制到临时表时有效,c#,sql,stored-procedures,table-valued-parameters,C#,Sql,Stored Procedures,Table Valued Parameters,我使用dapper通过c到sql存储过程传递数据 c使用简洁: var dt = new DataTable("dbo.TVPtype"); dt.SetTypeName("dbo.TVPtype"); dt.Columns.Add("ID", typeof(int)); dt.Rows.Add(5); _db.Execute("mysp", param: new { TVP = dt.AsTableValuedParameter("dbo.TVPtype"), commandType:

我使用dapper通过c到sql存储过程传递数据

c使用简洁:

 var dt = new DataTable("dbo.TVPtype");
 dt.SetTypeName("dbo.TVPtype");
 dt.Columns.Add("ID", typeof(int));
 dt.Rows.Add(5);
_db.Execute("mysp", param: new { TVP = dt.AsTableValuedParameter("dbo.TVPtype"), commandType: CommandType.StoredProcedure);
下面的SQL查询将无法工作,我不知道为什么!它将从mytable中删除所有数据。 SQL存储过程:

CREATE PROCEDURE [dbo].[mysp] @TVP dbo.TVPtype READONLY AS
DELETE FROM [dbo].[mytable] WHERE NOT EXISTS
(
SELECT NULL FROM @TVP na
WHERE ID = na.ID
)
为了解决这个问题,我在存储过程中使用了一个临时表,如bellow,它工作得很好。 使用临时表的我的解决方案:

CREATE table temptb (ID int)
insert into temptb select * from @TVP
现在我在删除查询中使用了TENTEB而不是@TVP:

DELETE FROM [dbo].[mytable] WHERE NOT EXISTS
(
SELECT NULL FROM temptb na
WHERE ID = na.ID
)
它可以很好地删除特定数据,而不是所有数据!
那么,我的第一个问题出了什么问题

我无法告诉您,为什么它使用临时表,但如果将DELETE语句更改为:

DELETE t1 
FROM [dbo].[mytable] AS t1 WHERE NOT EXISTS
(
    SELECT NULL FROM @TVP na
    WHERE t1.ID = na.ID
)
它会起作用的。请看,当我将alias添加到mytable时,条件变得很清楚,它应该比较哪个ID。在您的示例中,它可能会将@TVP ID与其自身进行比较,这是我的猜测

我想在您的查询中再添加两点:

当您检查是否存在时,最好选择非NULL的内容,因为NULL在sql中是特殊的,尽管它在您的示例中起作用。例如,从@TVP中选择1。。。会更具可读性

为什么不这样做:

片段:

DELETE FROM [dbo].[mytable] AS t1 WHERE ID NOT IN
(
    SELECT na.ID FROM @TVP na
)

我无法告诉您为什么它使用临时表,但如果将其更改为:

DELETE t1 
FROM [dbo].[mytable] AS t1 WHERE NOT EXISTS
(
    SELECT NULL FROM @TVP na
    WHERE t1.ID = na.ID
)
它会起作用的。请看,当我将alias添加到mytable时,条件变得很清楚,它应该比较哪个ID。在您的示例中,它可能会将@TVP ID与其自身进行比较,这是我的猜测

我想在您的查询中再添加两点:

当您检查是否存在时,最好选择非NULL的内容,因为NULL在sql中是特殊的,尽管它在您的示例中起作用。例如,从@TVP中选择1。。。会更具可读性

为什么不这样做:

片段:

DELETE FROM [dbo].[mytable] AS t1 WHERE ID NOT IN
(
    SELECT na.ID FROM @TVP na
)

限定您的列名!你认为你在写:

DELETE FROM [dbo].[mytable]
    WHERE NOT EXISTS (SELECT 1
                      FROM @TVP na
                      WHERE mytable.ID = na.ID
                     );
但你不是。SQL的作用域规则将您的查询解释为:

DELETE FROM [dbo].[mytable]
    WHERE NOT EXISTS (SELECT 1
                      FROM @TVP na
                      WHERE na.ID = na.ID
                     );
这是相当不理智的。WHERE与外部查询不相关。如果@TVP为空,或者ID始终为空,或者在任何其他情况下都没有行,那么它将删除所有行


如果您限定所有列引用,您将永远不会遇到此问题。

限定您的列名!你认为你在写:

DELETE FROM [dbo].[mytable]
    WHERE NOT EXISTS (SELECT 1
                      FROM @TVP na
                      WHERE mytable.ID = na.ID
                     );
但你不是。SQL的作用域规则将您的查询解释为:

DELETE FROM [dbo].[mytable]
    WHERE NOT EXISTS (SELECT 1
                      FROM @TVP na
                      WHERE na.ID = na.ID
                     );
这是相当不理智的。WHERE与外部查询不相关。如果@TVP为空,或者ID始终为空,或者在任何其他情况下都没有行,那么它将删除所有行


如果您限定了所有列引用,您将永远不会遇到此问题。

首先,找出问题是在c中还是在SQL中-尝试直接从SSMS运行第一个存储过程,看看会发生什么。首先,找出问题是在c中还是在SQL中-尝试直接从SSMS运行第一个存储过程,看看会发生什么。