1

好的,所以我的 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 个存储函数。不确定它的效率如何,但不会有那么多付款或与单个债券相关的任何事情。当程序有很多记录时,它可能会变慢。

功能一:

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

功能二:

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)

4

2 回答 2

9

您在RETURN每个部分的开头都有一个声明。

查询将在此语句被命中时立即返回,因此SELECT不会执行,也不会返回任何内容。

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

于 2012-05-16T15:42:37.410 回答
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 链接的其他表格)附加到一个债券,那么您将得到一个无意的交叉连接,将这些值相乘然后相加,得到不正确的结果。

我怀疑你需要做这样的事情来做你的分组 - 请注意,我已经在子查询中完成了分组并用相同的名称重新命名它们:

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
于 2012-05-16T15:54:40.880 回答