SQL Server过程没有返回任何结果

时间:2012-05-16 15:40:04

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

好的,我在SQL Server 2005数据库中有以下过程。我想弄清楚为什么它没有给我任何结果。尝试访问它的用户是管理员,但我也尝试过与其他用户访问它,但我仍然没有得到任何结果。 Bond在Bond表的基本查询中返回。我只想弄清楚为什么这没有结果。任何帮助表示赞赏。

ALTER PROCEDURE dbo.GetBondAmounts
(
    @Username varchar(20)
)
AS
DECLARE @Admin AS bit
SELECT @Admin = Admin FROM Users WHERE Username = @Username
if(@Admin = 1)
BEGIN
    RETURN
    SELECT Bond.ID, SUM(Charge.BondAmount) + SUM(ChargeWithoutPower.BondAmount) Amount,
    SUM(Charge.BondPremium) + SUM(ChargeWithoutPower.BondPremium) + SUM(Forfeiture.AmountPaid)
    + SUM(Forfeiture.CostOfApprehension) - SUM(Payment.Amount) - SUM(BalanceForgiveness.AmountForgiven) Balance
    FROM Bond LEFT OUTER JOIN Payment ON Bond.ID = Payment.Bond
    LEFT OUTER JOIN BalanceForgiveness ON Bond.ID = BalanceForgiveness.BondID
    LEFT OUTER JOIN Powers ON Bond.ID = Powers.Bond
    LEFT OUTER JOIN Charge ON Powers.Surety = Charge.PowerSurety
    AND Powers.PowerPrefix = Charge.PowerPrefix AND Powers.PowerNumber = Charge.PowerNumber
    LEFT OUTER JOIN ChargeWithoutPower ON Bond.ID = ChargeWithoutPower.ID
    LEFT OUTER JOIN Forfeiture ON Bond.ID = Forfeiture.Bond
    LEFT OUTER JOIN BondFee ON Bond.ID = BondFee.Bond
    GROUP BY Bond.ID
END
ELSE
BEGIN
    RETURN
    SELECT Bond.ID, SUM(Charge.BondAmount) + SUM(ChargeWithoutPower.BondAmount) Amount,
    SUM(Charge.BondPremium) + SUM(ChargeWithoutPower.BondPremium) + SUM(Forfeiture.AmountPaid)
    + SUM(Forfeiture.CostOfApprehension) - SUM(Payment.Amount) - SUM(BalanceForgiveness.AmountForgiven) Balance
    FROM Bond LEFT OUTER JOIN UserAgency ON Bond.Agency = UserAgency.Agency
    LEFT OUTER JOIN Payment ON Bond.ID = Payment.Bond
    LEFT OUTER JOIN BalanceForgiveness ON Bond.ID = BalanceForgiveness.BondID
    LEFT OUTER JOIN Powers ON Bond.ID = Powers.Bond
    LEFT OUTER JOIN Charge ON Powers.Surety = Charge.PowerSurety
    AND Powers.PowerPrefix = Charge.PowerPrefix AND Powers.PowerNumber = Charge.PowerNumber
    LEFT OUTER JOIN ChargeWithoutPower ON Bond.ID = ChargeWithoutPower.ID
    LEFT OUTER JOIN Forfeiture ON Bond.ID = Forfeiture.Bond
    LEFT OUTER JOIN BondFee ON Bond.ID = BondFee.Bond
    WHERE UserAgency.Username = @Username
    GROUP BY Bond.ID
END

我正在使用C#访问此过程,如下所示:

bondingData.Merge(getBondAmountsAdapter.GetData(currentUser.Username));

这是我添加的测试行,看看是否返回了任何结果:

MessageBox.Show("Bond Count A: " + bondingData.Bond.Count.ToString() + "\r\nBond Count B: " + bondingData.GetBondAmounts.Count.ToString());

当我跑步时,这是我收到的结果:

Bond Count A: 1
Bond Count B: 0

[编辑]

好的,所以这是我解决问题的方法:

ALTER PROCEDURE dbo.GetBondAmounts
(
    @Username varchar(20)
)
AS
    SELECT Bond.ID, dbo.GetBondTotal(Bond.ID) Total, dbo.GetBondBalance(Bond.ID) Balance
    FROM Bond LEFT OUTER JOIN
    UserAgency ON Bond.Agency = UserAgency.Agency
    WHERE UserAgency.Username = @Username
    OR EXISTS (SELECT * FROM Users WHERE Username = @Username AND Admin = 1)
    GROUP BY Bond.ID

这是在此处调用的2个存储函数。不确定它的效率如何,但不会有那么多的付款或任何与个人债券相关的东西。当程序有大量记录时,它可能会变慢。

功能1:

ALTER FUNCTION dbo.GetBondTotal
(
@BondID bigint
)
RETURNS money
AS
BEGIN
    DECLARE @PowersTotal AS money;
    DECLARE @ChargesTotal AS money;
    DECLARE @BondFeeTotal AS money;
    DECLARE @ForfeitureCosts AS money;
    SELECT @PowersTotal = SUM(BondPremium)
    FROM Charge INNER JOIN Powers ON Charge.PowerSurety = Powers.Surety
    AND Charge.PowerPrefix = Powers.PowerPrefix
    AND Charge.PowerNumber = Powers.PowerNumber
    WHERE Bond = @BondID
    SELECT @ChargesTotal = SUM(BondPremium)
    FROM ChargeWithoutPower
    WHERE BondID = @BondID
    SELECT @BondFeeTotal = SUM(Amount)
    FROM BondFee WHERE Bond = @BondID
    SELECT @ForfeitureCosts = SUM(CostOfApprehension) + SUM(AmountPaid)
    FROM Forfeiture WHERE Bond = @BondID
    RETURN @PowersTotal + @ChargesTotal + @BondFeeTotal + @ForfeitureCosts
END

功能2:

ALTER FUNCTION dbo.GetBondBalance
(
@BondID bigint
)
RETURNS MONEY
AS
    BEGIN
    DECLARE @PowersTotal AS money;
    DECLARE @ChargesTotal AS money;
    DECLARE @BondFeeTotal AS money;
    DECLARE @ForfeitureCosts AS money;
    DECLARE @PaymentTotal AS money;
    DECLARE @AmountForgiven AS money;
    SELECT @PowersTotal = SUM(BondPremium)
    FROM Charge INNER JOIN Powers ON Charge.PowerSurety = Powers.Surety
    AND Charge.PowerPrefix = Powers.PowerPrefix
    AND Charge.PowerNumber = Powers.PowerNumber
    WHERE Bond = @BondID
    SELECT @ChargesTotal = SUM(BondPremium)
    FROM ChargeWithoutPower
    WHERE BondID = @BondID
    SELECT @BondFeeTotal = SUM(Amount)
    FROM BondFee WHERE Bond = @BondID
    SELECT @ForfeitureCosts = SUM(CostOfApprehension) + SUM(AmountPaid)
    FROM Forfeiture WHERE Bond = @BondID
    SELECT @PaymentTotal = SUM(Amount)
    FROM Payment WHERE Bond = @BondID
    SELECT @AmountForgiven = SUM(AmountForgiven)
    FROM BalanceForgiveness WHERE BondID = @BondID
    RETURN @PowersTotal + @ChargesTotal + @BondFeeTotal + @ForfeitureCosts - @PaymentTotal - @AmountForgiven
END

我相信我会创建第三个涵盖金额的函数(Charge.Amount + ChargeWithoutPower.Amount)

2 个答案:

答案 0 :(得分:9)

您在每个部分的开头都有RETURN语句。

一旦命中此语句,查询就会返回,因此SELECT将不会执行,也不会返回任何内容。

要解决此问题,请删除RETURN语句。

答案 1 :(得分:3)

我怀疑您认为该过程需要返回结果集。实际上,过程只能“返回”一个整数。它们可以设置输出参数,所选的任何结果集都将放在输出流中,但它们与RETURN语句无关。

另请注意,您的第二个查询WHERE子句有效地将第一个LEFT JOIN转换为INNER JOIN。

您可以将这两个查询合并到一个可能更易于维护的查询中,并且您可以消除对单独的位变量和管理查询的需要。请注意,组合版本可以更容易维护,但是可以有一个次优的执行计划,因为这两种情况实际上可能需要非常不同的执行计划。它也可能容易受到参数嗅探的影响,因此您可能希望使用“优化未知”选项和/或将它们分成两部分 - 这是一种权衡。很多时候,当我看到重复的代码可能更容易在一个地方维护时,我不得不权衡。有时,重复连接可以转换为视图或内联表值函数。

我认为它减少到了这个:

ALTER PROCEDURE dbo.GetBondAmounts
(
    @Username varchar(20)
)
AS
BEGIN
    SELECT Bond.ID
           ,SUM(Charge.BondAmount)
             + SUM(ChargeWithoutPower.BondAmount) AS Amount
           ,SUM(Charge.BondPremium)
             + SUM(ChargeWithoutPower.BondPremium)
             + SUM(Forfeiture.AmountPaid)
             + SUM(Forfeiture.CostOfApprehension)
             - SUM(Payment.Amount)
             - SUM(BalanceForgiveness.AmountForgiven) AS Balance
    FROM Bond
    LEFT OUTER JOIN UserAgency ON Bond.Agency = UserAgency.Agency
    LEFT OUTER JOIN Payment ON Bond.ID = Payment.Bond
    LEFT OUTER JOIN BalanceForgiveness ON Bond.ID = BalanceForgiveness.BondID
    LEFT OUTER JOIN Powers ON Bond.ID = Powers.Bond
    LEFT OUTER JOIN Charge ON Powers.Surety = Charge.PowerSurety
        AND Powers.PowerPrefix = Charge.PowerPrefix
        AND Powers.PowerNumber = Charge.PowerNumber
    LEFT OUTER JOIN ChargeWithoutPower ON Bond.ID = ChargeWithoutPower.ID
    LEFT OUTER JOIN Forfeiture ON Bond.ID = Forfeiture.Bond
    LEFT OUTER JOIN BondFee ON Bond.ID = BondFee.Bond
    WHERE UserAgency.Username = @Username
        OR EXISTS (SELECT * FROM Users WHERE Username = @Username AND Admin = 1)
    GROUP BY Bond.ID
END

(注意,在这个简化点上,我强烈考虑使用内联表值函数而不是过程,这类似于参数化视图,比存储过程更灵活)

让我担心你的分组和加入方式。

如果您有多个付款和没收(或由Bond.ID链接的任何其他表格)附加到债券,那么您将获得无意的交叉连接,将这些值相乘,然后将它们相加,得到不正确的结果。< / p>

我怀疑你需要做这样的事情才能进行分组 - 注意我已经在子查询中完成了分组并用相同的名称重新别名:

ALTER PROCEDURE dbo.GetBondAmounts
(
    @Username varchar(20)
)
AS
BEGIN
    SELECT Bond.ID
           ,Charge.BondAmount
             + ChargeWithoutPower.BondAmount AS Amount
           ,Charge.BondPremium
             + ChargeWithoutPower.BondPremium
             + Forfeiture.AmountPaid
             + Forfeiture.CostOfApprehension
             - Payment.Amount
             - BalanceForgiveness.AmountForgiven AS Balance
    FROM Bond
    LEFT OUTER JOIN UserAgency ON Bond.Agency = UserAgency.Agency
    LEFT OUTER JOIN (
        SELECT Bond, SUM(Amount) AS Amount
        FROM Payment
        GROUP BY Bond
    ) AS Payment ON Bond.ID = Payment.Bond
    --- etc..
    WHERE UserAgency.Username = @Username
        OR EXISTS (SELECT * FROM Users WHERE Username = @Username AND Admin = 1)
END