Function giving subquery returned more than 1 value, this is not permitted.....error

  • I am getting this error:subquery returned more than 1 value, this is not permitted when the subquery follow........whenever I try to run this function.

    USE [DB1]GO SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER FUNCTION fn_PayrollConfirm (@EmpID int)RETURNS @PayrollConfirm TABLE (PayslipID int identity(1,1), EmpID int, TaxableIncome int, NetPay int) ASBEGIN DECLARE @TotalDays int; SET @TotalDays = (select datediff(day,StartDate,EndDate) from WorkingRecord); IF (@TotalDays =30 or @TotalDays <=31)  BEGIN   INSERT INTO @PayrollConfirm            SELECT EmpID, BasePay * 0.2 AS TaxableIncome, BasePay-BasePay * 0.2 AS NetPay            FROM dbo.WorkingPeriod             WHERE EmpID = @EmpID  END;    ELSE IF (@TotalDays <30)     BEGIN      INSERT INTO @PayrollConfirm            SELECT EmpID,BasePay * 0.2 AS TaxableIncome,BasePay/30*@TotalDays as NetPay            FROM dbo.WorkingPeriod             WHERE EmpID = @EmpID            END; RETURN;END--select * from fn_PayrollConfirm(11)

    In that function,I am trying to calculate TaxableIncome and NetPay according to @TotalDays(a parameter which counts number of working day). And put those values to a table called PayrollConfirm( where I have added PayslipID which is auto generated )
    My expected result from function is only one row displaying PayslipID,EmpID,TaxableIncome,NetPay.

  • Formatted so that it's actually readable.

    ALTER FUNCTION fn_PayrollConfirm (@EmpID INT)
    RETURNS @PayrollConfirm TABLE (
      PayslipID INT IDENTITY(1, 1),
      EmpID INT,
      TaxableIncome INT,
      NetPay INT
      )
    AS
      BEGIN
       DECLARE @TotalDays INT;
        SET @TotalDays = (SELECT DATEDIFF (DAY, StartDate, EndDate) FROM WorkingRecord);
        IF (@TotalDays = 30
          OR @TotalDays <= 31)
        BEGIN
          INSERT INTO @PayrollConfirm
          SELECT EmpID,
            BasePay * 0.2 AS TaxableIncome,
            BasePay - BasePay * 0.2 AS NetPay
          FROM  dbo.WorkingPeriod
          WHERE EmpID = @EmpID;
        END;
        ELSE
        IF (@TotalDays < 30)
          BEGIN
           INSERT INTO @PayrollConfirm
           SELECT EmpID,
              BasePay * 0.2 AS TaxableIncome,
              BasePay / 30 * @TotalDays AS NetPay
           FROM  dbo.WorkingPeriod
           WHERE EmpID = @EmpID;
          END;
        RETURN;
       END

    Most likely this returns more than one row:
    SELECT DATEDIFF (DAY, StartDate, EndDate) FROM WorkingRecord
    Since you're using it with SET, it must return one and only one row.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • Thank you. How could I format nicely, especially for block of sql code for better readability?  I've edited select datediff(day,wr.StartDate,wr.EndDate) from WorkingRecord wr inner join EmpTbl e ON wr.EmpID=e.EmpID where e.EmpID=@EmpID and the function is get me one row result. But will It actually store in PayConfirmTbl? For example if I want to use that PayConfirmTbl alone in another place?

  • Newbi - Friday, August 18, 2017 1:44 AM

     But will It actually store in PayConfirmTbl? For example if I want to use that PayConfirmTbl alone in another place?

    Huh?

    To store something in that table, insert it, or update an existing row.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • I know why because that @PayrollConfirmTable is a temporary one and thus i can't get result when I execute the table outside of the function. How can I make it as a separate table and recall from some where else of the application.

  • Not related to the question, but to the SQL provided.

    Why is the first IF statement IF (@TotalDays = 30 OR @TotalDays <= 31) and the ELSE IF statement ELSE IF (@TotalDays < 30). The second statement will never be fulfilled, as if @TotalDays less than 30, then it's less than or equal for 31 (basic maths). As the first IF statement's prerequisite is fulfilled, no other parts of the IF (ELSE) will be entered.

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • Newbi - Friday, August 18, 2017 3:01 AM

    I know why because that @PayrollConfirmTable is a temporary one and thus i can't get result when I execute the table outside of the function. How can I make it as a separate table and recall from some where else of the application.

    There's nothing in @PayrollConfirmTable because your function errors before it gets to inserting into it.  Once you've sorted that out, you can put the results into a temporary or permanent table so that you can query them:
    SELECT *
    INTO #PayrollConfirmTable
    FROM fn_PayrollConfirm;

    John

Viewing 7 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic. Login to reply