SQL SELECT 中如何用文字表示没有结果?

How to textually indicate that there are no results in a SQL SELECT?

我有以下 SQL CASE 语句似乎没有正确评估条件。这个 table 当前是空的(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

您不能 return 从空的 table 记录。正在根据 table 中的每条记录评估 case 语句。当没有记录时,将没有任何可评估的内容,因此结果集为空。有几种方法可以检查这种情况。如果客户期望特定的结果集并将检查已知字段中是否存在数据(这看起来很老套),那么您可以 return 来自派生结果集的类似形状的数据与您的消息传递,但是,我鼓励您考虑在消费者处检查这种情况,因为数据库查询更适合 inserting/updating/deleting 并获取数据

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

第一行将计算 table 中有多少非空行 第二行将 return 1 列 table 包含所有非 NULL 或 '' 的 ID(如果找到的话) 如果 table 实际上是空的

,则第 4 行将 return 默认消息

您的问题是您的 CASE 仅针对现有行进行评估,如果您的 table 为空,您将根本没有记录。

但是,即使 table 为空,您也想获得一条包含消息的记录,因此您必须创建该行。 您可以使用 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 )

列中的所有值必须具有相同的数据类型。因此,如果在没有任何记录的情况下 INV_ITEM_ID 列用于 'NO ITEMS IN STAGING TABLES' 的字符串值,则该列必须具有文本数据类型。

如果不是这种情况,您需要将 ID 转换为字符串以在有记录的情况下与之匹配。我个人建议不要这样做,因为它就像混合粉笔和奶酪——字符串值并不真正属于数字 ID 列——即使 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

SQL 服务器是一个 relational 数据库。关系数据库使用 off sets,它基本上是一个记录列表。如果没有记录,则无法应用您的功能/逻辑(在本例中为CASE)。如果您需要在查询时返回一条记录 returns 零条记录,那么您需要提供一条来自另一个要返回的源的记录。一种方法是通过 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

使用通用 Table 表达式 (CTE),一个用于主查询(您的查询),另一个用于检查您感兴趣的 table 是否为空。

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 中的内容,并根据 MainQuery 的内容更改最后的 ORDER BY 子句。

不利的一面是,您将始终有一个额外的列包含(作为占位符)空 table/record/result 的消息。

可以通过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


场景:

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

如果你的问题只是为什么你没有得到任何结果,这是我的回答:

一个SQL查询由称为“子句”的不同部分组成。 SELECTFROM 是其中的两个(可能是最重要的)。

无论您在 SELECT 子句中写入什么(即在 SELECT 之后和 FROM 之前),都只能从符合以下条件的行中生成 您在 FROM 子句中所写内容的结果。 FROM 子句中的 table PS_MASTER_ITEM_EC 不包含任何行,因此 FROM 子句不能生成任何行。因此 SELECT 子句没有任何可以为其创建列的行。

不过有一个例外:如果您省略 FROM 子句,SELECT 可以 产生一个只有一行的结果,如

SELECT 'no result found' as Dummy
-- Will generate a result with one row, one column "Dummy" containing 'no result found'