Подтвердить что ты не робот

SQL: возвращает "true", если список записей существует?

Альтернативным заголовком может быть: Проверить наличие нескольких строк?

Используя комбинацию SQL и С#, я хочу, чтобы метод возвращал true, если все продукты в списке существуют в таблице. Если это можно сделать в SQL, что было бы предпочтительнее. Я написал метод, который возвращает, существует ли один productID, используя следующий SQL:

SELECT productID FROM Products WHERE ProductID = @productID

Если это возвращает строку, то метод С# возвращает true, иначе false.

Теперь мне интересно, есть ли у меня список идентификаторов продуктов (а не огромный список, который вам нравится, обычно до 20 лет). Как я могу написать запрос, который вернет строку, если весь идентификатор продукта существует, и нет строки, если один или несколько идентификаторов продукта не существуют?

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

EDIT:

Как результат выражен, для меня не важно. Если запрос возвращает 1 или 0, пустой набор результатов или непустой, true или false, не имеет значения. Я бы предпочел ответ, который 1) легко читается и понимается, и 2) исполнитель

Я предполагал объединить список идентификаторов продукта с SQL. Очевидно, что это открывает код до SQL-инъекции (идентификатор продукта на самом деле varchar. В этом случае вероятность тонкая, но все же хочет избежать этой возможности). Поэтому, если есть способ обойти это, было бы лучше. Использование SQL Server 2005.

Идентификатор продукта varchar

4b9b3361

Ответ 1

Учитывая ваш обновленный вопрос, это самые простые формы:

Если ProductID уникально, вы хотите

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

а затем проверьте этот результат на 3, количество продуктов, которые вы запрашиваете (эта последняя часть может быть выполнена в SQL, но может быть проще сделать это на С#, если вы еще не делаете 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 будет делать, как заявили или подразумевали другие ответы.

Ответ 2

@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

В коде С#:

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

[EDIT]

Как написать запрос, который будет верните строку, если все идентификаторы продукта существует и нет строки, если один или несколько идентификатор продукта не существует?

Относительно возврата строки (единственного числа), если все строки существуют, и нет строки, если один или несколько идентификаторов продукта не существуют:

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

Затем на ваш код С#:

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

Вот как я обычно это делаю:

Просто замените ваш запрос с помощью этого оператора SELECT * FROM table WHERE 1

   SELECT
      CASE WHEN EXISTS 
      (
            SELECT * FROM table WHERE 1
      )
      THEN 'TRUE'
      ELSE 'FALSE'
   END

Ответ 4

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

Ваш С# должен будет выполнить лишь небольшую работу (считая количество переданных идентификаторов), но попробуйте следующее:

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

Edit:

4 определенно может быть параметризован, как и список целых чисел.

Если вы не генерируете SQL из ввода строки пользователем, вам не нужно беспокоиться об атаках. Если да, вам просто нужно убедиться, что вы получаете целые числа. Например, если вы взяли строку "1, 2, 3, 4", вы бы сделали что-то вроде

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

Это будет бросать, если вы ошиблись. Затем просто установите это как параметр.

Кроме того, обязательно укажите особый случай, если items.Count == 0, так как ваша БД будет задыхаться, если вы отправите ее where ParameterID in ().

Ответ 6

// not familiar with C#, but C# 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)

Ответ 7

Если предложение 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 является сложным, то либо вставляйте его в таблицу, либо пишите дважды.

Ответ 8

Если у вас есть идентификаторы, хранящиеся в таблице temp (что может быть сделано с помощью некоторой функции С# или простого 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) и не вернут строку, если выше это не так.

Если вы не хотите писать в временную таблицу, вам нужно указать некоторый параметр для количества продуктов, которые вы пытаетесь найти, и заменить таблицу temp на "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"

Ответ 9

Если вы используете 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 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

Ответ 10

Где этот список продуктов, который вы пытаетесь определить, существует? Если этот список существует в другой таблице, вы можете сделать это

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

Edit:

Затем выполните ВСЕ работу в С#. Загрузите фактический список продуктов в вашем приложении и выполните запрос 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

Предполагая, что вы используете SQL Server, тип boolean не существует, но тип бита делает, который может содержать только 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 всегда будет возвращено (если строка не существует).

Ответ 12

Это может быть слишком просто, но я всегда использую:

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