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

时间:2010-05-19 00:23:08

标签: c# sql conditional boolean exists

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

使用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

14 个答案:

答案 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;