【问题标题】:SP return null as ZERO?SP 将 null 作为零返回?
【发布时间】:2009-08-21 12:24:42
【问题描述】:

使用存储过程,我有一个相当复杂的 SQL 语句,它返回一个 COUNT 值作为伪列。在许多情况下,结果将为“null”。这会导致我的应用程序出现问题,所以我想知道是否可以从存储过程中默认将“null”返回为“0”?

谢谢。

更新

我需要将 ISNULL 应用于以下语句;

    select recip_Chosen, recip_CampaignId) AS ChosenCount
    from TBL_CAMPAIGNRECIPIENTS
    WHERE recip_CampaignId =  @campaign
    group by recip_Chosen

应该是这样的;

    select recip_Chosen, ISNULL(count(recip_CampaignId),0) AS ChosenCount
    from TBL_CAMPAIGNRECIPIENTS
    WHERE recip_CampaignId =  @campaign
    group by recip_Chosen

但是,这仍然会在 ChosenCount 列中返回空值。有什么想法吗?

更新

好的,所以上面的语句是一个更大的语句的一部分,如下所示。这是完整的存储过程,但不是表结构,因为它涉及多个表。我只需要“ChosenCount”返回“0”而不是 Null。 SP 确实为 TBL_CAMPAIGNS_CHARITIES 中对应于 TBL_CAMPAIGNS 的每条记录返回 1 行。

CREATE PROCEDURE web.getPublicCampaignData
   (
   @campaign BIGINT
   )
AS
BEGIN

SELECT * 
FROM TBL_CAMPAIGNS C
INNER JOIN TBL_MEMBERS M
    ON C.campaign_MemberId = M.members_Id
INNER JOIN TBL_CAMPAIGNS_CHARITIES CC
    ON C.campaign_Key = CC.camchar_CampaignID
INNER JOIN TBL_CHARITIES CH
    ON CC.camchar_CharityID = CH.cha_Key
LEFT OUTER JOIN (
    select recip_Chosen, count(recip_CampaignId) as ChosenCount
    from TBL_CAMPAIGNRECIPIENTS
    WHERE recip_CampaignId =  @campaign
    group by recip_Chosen
) CRC
on CH.cha_Key = CRC.recip_Chosen
WHERE C.campaign_Key = @campaign;

END

【问题讨论】:

  • 如何将此 COUNT 列实现为“计数”NULL 而不是 0?
  • 用完整的陈述更新了问题。
  • 好吧,问题是:你在这里做一个左外连接,所以如果没有基于on CH.cha_Key = CRC.recip_Chosen条件显示的数据,那么那里什么都没有。 LEFT OUTER JOIN 里面的 SELECT 根本不会被执行,所以这就是为什么 ISNULL 从来没有机会做它的工作
  • 查看我更新的帖子 - 我试图展示如何重新订购您的 SProc 以使 ISNULL 为您工作

标签: sql sql-server sql-server-2005 stored-procedures


【解决方案1】:

是的:

RETURN ISNULL(yourvalue, 0)

这基本上意味着什么:

  • 如果“yourvalue”(计算值或 @variable 的值)不为 NULL,则返回该值

  • 如果“yourvalue”为NULL,则返回第二个参数(此处为“0”)

我不确切知道您是如何计算计数的 - 我假设您将其分配给存储过程中的某个局部变量:

CREATE PROCEDURE dbo.DoMyCount()
RETURNS INT
AS BEGIN
   DECLARE @MyCountVariable INT

   SET @MyCountVariable = SELECT COUNT(*)......... -- whatever you do here

   RETURN ISNULL(@MyCountVariable, 0)
END

在这种情况下,您的存储过程 dbo.DoMyCount 将返回一个计数(无论您如何计算),或者“0”(零)表示该计数为 NULL。

这样,您可以确保始终从存储过程中获取有效的 NON-NULL INT 值。

马克

更新:

存储过程清楚地说明了为什么 ISNULL 不起作用 - 它在 LEFT OUTER JOIN 中使用。如果没有数据匹配,则永远不会调用 LEFT OUTER JOIN 中的整个选择 --> ISNULL 永远不会有机会完成它的工作。

你需要稍微重构你的存储过程:

CREATE PROCEDURE web.getPublicCampaignData(@campaign BIGINT)
AS BEGIN
  SELECT
     (list of fields), ISNULL(CRC.ChosenCount, 0), .....
  FROM TBL_CAMPAIGNS C
  INNER JOIN TBL_MEMBERS M 
     ON C.campaign_MemberId = M.members_Id
  INNER JOIN TBL_CAMPAIGNS_CHARITIES CC 
     ON C.campaign_Key = CC.camchar_CampaignID
  INNER JOIN TBL_CHARITIES CH 
    ON CC.camchar_CharityID = CH.cha_Key
  LEFT OUTER JOIN (
    select recip_Chosen, count(recip_CampaignId) as ChosenCount
    from TBL_CAMPAIGNRECIPIENTS
    WHERE recip_CampaignId =  @campaign
    group by recip_Chosen
  ) CRC on CH.cha_Key = CRC.recip_Chosen
  WHERE 
     C.campaign_Key = @campaign;
END

这样,如果 CH.cha_Key = CRC.recip_Chosen 不匹配并且 LEFT OUTER JOIN 返回 NULL,它将被捕获,并且 ChosenCount = NULL 将变为“0”。

【讨论】:

  • 最佳选择,ISNULL 比 COALESCE 快(这是 CASE WHEN THEN END,大多数人不知道)
  • Svetlozar 是对的,这应该被接受。我的答案是你知道的更多类型。 Marc 已经赢得了我的 +1。
  • 马克,谢谢你的回答。您能否分解这里发生的事情,以便我可以完全理解它,从而从中学习。谢谢。
  • 用声明的细节更新了我的问题。请看一下。谢谢。
【解决方案2】:

除了 SQL Server 上的 isnull 之外,我还是 coalesce 的忠实粉丝,因为它可以接受任意数量的参数。对于两个参数,它在功能上等价于isnull

return coalesce(yourvalue, 0)

等同于:

return isnull(yourvalue, 0)

然而,

coalesce(yourvalue, backupval, 0)

等价于

isnull(isnull(yourvalue, backupval), 0)

显然,coalesce 在这种情况下更具可读性,所以这就是我成为粉丝的原因。

对一个非常简单的问题的冗长回答表示歉意,但是,嘿,为什么不学习其他东西,嗯?

【讨论】:

  • COALESCE 并不完全等同于 ISNULL,因为 COALESCE 处理具有多种数据类型作为对象,其中 ISNULL 要求数据类型相同。 ISNULL('test', 0) 会失败,而 COALESCE('test', 0) 会成功。
【解决方案3】:
select isnull(sum(size),0) as total_size from my_table where is_valid = 1

【讨论】:

  • 用声明的细节更新了我的问题。请看一下,因为我尝试了这种方法但没有成功。谢谢。
【解决方案4】:

ISNULL 可能更快,但它特定于 SQLServer。

COALESCE 是 ANSI 标准

Here's some differences and other explanations about ISNULL and COALESCE

【讨论】:

  • 越快越好,如果在极少数情况下你移植代码会有一百万个其他更困难的问题,但是从 ISNULL 的搜索和替换COALESCE 很容易...
猜你喜欢
  • 2011-02-17
  • 2018-05-25
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 2021-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多