44

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

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

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'))

编辑:

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

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

产品 ID 是varchar

4

14 回答 14

30

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

如果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会像其他答案所述或暗示的那样。

于 2010-05-19T00:35:07.427 回答
25

这是我通常的做法:

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

   SELECT
      CASE WHEN EXISTS 
      (
            SELECT * FROM table WHERE 1
      )
      THEN 'TRUE'
      ELSE 'FALSE'
   END
于 2015-07-24T00:26:23.123 回答
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;
于 2010-05-19T02:19:15.887 回答
1

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

我会这样:

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

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

甚至:

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

在这里,将始终返回标量值 1 或 0(如果不存在行)。

于 2010-05-19T00:35:56.600 回答
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]
于 2010-05-19T06:01:48.307 回答
1

我知道这很旧,但我认为这将帮助其他任何前来寻找的人......

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

如果存在,则始终返回 TRUE,否则返回 FALSE(与无行相反)。

于 2018-10-16T17:58:26.407 回答
1

您可以像这样使用SELECT CASE语句:

select case when EXISTS (
 select 1 
 from <table>
 where <condition>
 ) then TRUE else FALSE end

TRUE当您在父母中的查询存在时,它会返回。

于 2019-07-31T14:22:38.157 回答
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 ()

于 2010-05-19T00:34:31.373 回答
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)
于 2010-05-19T00:35:57.173 回答
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 子句很复杂,那么要么将其假脱机到一个表中,要么将其写入两次。

于 2010-05-19T01:34:17.797 回答
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"
于 2010-05-19T02:06:35.513 回答
0

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

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 in here 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
于 2010-05-19T02:32:31.377 回答
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 查询,并将所有应用程序逻辑保留在应用程序中。

于 2010-05-19T04:35:11.870 回答
0

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

SELECT COUNT(*)>0 FROM `table` WHERE condition;
于 2011-11-23T13:01:41.767 回答