如何以文本方式指示SQL选择中没有结果?

如何以文本方式指示SQL选择中没有结果?,sql,select,count,case,sql-server-2014,Sql,Select,Count,Case,Sql Server 2014,我有下面的SQL CASE语句,它似乎没有正确地计算条件。此表当前为空0个非空行,因此我假设ELSE条件为true,因此输出下面的文本字符串。但是,它不会填充结果中的任何内容 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

我有下面的SQL CASE语句,它似乎没有正确地计算条件。此表当前为空0个非空行,因此我假设ELSE条件为true,因此输出下面的文本字符串。但是,它不会填充结果中的任何内容

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

不能从空表返回记录。case语句将根据表中的每条记录进行求值。当没有记录时,将没有任何要计算的内容,因此结果集为空。有几种方法可以检查这种情况。如果客户端需要一个特定的结果集,并且会检查一个已知字段是否存在数据,这似乎有点骇人听闻,那么您可以通过消息传递从派生结果集中返回类似形状的数据,我鼓励您考虑在消费者处检查这种情况,因为数据库查询更适合于插入/更新/删除和获取数据

第一行将计算表中有多少非空行 第二行将返回一个1列表,其中包含所有不为NULL的ID,或者如果找到任何ID,则返回该表 如果表实际为空,则第4行将返回默认消息。您的问题是,您的案例仅针对现有行进行评估,如果表为空,则根本不会得到任何记录

但是,即使该表为空,您也希望获得包含消息的记录,因此必须创建该行。 只有当PS_MASTER_ITEM_EC为空时,才能使用UNION将新行添加到结果集中

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 )
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
因此,如果有任何记录,您可以简单地列出所有记录, 并在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 )
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
请注意,您需要INV_ITEM_ID列的类型为char/varchar/nvarchar,否则会出现错误。 如果您的库存项目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碰巧是字符串,也有疑问,因为从语义上讲,无结果字符串不是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演示:

SQL Server是一个关系数据库。关系数据库的工作方式是偏移,它基本上是一个记录列表。如果没有记录,则无法应用本例中的功能/逻辑案例。如果您的查询返回零记录时需要返回一条记录,那么您需要提供一条来自另一个要返回的源的记录。一种方法是通过与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

使用公共表表达式CTE,一个用于查询的主查询,另一个用于检查您感兴趣的表是否为空

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


消极的一面是,您总是会有一个额外的列,其中包含空表/记录/结果的消息占位符。

可以通过使用左连接来实现:

如果你的问题只是为什么没有结果,我的答案是:

SQL查询由称为子句的不同部分组成。SELECT和FROM可能是其中最重要的两个

在SELECT子句中写入的内容(即SELECT之后和FROM之前)只能从FROM子句中写入的结果行生成列。FROM子句中的表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'

如果表为空,则查询不返回任何行。未计算case表达式NOT语句。如果表有0行,则上面的SELECT将不返回任何内容。如果没有行,则CASE表达式不能返回任何行。当没有行时,返回结果集的唯一简单SQL语句是不带GROUP BY的计数。
例如,从sys.tables中选择COUNT*,其中[name]=N‘如果您有一个名为this的表,您太傻了!’@Larnu那么我可以在Case语句中使用COUNT*,或者如果不存在行,我如何实现返回文本字符串;SQL Server不支持Case Switch语句。您需要了解更多详细信息来回答您的问题,例如当有多行时,您的期望值。不存在的查询更容易理解,IMHO:从PS_MASTER_ITEM_EC中选择“暂存表中没有项目”作为库存项目ID(如果不存在)。从PS_MASTER_ITEM_EC贪婪中选择1,谢谢-已相应修改答案。实际上需要省略FROM子句,因为它导致不存在行。