SQL,保持NULL而不是0

时间:2015-10-21 13:51:35

标签: sql sql-server-2008-r2 null

我有一个sql存储过程,由于一些奇怪的原因,从user-define-function返回0,即使这返回一个空值。

更奇怪的是,如果我只将这部分存储过程移动到新查询,则返回正确的NULL,所以我无法重现它

被控制的列为Abbattimento,用户函数为[FN_Abbattimento_Copertura_Processo],以这种方式链接:

OUTER APPLY dbo.FN_Abbattimento_Copertura_Processo(Kint_TP006_IdAttivita,@AnnoRiferimento, IdLiv4,  SPD.Ktyi_TP001_IdSocieta, Ktyi_TP058_IdSocietaService, tyi_TP058_Copertura, 2) [acp]    

相反,如果我添加

(Select * FROM dbo.FN_Abbattimento_Copertura_Processo(...)) AS Abbattimento

我得到NULL VALUE,所以问题似乎是使用apply

调用函数

这是整个商店程序:

ALTER PROCEDURE [dbo].EXT_Pian_DettaglioProcessi
        @AnnoRiferimento    SMALLINT = NULL
    ,   @IdSocieta          SMALLINT = NULL
    ,   @IDAreaIncaricata   SMALLINT = NULL
    ,   @IDAreaCoinvolta    SMALLINT = NULL
    ,   @Ufficiale          BIT     = 0
    ,   @Virtuali           BIT     = 0
AS
BEGIN

    DECLARE @VirtualiIntero AS TINYINT
    SET @VirtualiIntero =
                CASE @Virtuali 
                    WHEN 0 THEN 2
                    ELSE 0
                END

    --IF @IdSocieta = 0
    --  SET @IdSocieta = NULL

    --print @Virtuali

    SELECT 
            SA.nvc_TP001_Societa        AS Societa          
        ,   Kint_TP006_IdAttivita       AS IdAttivita
        ,   nvc_TP006_Attivita          AS Attivita 
        ,   AreaIncaricata                      
        ,   CONVERT(NVARCHAR(10), DataPianificata.InizioValStatus, 103) AS DataPianificazione
        ,   StatusAttuale.DescrizioneStatus                             AS StatusAttuale
        ,   CONVERT(NVARCHAR(10), StatusAttuale.InizioValStatus, 103)   AS Dal
        --, IdLiv2                                  AS IdProcessoLivello2
        ,   Liv2                                    AS ProcessoLivello2
        ,   IdLiv4                                  AS IdProcessoLivello4
        ,   Liv4                                    AS ProcessoLivello4
        ,   SPD.nvc_TP001_Societa                   AS SocietaProcesso
        ,   SPS.nvc_TP001_SocietaAbbreviata         AS SocietaServiceProcesso
        ,   tyi_TP058_Copertura                     AS Copertura
        ,   ksin_TP058_Anno                         AS AnnoInizioCopertura
        --, CASE Abbattimento
        --      WHEN 0 THEN NULL
        --      ELSE Abbattimento
        --  END                                     AS Abbattimento
        ,   Abbattimento
        ,   TipoCopertura   
        ,   ISNULL(CP.CoperturaOverride, 0) + ISNULL(CP.CoperturaAttConRating, 0)  AS CoperturaComplessivaProcesso      

    FROM
            -- faccio una distinct per non avere duplicati per area e perimetro
            -- non lo faccio nella select iniziale perchè altrimenti dovrei selezionare anche i campi usati solo per ordinamento
            (SELECT DISTINCT 
                    Kint_TP013_IdAttivita
                ,   Ksin_TP013_AnnoRifPian
                ,   Ktyi_TP013_ProgressivoPian
            FROM Q_TP013_Pianificazione
            WHERE
                (ISNULL(@IDAreaIncaricata, @IDAreaCoinvolta) IS NULL
                OR
                Ksin_TP013_IdArea IN (SELECT idarea FROM dbo.FN_StrutturaAree(ISNULL(@IDAreaIncaricata, @IDAreaCoinvolta)))
                )) AS Pian
        INNER JOIN dbo.[FN_DettaglioPianificazione](@AnnoRiferimento, @Ufficiale) AS FiltroPianificazione
            ON IdAttivita = Kint_TP013_IdAttivita
            AND Progressivo = Ktyi_TP013_ProgressivoPian
        INNER JOIN Q_TP006_Attivita
            ON Kint_TP006_IdAttivita = Kint_TP013_IdAttivita
        INNER JOIN TP001_Societa AS SA
            ON SA.Ktyi_TP001_IdSocieta = tyi_TP006_IdSocieta
        INNER JOIN 
                (SELECT 
                        nvc_TP003_Area AS AreaIncaricata
                    ,   Kint_TP024_IdAttivita
                FROM
                    Q_TP024_LinkAttivitaArea
                INNER JOIN TP003_Area
                    ON Ksin_TP003_IdArea = Ksin_TP024_IdArea
                WHERE 
                        tyi_TP024_IdTipoLinkAttivitaArea = 1
                    AND Ksin_TP024_IdArea = COALESCE(@IDAreaIncaricata, Ksin_TP024_IdArea)
                ) AS AI
            ON Kint_TP024_IdAttivita = Kint_TP006_IdAttivita    
        INNER JOIN dbo.FN_CoperturaProcessiAttivita(@AnnoRiferimento,0, @VirtualiIntero,0)
            ON Kint_TP058_IdAttivita = Kint_TP006_IdAttivita
        LEFT OUTER JOIN dbo.[FN_StrutturaProcessi](GETDATE())
            ON IdLiv4 = Ksin_TP058_IdProcesso           
        LEFT OUTER JOIN TP001_Societa SPD
            ON SPD.Ktyi_TP001_IdSocieta = Ktyi_TP058_IdSocieta
        LEFT OUTER JOIN TP001_Societa SPS
            ON SPS.Ktyi_TP001_IdSocieta = Ktyi_TP058_IdSocietaService
        OUTER APPLY dbo.FN_DataStatusAttivita(Kint_TP006_IdAttivita,1) AS DataPianificata       
        OUTER APPLY dbo.FN_Status_Attivita_Periodo(GETDATE(), Kint_TP006_IdAttivita, null, null) AS StatusAttuale
        OUTER APPLY dbo.FN_Abbattimento_Copertura_Processo(Kint_TP006_IdAttivita,@AnnoRiferimento, IdLiv4,  SPD.Ktyi_TP001_IdSocieta, Ktyi_TP058_IdSocietaService, tyi_TP058_Copertura, 2) [acp]        
        OUTER APPLY dbo.FN_CoperturaProcesso(IdLiv4, SPD.Ktyi_TP001_IdSocieta, SPS.Ktyi_TP001_IdSocieta, @AnnoRiferimento) AS CP


    WHERE
            Ksin_TP013_AnnoRifPian = @AnnoRiferimento   

            --and IdAttivita = 12331

    ORDER BY
            Societa
        ,   IdAttivita
        ,   Ord1
        ,   Ord2
        ,   Ord3
        ,   Ord4

这是计算Abbattimento的用户函数:

ALTER FUNCTION [dbo].[FN_Abbattimento_Copertura_Processo]
(   
    -- Add the parameters for the function here
    -- Add the parameters for the function here
    @idAttivita int,
    @anno smallint = 0,
    @idProcesso smallint = 0,
    @idSocieta tinyint = 0,
    @idSocietaService tinyint = 0,
    @copertura tinyint = 0,
    @tipoAbbattimento TINYINT = 1   --1 Dalla prima presente, 2 dalla precedente
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT 
        CASE 
            WHEN @tipoAbbattimento = 1 THEN  
                (SELECT TOP 1 (CAST(tyi_TP058_Copertura AS SMALLINT) - @copertura) 
                        FROM    dbo.Q_TP058_LinkAttivitaLinkProcessoSocieta
                        WHERE Kint_TP058_IdAttivita = @idAttivita
                            AND Ksin_TP058_Anno between @anno-5 and  @anno
                            AND Ksin_TP058_IdProcesso = @idProcesso
                            AND Ktyi_TP058_IdSocieta = @idSocieta
                            AND Ktyi_TP058_IdSocietaService = @idSocietaService
                        ORDER BY Ksin_TP058_Anno)
            WHEN @tipoAbbattimento = 2 THEN
                (SELECT TOP 1 (CAST(tyi_TP058_Copertura AS SMALLINT) - @copertura) 
                        FROM    dbo.Q_TP058_LinkAttivitaLinkProcessoSocieta
                        WHERE Kint_TP058_IdAttivita = @idAttivita
                            AND Ksin_TP058_Anno between @anno-5 and  @anno-1
                            AND Ksin_TP058_IdProcesso = @idProcesso
                            AND Ktyi_TP058_IdSocieta = @idSocieta
                            AND Ktyi_TP058_IdSocietaService = @idSocietaService
                        ORDER BY Ksin_TP058_Anno DESC)
        END AS Abbattimento
)

正如你在评论中看到的那样我现在有一个案例可以将0转换回NULL,但说实话,我不喜欢这个解决方案。

你可以帮助我找到原因吗?

1 个答案:

答案 0 :(得分:0)

我没有阅读您的查询,但可能会对您有所帮助NULLIF

NULLIF(col,0)

如果您的列等于NULL

,它将返回0