Как текстуально указать, что в запросе SQL SELECT нет результатов? - PullRequest
0 голосов
/ 04 августа 2020

У меня есть следующий оператор SQL CASE, который, похоже, неправильно оценивает условное выражение. Эта таблица в настоящее время пуста (0 ненулевых строк), поэтому я предполагаю, что условие ELSE должно быть истинным, и поэтому вывести текстовую строку ниже. Однако он ничего не заполняет в результатах.

SELECT 
CASE WHEN EC.INV_ITEM_ID <> '' THEN EC.INV_ITEM_ID
     ELSE 'NO ITEMS IN STAGING TABLES'
     END
  
FROM PS_MASTER_ITEM_EC EC
ORDER BY INV_ITEM_ID

Ответы [ 8 ]

1 голос
/ 07 августа 2020
IF ((SELECT COUNT(*) FROM PS_MASTER_ITEM_EC EC WHERE EC.INV_ITEM_ID <> '' AND EC.INV_ITEM_ID IS NOT NULL) > 0)
SELECT EC.INV_ITEM_ID FROM PS_MASTER_ITEM_EC EC WHERE EC.INV_ITEM_ID <> '' AND EC.INV_ITEM_ID IS NOT NULL
ELSE
SELECT 'NO ITEMS IN STAGING TABLES'

Первая строка вычислит, сколько непустых строк в таблице, вторая строка вернет таблицу с 1 столбцом со всеми идентификаторами, которые не были NULL или '', если они вообще найдены, 4-я строка вернет сообщение по умолчанию, если таблица была фактически пустой

0 голосов
/ 13 августа 2020

Если ваш вопрос просто почему вы не получаете результатов, вот мой ответ:

Запрос SQL состоит из разных частей, называемых «предложениями». SELECT и FROM - два из них (вероятно, самые важные).

Все, что вы напишете в предложении SELECT (т.е. после SELECT и до FROM), может дать только столбцов из строк, которые являются результатом того, что вы пишете в предложении FROM. Таблица PS_MASTER_ITEM_EC в вашем предложении FROM не содержит никаких строк, поэтому ваше предложение FROM не может создавать никаких строк. Следовательно, в предложении SELECT нет строк, для которых оно может создавать столбцы.

Однако есть одно исключение: если вы опустите предложение FROM, SELECT может произвести результат с одной строкой, как в

SELECT 'no result found' as Dummy
-- Will generate a result with one row, one column "Dummy" containing 'no result found'
0 голосов
/ 12 августа 2020

Этого можно добиться, используя LEFT JOIN:

SELECT IIF(EC.INV_ITEM_ID <> '', EC.INV_ITEM_ID, s.col)
FROM (SELECT 'NO ITEMS IN STAGING TABLES') s(col)
LEFT JOIN PS_MASTER_ITEM_EC EC ON 1=1
ORDER BY EC.INV_ITEM_ID;

db <> fiddle demo

СКЭНАР ios:

CREATE TABLE PS_MASTER_ITEM_EC(INV_ITEM_ID NVARCHAR(10));

-- case 1: empty value
INSERT INTO PS_MASTER_ITEM_EC VALUES ('');
-- NO ITEMS IN STAGING TABLES

-- case 2: empty table
TRUNCATE TABLE PS_MASTER_ITEM_EC
-- NO ITEMS IN STAGING TABLES

-- case 3: data in table
INSERT INTO PS_MASTER_ITEM_EC VALUES ('abc')
-- output: abc
0 голосов
/ 10 августа 2020

Использование общего табличного выражения (CTE), одно для основного запроса (вашего запроса), а другое для проверки, пуста ли интересующая вас таблица.

WITH MainQuery AS (
  SELECT 
  CASE WHEN EC.INV_ITEM_ID <> '' THEN EC.INV_ITEM_ID
       END AS INV_ITEM_ID
  FROM PS_MASTER_ITEM_EC EC
),
EmptyTableMessage AS (
  SELECT
  CASE WHEN (SELECT COUNT(*) FROM MainQuery) > 0 THEN ''
       ELSE 'NO ITEMS IN STAGING TABLES'
       END AS EmptyMessage 
)
SELECT
EmptyTableMessage.EmptyMessage,
MainQuery.*
FROM EmptyTableMessage
LEFT OUTER JOIN MainQuery ON 1 = 1
ORDER BY MainQuery.INV_ITEM_ID

Не стесняйтесь изменять содержимое внутри MainQuery с любым запросом, который вам нужен, и измените предложение ORDER BY в самом конце в соответствии с содержимым MainQuery.

Отрицательный аспект этого заключается в том, что вы всегда будете иметь дополнительный столбец, содержащий (в качестве заполнителя) сообщение для пустой таблицы / записи / результата.

0 голосов
/ 09 августа 2020

SQL Сервер - это база данных relational. Реляционные базы данных работают с sets, который в основном представляет собой список записей. Если записи нет, то ваша функция / logi c (в данном случае CASE) не может быть применена. Если вам нужна запись, возвращаемая, когда ваш запрос возвращает нулевую запись, вам необходимо предоставить запись из другого источника для возврата. Один из способов сделать это - предоставить запись через UNION с предложением WHERE, которое гарантирует, что специальная запись будет возвращена, когда набор результатов пуст. Если набор результатов НЕ пуст, то предложение WHERE гарантирует, что эта новая запись не будет возвращена. Проблема здесь в том, что эта специальная запись должна иметь такое же количество столбцов, что и результат обычного запроса, и с такими же или совместимыми типами данных.

; WITH cte (
 ---- your complex query goes here 
  select colString, colNumeric 
   .............
) 
SELECT colString, colNumeric FROM cte 
UNION ALL
SELECT 'no result found' as colString, NULL as colNumeric  WHERE NOT EXISTS (SELECT * FROM cte) --- this returns true only if no record in cte
0 голосов
/ 08 августа 2020

Все значения в столбце должны иметь один и тот же тип данных. Поэтому, если столбец INV_ITEM_ID используется для строкового значения 'NO ITEMS IN STAGING TABLES' в случае отсутствия каких-либо записей, тогда столбец должен иметь текстовый тип данных.

Если это не В этом случае вам нужно будет преобразовать идентификаторы в строки, чтобы они соответствовали этому случаю, когда есть записи. Лично я бы не советовал этого делать, так как это похоже на смешивание мела и сыра - строковое значение на самом деле не принадлежит столбцу numeri c ID - и даже если идентификаторы оказываются строками, это все еще сомнительно, поскольку семантически «нет результатов» "строка не является идентификатором.

Но если вы действительно хотите это сделать, это можно сделать примерно так: SQL:

SELECT 'NO ITEMS IN STAGING TABLES' AS INV_ITEM_ID
WHERE NOT EXISTS (SELECT * FROM PS_MASTER_ITEM_EC)
UNION ALL 
SELECT CAST(INV_ITEM_ID AS VARCHAR(26))
FROM PS_MASTER_ITEM_EC EC
ORDER BY INV_ITEM_ID;

Демонстрация Rextester: https://rextester.com/FIRWF53864

0 голосов
/ 07 августа 2020

Ваша проблема в том, что ваш CASE оценивается только для существующих строк, если ваша таблица пуста, вы не получите вообще никакой записи.

Но вы хотите получить запись с сообщением, даже если таблица пуста, поэтому вы должны создать эту строку. Вы можете сделать это, используя UNION, чтобы добавить новую строку в набор результатов, только когда PS_MASTER_ITEM_EC пуст.

Итак, вы можете просто перечислить все свои записи, если они есть, и показать свое сообщение, когда PS_MASTER_ITEM_EC пусто.

SELECT EC.INV_ITEM_ID
FROM PS_MASTER_ITEM_EC EC
ORDER BY INV_ITEM_ID

UNION ALL

SELECT 'NO ITEMS IN STAGING TABLES'
WHERE NOT EXISTS(SELECT TOP 1 'X' X FROM PS_MASTER_ITEM_EC )

Обратите внимание, вам нужно, чтобы столбец INV_ITEM_ID имел тип char / varchar / nvarchar, иначе вы получите сообщение об ошибке. Если ваш INV_ITEM_ID - это номер, вы можете использовать этот обходной путь:

SELECT EC.INV_ITEM_ID, NULL Message
FROM PS_MASTER_ITEM_EC EC
ORDER BY INV_ITEM_ID

UNION ALL

SELECT NULL INV_ITEM_ID, 'NO ITEMS IN STAGING TABLES' Message
WHERE NOT EXISTS(SELECT TOP 1 'X' X FROM PS_MASTER_ITEM_EC )
0 голосов
/ 07 августа 2020

Вы не можете вернуть записи из пустой таблицы. Оператор case оценивается по каждой записи в таблице. Когда нет записей, тогда нечего будет оценивать, следовательно, пустой набор результатов. Есть несколько способов проверить это условие. Если клиент ожидает определенный набор результатов c и будет проверять известное поле на наличие данных (что кажется хакерским), вы можете вернуть данные аналогичной формы из производного набора результатов с вашим обменом сообщениями, однако Я бы посоветовал вам подумать о проверке этого условия у потребителя, поскольку запросы к базе данных лучше подходят для вставки / обновления / удаления и получения данных .

DECLARE @PS_MASTER_ITEM_EC TABLE(INV_ITEM_ID NVARCHAR(200))
--INSERT @PS_MASTER_ITEM_EC VALUES ('I''m Here')

IF(NOT EXISTS(SELECT EC.INV_ITEM_ID FROM @PS_MASTER_ITEM_EC EC))
    SELECT INV_ITEM_ID =  'NO ITEMS IN STAGING TABLES'
ELSE
SELECT 
CASE WHEN EC.INV_ITEM_ID <> '' THEN EC.INV_ITEM_ID
     ELSE 'EC.INV_ITEM_ID has an empty string for a value'
     END AS INV_ITEM_ID
  
FROM @PS_MASTER_ITEM_EC EC
ORDER BY INV_ITEM_ID 
...