好的,我在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)
答案 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