SQL:如果存在记录列表,则返回“true”?

另一个标题可能是:检查是否存在多行?

使用SQL和C#的组合,如果列表中的所有产品都存在于表中,我希望方法返回true。 如果它可以在SQL中完成,那将是更好的选择。 我编写了一个方法,使用以下SQL返回是否存在单个productID

 SELECT productID FROM Products WHERE ProductID = @productID 

如果返回一行,则c#方法返回true,否则返回false。

现在我想知道我是否有一个产品ID清单(不是一个很大的清单,通常在20岁以下)。 如果所有产品ID都存在则如何编写将返回一行的查询,如果一个或多个产品ID不存在则如何不返回行?

 (Maybe something involving "IN" like: SELECT * FROM Products WHERE ProductID IN ('1', '10', '100', 'ABC')) 

编辑:

如何表达结果对我来说并不重要。 无论查询返回1还是0 ,空结果集还是非空结果集,true或false都无关紧要。 我更喜欢这样的答案:1)易于阅读和理解,2)高效

我想要将产品ID列表与SQL连接起来。 显然这会打开SQL注入代码(产品ID实际上是varchar 。在这种情况下,机会很小但仍然希望避免这种可能性)。 因此,如果有办法解决这个问题会更好。 使用SQL Server 2005。

产品ID是varchar

鉴于您更新的问题,这些是最简单的forms:

如果ProductID是您想要的唯一

 SELECT COUNT(*) FROM Products WHERE ProductID IN (1, 10, 100) 

然后检查结果对3 ,你要查询的产品数量(最后一部分可以在SQL中完成,但在C#中可能更容易,除非你在SQL中做得更多)。

如果ProductID不是唯一的,那么

 SELECT COUNT(DISTINCT ProductID) FROM Products WHERE ProductID IN (1, 10, 100) 

当问题被认为需要在所有ProductIds存在时返回行,否则:

 SELECT ProductId FROM Products WHERE ProductID IN (1, 10, 100) AND ((SELECT COUNT(*) FROM Products WHERE ProductID IN (1, 10, 100))=3) 

要么

 SELECT ProductId FROM Products WHERE ProductID IN (1, 10, 100) AND ((SELECT COUNT(DISTINCT ProductID) FROM Products WHERE ProductID IN (1, 10, 100))=3) 

如果你真的打算对结果做些什么。 否则简单的SELECT 1 WHERE (SELECT ...)=3将像其他答案所陈述或暗示的那样。

@Mark Hurd,谢谢你指出错误。

这将工作(如果你使用Postgresql,Sql Server 2008):

 create table products ( product_id int not null ); insert into products values(1),(2),(10),(100); SELECT CASE WHEN EXISTS( SELECT 1 FROM (values(1),(10),(100)) as x(id) WHERE x.id NOT IN (select product_id from products)) THEN 0 --'NOT ALL' ELSE 1 -- 'ALL' END 

如果您使用的是MySQL,请创建一个临时内存表(然后在那里填充1,10,100):

 create table product_memory(product_id int) engine=MEMORY; insert into product_memory values(1),(10),(100); SELECT CASE WHEN EXISTS( SELECT 1 FROM product_memory WHERE product_memory.id NOT IN (select product_id from products)) THEN 0 -- 'NOT ALL' ELSE 1 -- 'ALL' END 

在你的C#代码上:

 bool isAllExist = (int)(new SqlCommand(queryHere).ExecuteScalar()) == 1; 

[编辑]

如果所有产品ID都存在则如何编写将返回一行的查询,如果一个或多个产品ID不存在则如何不返回行?

关于如果所有行都存在则返回一行(单数),如果一个或多个产品ID不存在则不返回任何行

MySQL的:

 SELECT 1 WHERE NOT EXISTS( SELECT 1 FROM product_memory WHERE product_memory.id NOT IN (select product_id from products) ) 

Posgresql,Sql Server 2008:

 SELECT 1 WHERE NOT EXISTS( SELECT 1 FROM (values(1),(10),(100)) as x(id) WHERE x.id NOT IN (select product_id from products) ) 

然后在你的C#代码上:

 var da = new SqlDataAdapter(queryhere, connectionhere); var dt = new DataTable(); da.Fill(dt); if (dt.Rows.Count > 0) return true; else return false; 

或者只是缩短条件:

 return dt.Rows.Count > 0; 

这是我通常这样做的方式:

只需用此语句SELECT * FROM table WHERE 1 替换您的查询

  SELECT CASE WHEN EXISTS ( SELECT * FROM table WHERE 1 ) THEN 'TRUE' ELSE 'FALSE' END 
 DECLARE @values TABLE (ProductId int) INSERT @values (1) INSERT @values (10) INSERT @values (100) SELECT CASE WHEN (SELECT COUNT(*) FROM @values v) = (SELECT COUNT(*) FROM Products p WHERE p.ProductId IN (SELECT v.ProductId FROM @values v)) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END [AreAllFound] 
 // not familiar with C#, but C#'s equivalent of PHP's: $count = count($productIds); // where $productIds is the array you also use in IN (...) SELECT IF ((SELECT COUNT(*) FROM Products WHERE ProductID IN (1, 10, 100)) = $count, 1, 0) 

如果IN子句是一个参数(SP或热建SQL),那么总是可以这样做:

 SELECT (SELECT COUNT(1) FROM product_a WHERE product_id IN (1, 8, 100) ) = (number of commas in product_id as constant) 

如果IN子句是一个表,那么总是可以这样做:

 SELECT (SELECT COUNT(*) FROM product_a WHERE product_id IN (SELECT Products FROM #WorkTable) ) = (SELECT COUNT(*) FROM #WorkTable) 

如果IN子句很复杂,则将其假脱机到表中或写入两次。

如果您将ID存储在临时表中(可以通过某些C#函数或简单的SQL来完成),那么SQL中的问题就变得简单易行。

 select "all exist" where (select case when count(distinct t.id) = (select count(distinct id) from #products) then "true" else "false" end from ProductTable t, #products p where t.id = p.id) = "true" 

#products中的所有产品#products存在于目标表( ProductTable )中时,这将返回“all exists”,如果上述内容不为真,则不会返回一行。

如果您不愿意写入临时表,那么您需要为您尝试查找的产品数量提供一些参数,并将临时表替换为“in”; 子句,因此子查询看起来像这样:

 SELECT "All Exist" WHERE( SELECT case when count(distinct t.id) = @ProductCount then "true" else "false" FROM ProductTable t WHERE t.id in (1,100,10,20) -- example IDs ) = "true" 

如果您使用的是SQL Server 2008,我将创建一个采用表值参数的存储过程。 然后,查询应该是一个特别简单的forms:

 CREATE PROCEDURE usp_CheckAll (@param dbo.ProductTableType READONLY) AS BEGIN SELECT CAST(1 AS bit) AS Result WHERE (SELECT COUNT(DISTINCT ProductID) FROM @param) = (SELECT COUNT(DISTINCT p.ProductID) FROM @param AS p INNER JOIN Products ON p.ProductID = Products.ProductID) END 

我改变了这个以返回一行,因为你似乎需要。 还有其他方法可以使用WHERE NOT EXISTS(这里的LEFT JOIN WHERE rhs IS NULL):

 CREATE PROCEDURE usp_CheckAll (@param dbo.ProductTableType READONLY) AS BEGIN SELECT CAST(1 AS bit) AS Result WHERE NOT EXISTS ( SELECT * FROM @param AS p LEFT JOIN Products ON p.ProductID = Products.ProductID WHERE Products.ProductID IS NULL ) END 

你的c#必须做一些工作(计算传入的ID数),但试试这个:

 select (select count(*) from players where productid in (1, 10, 100, 1000)) = 4 

编辑:

绝对可以参数化4,整数列表也可以参数化。

如果您没有从用户输入的字符串生成SQL,则无需担心攻击。 如果你是,你只需要确保你只获得整数。 例如,如果你输入字符串“1,2,3,4”,你会做类似的事情

 String.Join(",", input.Split(",").Select(s => Int32.Parse(s).ToString())) 

如果你弄错了,那就扔了。 然后将其设置为参数。

此外,如果items.Count == 0,请务必确保特殊情况,因为如果您将数据发送where ParameterID in ()您的数据库将会阻塞。

您试图确定存在的产品列表在哪里? 如果该列表存在于另一个表中,则可以执行此操作

 declare @are_equal bit declare @products int SELECT @products = count(pl.id) FROM ProductList pl JOIN Products p ON pl.productId = p.productId select @are_equal = @products == select count(id) from ProductList 

编辑:

然后在C#中完成所有工作。 在某处缓存应用程序中的实际产品列表,并执行LINQ查询。

 var compareProducts = new List(){p1,p2,p3,p4,p5}; var found = From p in GetAllProducts() Join cp in compareProducts on cp.Id equals p.Id select p; return compareProducts.Count == found.Count; 

这可以防止手动构建SQL查询,并将所有应用程序逻辑保留在应用程序中。

我知道这已经过时了,但我认为这会有助于其他人来看…

 SELECT CAST(COUNT(ProductID) AS bit) AS [EXISTS] FROM Products WHERE(ProductID = @ProductID) 

如果存在,这将总是返回TRUE,如果不存在则返回FALSE(而不是没有行)。

假设您使用的是SQL Server,则布尔类型不存在,但位类型不存在,只能包含0或1,其中0表示False,1表示True。

我会这样走:

 select 1 from Products where ProductId IN (1, 10, 100) 

这里,将返回null或no行(如果不存在行)。

甚至:

 select case when EXISTS ( select 1 from Products where ProductId IN (1, 10, 100) ) then 1 else 0 end as [ProductExists] 

这里,将始终返回标量值1或0中的任何一个(如果不存在行)。

这可能太简单了,但我总是使用:

 SELECT COUNT(*)>0 FROM `table` WHERE condition;