代码之家  ›  专栏  ›  技术社区  ›  User

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

  •  29
  • User  · 技术社区  · 14 年前

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

    如果列表中的所有产品都存在于表中,那么使用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'))
    

    编辑:

    结果如何表达对我来说并不重要。查询是否返回 1 0 空结果集或非空结果集,无论是真是假都无所谓。我希望答案是:1)易于阅读和理解;2)性能

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

    产品ID是 瓦卡尔

    13 回复  |  直到 6 年前
        1
  •  19
  •   Mark Hurd    10 年前

    考虑到更新后的问题,这些是最简单的形式:

    如果 ProductID 你想要的独一无二

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

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

    如果 产品目录 不是独一无二的

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

        2
  •  11
  •   Michael Buen    14 年前

    @马克·赫德,谢谢你指出了错误。

    这将有效(如果您使用的是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,10100):

    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;
    
        3
  •  8
  •   Mahmoud Zalt    9 年前

    我通常是这样做的:

    只是 代替 您对此语句的查询 SELECT * FROM table WHERE 1

       SELECT
          CASE WHEN EXISTS 
          (
                SELECT * FROM table WHERE 1
          )
          THEN 'TRUE'
          ELSE 'FALSE'
       END
    
        4
  •  1
  •   Anthony Faull    14 年前
    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]
    
        5
  •  0
  •   Alec    14 年前
    // 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
  •   Joshua    14 年前

    如果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子句很复杂,那么要么将其spool到表中,要么将其写入两次。

        7
  •  0
  •   TerrorAustralis    14 年前

    如果您将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
  •   Cade Roux    14 年前

    如果您使用的是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
    

    我把这个改成返回一行,正如你所要求的。有其他方法可以使用不存在的(此处的左联接,rhs为空)执行此操作:

    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
  •   user24359    14 年前

    您的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()))
    

    如果你得到错误的东西,那会扔。然后将其设置为一个参数。

    另外,如果项,请务必使用特殊情况。count==0,因为如果发送,数据库将阻塞。 where ParameterID in () .

        10
  •  0
  •   Josh Smeaton    14 年前

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

    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查询,并在应用程序中保留所有应用程序逻辑。

        11
  •  0
  •   joels    6 年前

    我知道这是旧的,但我认为这将帮助任何人谁来找…

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

    如果存在,则返回true;如果不存在,则返回false(与没有行相反)。

        12
  •  -1
  •   Will Marcouiller    14 年前

    假设您使用的是SQL Server,则布尔类型不存在,但位类型存在,它只能容纳0或1,其中0表示假,1表示真。

    我要走这条路:

    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(如果不存在行)。

        13
  •  -1
  •   NAB    13 年前

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

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