另一个标题可能是: 检查是否存在多行?
使用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
答案 0 :(得分:19)
鉴于您的更新问题,这些是最简单的形式:
如果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
将像其他答案所陈述或暗示的那样。
答案 1 :(得分:11)
@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;
答案 2 :(得分:10)
以下是我通常的做法:
使用此语句SELECT * FROM table WHERE 1
SELECT
CASE WHEN EXISTS
(
SELECT * FROM table WHERE 1
)
THEN 'TRUE'
ELSE 'FALSE'
END
答案 3 :(得分:1)
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]
答案 4 :(得分:0)
你的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 ()
,您的数据库会阻塞。
答案 5 :(得分:0)
// 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)
答案 6 :(得分: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子句很复杂,则将其假脱机到表中或写两次。
答案 7 :(得分:0)
如果您将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
中的所有产品都存在于目标表(ProductTable
)中时,这将返回“全部存在”,如果上述情况不正确,则不会返回一行。
如果您不愿意写入临时表,那么您需要为您尝试查找的产品数量输入一些参数,并将临时表替换为“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"
答案 8 :(得分:0)
如果您使用的是SQL Server 2008,我将创建一个采用a table-valued parameter的存储过程。然后,查询应该是一种特别简单的形式:
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
答案 9 :(得分:0)
您试图确定存在的产品列表在哪里?如果该列表存在于另一个表中,则可以执行此操作
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<Product>(){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查询,并将所有应用程序逻辑保留在应用程序中。
答案 10 :(得分:0)
我知道这很老了,但是我认为这会帮助其他寻找...的人
SELECT CAST(COUNT(ProductID) AS bit) AS [EXISTS] FROM Products WHERE(ProductID = @ProductID)
如果存在,这将始终返回TRUE,否则将返回FALSE(与没有行相对)。
答案 11 :(得分:0)
您可以像这样使用SELECT CASE语句:
select case when EXISTS (
select 1
from <table>
where <condition>
) then TRUE else FALSE end
当您在父母中的查询存在时,它将返回TRUE
。
答案 12 :(得分:-1)
假设您使用的是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中的任何一个(如果不存在行)。
答案 13 :(得分:-1)
这可能太简单了,但我总是使用:
SELECT COUNT(*)>0 FROM `table` WHERE condition;