我正在制作一个视图,但我有点困惑为什么我的字段被转换为可为空。我正在使用SQL Server 2016。
CREATE OR ALTER VIEW [dbo].[vwEmployeePTORequest]
AS
SELECT
Employees.EmployeeID, Employees.DivisionID,
PTORequests.PTORequestId, PTORequests.IsPaidOut,
PTORequests.PayoutPayEntryEarningId,
--Why do I have to use ISNULL here?
ISNULL(SummaryDetails.TotalHours, 0) AS TotalHours,
SummaryDetails.RequestStartDate, SummaryDetails.RequestEndDate,
SummaryDetails.DivisionPTOAccrualId
FROM
dbo.Employees
INNER JOIN
dbo.GlobalIds ON Employees.GlobalId = GlobalIds.Id
INNER JOIN
dbo.Activities ON Activities.OriginatorGlobalId = GlobalIds.Id
INNER JOIN
dbo.PTORequests ON Activities.ActivityId = PTORequests.ActivityId
CROSS APPLY
dbo.GetEmployeePTORequestDetailSummary(PTORequests.PTORequestId) AS SummaryDetails;
这是在CROSS APPLY
中调用的函数:
CREATE OR ALTER FUNCTION [dbo].[GetEmployeePTORequestDetailSummary]
(@PTORequestId INT)
RETURNS TABLE
AS
RETURN
(SELECT TOP 1
SUM(Hours) AS TotalHours,
MIN(RequestDate) AS RequestStartDate,
MAX(RequestDate) AS RequestEndDate,
DivisionPTOAccrualId AS DivisionPTOAccrualId
FROM
dbo.PTORequestDetails
WHERE
PTORequestId = @PTORequestId
GROUP BY
PTORequestId, DivisionPTOAccrualId);
这是表定义的相关部分:
CREATE TABLE [dbo].[PTORequestDetails]
(
[PTORequestDetailId] [int] IDENTITY(1,1) NOT NULL,
[RequestDate] [date] NOT NULL,
[StartTime] [datetime] NULL,
[Hours] [decimal](19, 2) NOT NULL,
)
我对为什么会发生这种情况有点困惑。如您所见,我的列不可为 NULL,聚合函数返回不可为空的类型,并且我正在使用类似于内部连接的每行工作的CROSS APPLY
。 由于它是一对一的,因此不应创建可为空的。
谁能解释为什么我的列显示为可为空,以及如何在函数中解决此问题,以便使用它的所有其他过程不必为每个选定的列指定ISNULL()
条件?
这不是交叉应用。它是聚合函数。SUM、MIN、MAX 都假定为可为空,因为如果您在没有 GROUP BY 的空表上使用它们,它们将返回 NULL。
此外,如果使用某些已弃用的会话选项,SUM 可以返回 NULL 而不是整数溢出错误。
因此,您需要将聚合包装在ISNULL
中,以使列被视为不可为空。