【问题标题】:I am having the error with a Subquery returning more than one value. How do I reduce to one?我有一个子查询返回多个值的错误。我如何减少到一个?
【发布时间】:2021-06-11 03:36:14
【问题描述】:

在存储过程的最后一个 SELECT 语句用于显示表的内容,包括同时填充表中字段的函数。

这是 Select 语句:

IF @type = 'SH'
SELECT DISTINCT *
FROM #History
ORDER BY 1, 2, 3, 4, 5
ELSE
SELECT DISTINCT   AmhazName
        ,Activity
        ,ServiceName
        ,Sarid
        ,PerformedDate
        ,UserRole
        ,Details
        ,dbo.ufn_SarHistoryActionText(sarid, status, performeddate) AS [ActionText]
        ,FullName
        ,CategoryDescription
        ,StatusDescription
        ,ActionPerformed

        ,Case 
            when Details like '%ProjManagerId%'
                Then    dbo.ufn_GetUserForHistoryReport (PerformedDate, SarId, '%ProjManagerId%')
        Else
            --when Details like '%UserId%'
                 dbo.ufn_GetUserForHistoryReport (PerformedDate, SarId, '%UserId%') 
                 --(select 'no user') as [AssignedUser]
        End as [AssignedUser]

        --,dbo.ufn_GetPMForHistoryReport(PerformedDate, SarId) as [AssignedUser]
FROM #history
ORDER BY 1, 2, 3, 4, 5
DROP TABLE #Historyw

这是我认为会导致问题的函数:

ALTER FUNCTION [dbo].[ufn_SarHistoryActionText] 
(
    -- Add the parameters for the function here
      @sarID int
    , @status varchar(6)
    , @statusDate datetime
)
RETURNS varchar(100)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @Result varchar(100)

    set @Result = (
                    SELECT C.ActionText
                    from LuStatusChange as C
                    WHERE   C.FromStatus = dbo.ufn_SarHistoryPriorStatus(@sarID,@status,@statusDate)
                        AND C.ToStatus = @status
                    )

    -- Return the result of the function
    RETURN @Result

END
GO

当我调试和遍历大量值时,我没有遇到任何导致多个值的情况。也许我错过了什么。

【问题讨论】:

  • 无法访问您的数据,我们无法提供太多服务。至于您的函数,它有可能返回多个值,但这取决于数据的样子。您始终可以将TOP 1ORDER BY 添加到选择中,但实际上您需要找到导致问题的值。如果无法访问上述值,我们将无能为力。
  • 嗯,很明显错误来自ufn_SarHistoryActionText。当该子查询返回多个值时,您将收到该错误消息。您可以使用select FromStatus, ToStatus from LuStatusChange group by FromStatus, ToStatus having count(*) > 1 找出可能的行
  • 您正在使用三个标量函数 - 可能还有第四个函数,具体取决于作为最后一列的注释行。第一步是停止相信并开始实际调试您的代码以找到导致错误的实际函数。您可以在检索分配值的查询中使用“TOP 1” - 但最好弄清楚您是否对架构做出了错误的假设,或者您在查询中是否存在逻辑缺陷。标量函数调用标量函数有异味。
  • 非常感谢你们的帮助。成功了!

标签: sql sql-server database tsql


【解决方案1】:

在函数内部的select中添加TOP 1:

SELECT TOP 1 C.ActionText 

【讨论】:

    【解决方案2】:

    你能换吗

    set @Result = (
                    SELECT C.ActionText
                    from LuStatusChange as C
                    WHERE   C.FromStatus = dbo.ufn_SarHistoryPriorStatus(@sarID,@status,@statusDate)
                        AND C.ToStatus = @status
                    )
    

    如下:

     @Result ***IN***  (
                    SELECT C.ActionText
                    from LuStatusChange as C
                    WHERE   C.FromStatus = dbo.ufn_SarHistoryPriorStatus(@sarID,@status,@statusDate)
                        AND C.ToStatus = @status
                    )
    

    如果在功能上您的查询不应超过 1 行,则说明您的查询有问题。

    【讨论】:

    • 这不是一个有效的语法
    • 整个查询中只有一个子查询!!!这是唯一的问题,请将 = 替换为 in
    • set @Result IN ( SELECT ...) 不是有效的 sql server 语法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-14
    相关资源
    最近更新 更多