使用存储过程进行计算

时间:2008-10-06 16:48:19

标签: sql-server database stored-procedures

我目前正在开发一个项目,该项目将在MS SQL数据库中存储有关客户的特定财务信息。之后,我们的用户需要能够查询数据库以基于某些标准(例如,大于特定大小的客户端,特定地理位置的客户端)从客户端返回数据,并将其总计用作基准。我们的财务软件将使用脚本访问数据库。

我目前正在编写数据库的存储过程。我计划做的是根据可以使用的不同类型的标准编写几个不同的存储过程。他们将返回客户编号。

我遇到的实际问题是检索数据的方法。我需要对客户端数据进行几种不同的计算。更好的做法是让不同的存储过程根据客户端编号进行计算并返回结果,还是让存储过程返回有关客户端的所有信息并在脚本中执行计算更好?

性能可能是个问题,因为数据库中会有很多客户端,所以我希望这个方法合理有效。

10 个答案:

答案 0 :(得分:3)

有趣的是,数据仓库人员一直这样做。他们经常使用最简单的SQL(SELECT SUM / COUNT ... GROUP BY ...)并在报表编写工具中使用数据库中完成工作。

我认为您应该获得数据仓库工具包的副本,并了解如何以更简单的方式完成此操作。更灵活,可能更具可扩展性。

答案 1 :(得分:1)

我认为这很大程度上与所涉及的数据和您正在进行的操作有关。我通常会发现,当进行减少DB(分组和聚合)返回大小的计算时,在DB中执行它会更有效。当你开始做其他计算时,它并不是那么明确。

答案 2 :(得分:1)

在大多数情况下,就像我认为你所描述的那样,使用存储过程更有效,但是有些边缘情况并非如此。最好的答案是尝试两种方式并进行一些负载测试,以确定哪种方法最有效。

答案 3 :(得分:1)

这实际上取决于操作。很可能将这些内容作为数据库中的计算列,在视图或SP中预先计算(或使用UDF),在ETL或汇总阶段单独计算和存储,或让客户端执行。

我会避免让客户做任何事情,除非你知道你可以一致地控制计算,这样他们就不会犯错误(所有独立完成工作的报告作者都是灾难的处方),特别是如果计算规则可能会改变。

答案 4 :(得分:0)

SQL Server是一个关系数据存储。我建议每次计算一个存储过程,它对客户端进行相同的计算。只需传入ID作为参数即可获得客户的特定结果。

“性能可能是一个问题,因为会有很多客户端”......这取决于表的规范化和索引方式。除非您完全了解索引到底是什么,否则不要对每列进行索引。

编辑〜查看您的计算。有些可以卸载到前端客户端。

答案 5 :(得分:0)

从您的问题中可以看出,最有效的方法是在SP中执行所有计算并将单个(?)结果返回给您的脚本。

如果您决定在脚本中进行处理,则应确保将检索的数据限制为仅在必要时进行处理,并确保尽可能少地往返数据库。

答案 6 :(得分:0)

如果确定计算结果的业务规则容易发生变化,请不要在存储过程中对此进行编码。更好的地方是控制器(MVC中的C)。规则是可插拔的,易于更改。

同样从可扩展性的角度来看,复制app-servers并不像复制数据库服务器那么昂贵。

这并不意味着不能使用存储过程。报告生成将是使用存储过程完成计算的理想候选者。

答案 7 :(得分:0)

考虑是否需要数据仓库。针对报告进行了优化的数据库与针对数据输入进行了优化的数据库非常不同。

答案 8 :(得分:0)

你说的一切都让我觉得你应该考虑仓储你的数据。如果您发现自己正在针对OLTP系统编写复杂的连接并需要进行额外的计算(听起来像是这样),那么对数据进行非规范化并将预先计算的聚合存储在仓库中将使您的生活变得更加简单。

尽管每个人似乎都想要向您提供大量的书籍和产品,但如果您的问题空间是离散的并且您的源数据得到妥善管理,那么任务通常是微不足道的。

答案 9 :(得分:-1)

您可以在存储过程中进行任何计算并返回数据。像存储过程这样的利息计算需要大量的计算。

您必须使用其他表格数据计算数据。

我们可以在SP中做,

Declare @SUMAmount decimal(12,3) 

- 也宣布@ A,@ B等

Select @SUMAmount= SUM(ISNULL(@A,0)+ISNULL(@B,0)+ISNULL(@C,0)+ISNULL(@D,0))

Select @SUMAmount= SUM((ISNULL(@A,0)+ISNULL(@B,0))*(ISNULL(@C,0)-ISNULL(@D,0)))

根据您的要求,您可以提供条件。

ISNULL用于检查数据是否为NULL然后返回0.使用Null值进行计算是不可能的,所以最好给出ISNULL条件。

Select A,B,SUM(C),D From TableName
Where SUM(C)>0
Group By A,B,D

此处聚合函数和非聚合函数都存在,因此您必须使用Group By。 您可以根据您的条件获得值,例如:“SUM(C)> 0”。你也可以在Group By之后使用。

 Declare @TotalNoofDays  int
 @TotalNoofDays = DATEDIFF(d, fromdate, todate) 

使用此函数查找天数。

你可以使用像

这样的条件
if @DueAmount >=0
BEGIN
IF @DiscountFlag = 1
BEGIN
SET @DueIntAmount   = 0
END
ELSE
   BEGIN
     SET @DueIntAmount  = ((@DueAmount*(@IntRateOnDue/100))/365)*@NoofDays
   END
  SET @ExcessInterestAmount = 0
END
ELSE
BEGIN
SET @DueIntAmount   = 0
SET @ExcessInterestAmount = ((@DueAmount*(@IntRateOnDeposit/100))/365)*@NoofDays
 END

您可以在存储过程中进行类似的计算。

如果你想逐个计算记录数,那么你可以在循环时使用临时表..

 Create Proc NewLearningProcedure
 (
   @Name Varchar(50),
   @Date DateTime
 )
 AS
 Begin

Declare @Temp Table
(
   ID int Identity(1,1),
   Name Varchar(50),
   Date DateTime
)

Insert Into @Temp
Select @Name,@Date

Declare @i int
set @i=10

While @i>0
Begin
  Insert Into @Temp
  Select @Name+CAST(@i as varchar(50)),@Date

  Set @i=@i-1
 End


 Select * from @Temp


 End

就像你可以用存储过程做任何事情一样。