这个存储过程还可不可以优化?pengdali(大力 V2.0)、 zjcxc(邹建)等高手请进!!!

cnwhm 2003-08-21 01:31:29
在我现有的数据库中有以下若干表:
   单位表(序号,单位名称,模块号)
另有大量的类似的下面结构的表
   产品表1(单位,品名,日产,月产,年产),产品表2(单位,.......
   其中产品表.单位=单位表.序号
   

不同的模块对不同的(产品表)有录入权限,且一个模块可包含多个不同的单位。现要做下面的统计:
分别根据统计的日期,求出月产,年产;
其逻辑为:
1、若为当月1日,则将产品表1中的月产赋为当日的日产,年产则为上日的年产+今日的日产。
2、若为当年的1日,则将产品表1中的月产和年产均赋为当日的日产。
3、其于日子,月产=昨日月产+今日日产,年产=昨日年产+今日日产。

现我是这样实现的
将单位表存入表变量,通过游标顺序读取,再通过表变量(模块号)判断该单位对哪张表有录入权限,若有,则调用另一存储过程:Cal_Add(传递参数:表名,单位序号),汇总该单位各种产品的当日的月产、年产。
我的Cal_Add是这样工作的:
根据传来的表名,单位序号,并取出今日的日期。
1,创建视图1和2分别存储该单位昨日和今日的数据。
2,根据今日的日期执行上述的逻辑,在视图中进行计算,更新表记录。

示例代码见下:
--用于存储临时数据(序号,单位名称,模块号)
declare @temptable table(xuhao int,dwmc varchar(30),code int);
--定义游标用到的变量 @tempid (序号) @unitname (单位名称) @tempcode (模块号)
declare @tempid int
declare @unitname varchar(30)
declare @tempcode int
declare @icount int

declare @today datetime
declare @yesterday datetime

set @today=convert(varchar(10),getdate(),120)
set @yesterday=convert(varchar(10),dateadd(dd,-1,getdate()),120)

insert into @temptable
select 序号,单位名称,模块号 from 系统_单位表

declare mycursor cursor for select xuhao,dwmc,code from @temptable

--打开游标
open mycursor
fetch next from mycursor
into @tempid,@unitname,@tempcode
--进入表循环
while @@fetch_status=0
begin
if(@tempcode=8 or @tempcode=7 or @tempcode=10 or @tempcode=6)
exec('cal_huizong ''产品表1'','+@tempid)
--移动游标到下一条记录
fetch next from mycursor
into @tempid,@unitname,@tempcode
end
--关闭游标
close mycursor
--释放游标
deallocate mycursor
--清除临时表数据
delete from @temptable

Cal_Add:

declare @today varchar(10)
declare @yesterday varchar(10)
set @today=convert(varchar(10),getdate(),120)
set @yesterday=convert(varchar(10),dateadd(dd,-1,getdate()),120)

if(@TableName='产品表1')
begin
IF EXISTS(SELECT * FROM sysobjects WHERE ID = OBJECT_ID('OldDateView'))
DROP VIEW OldDateView
IF EXISTS(SELECT * FROM sysobjects WHERE ID = OBJECT_ID('NewDateView'))
DROP VIEW NewDateView
--创建视图,分别保存新旧数据
exec('CREATE VIEW OldDateView AS SELECT 日产,月产,年产,品名 FROM 产品表1 WHERE 单位='+@UnitID+' AND 日期='''+@yesterday+'''')
exec('CREATE VIEW NewDateView AS SELECT 日产,月产,年产,品名 FROM 产品表1 WHERE 单位='+@UnitID+' AND 日期='''+@today+'''')
if(day(getdate())=1)
begin
UPDATE NewDateView SET 月产 = 日产
end
else
begin
UPDATE NewDateView SET 月产 = 日产 + ISNULL((SELECT 月产 FROM OldDateView WHERE NewDateView.品名 = OldDateView.品名),0)
end
if(getdate()=(year(getdate())+'01'+'01'))
UPDATE NewDateView SET 年产 = 日产
else
UPDATE NewDateView SET 年产 = 日产 + ISNULL((SELECT 年产 FROM OldDateView WHERE NewDateView.品名 = OldDateView.品名),0)
DROP VIEW OldDateView
DROP VIEW NewDateView
end


问还有没有办法将上面的存储过程再优化一下或还有什么办法加快执行速度?我现在的表中的记录有上万条,最多的上了十万条。
...全文
65 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
cnwhm 2003-08-21
  • 打赏
  • 举报
回复
谢谢zjcxc(邹建);
我已经清楚了,在存储过程中创建动态视图确实影响了速度,准备将这些创建动态视图的过程创建成表变量或临时表,这样应该会快很多。
zjcxc 元老 2003-08-21
  • 打赏
  • 举报
回复
最好能给出一个完事的数据处理.
cnwhm 2003-08-21
  • 打赏
  • 举报
回复

序号  单位名称    模块
  3 一厂 6
4 二厂 7
5 三厂 6
6 四厂 7
7 公司1 10
8 公司2 10
即模块号是判断单位的类型,例一厂是生产糖果的,所以在保存糖果厂的表中进行计算时就要用模块号来取得单位的序号来做条件。另外我不在表中直接计算是因为要求分单位来计算。

不知道上面的说法大家能理解不?
cnwhm 2003-08-21
  • 打赏
  • 举报
回复

序号  单位名称    模块
  3 一厂 6
4 二厂 7
5 三厂 6
6 四厂 7
7 公司1 10
8 公司2 10
即模块号是判断单位的类型,例一厂是生产糖果的,所以在保存糖果厂的表中进行计算时就要用模块号来取得单位的序号来做条件。另外我不在表中直接计算是因为要求分单位来计算。

不知道上面的说法大家能理解不?
cnwhm 2003-08-21
  • 打赏
  • 举报
回复
谢谢 zjcxc(邹建) 能来!
  我在游标的定义上用临时表是有原因的。因为后面还有存储过程要用到这些数据。如果不用的话,不知会不会对速度有影响?
  另外,用视图来更新表记录的方案可不可取,有没有比这更快的方案?
wenzm 2003-08-21
  • 打赏
  • 举报
回复

尽可能的不用游标!如果可能……
zjcxc 元老 2003-08-21
  • 打赏
  • 举报
回复
单从你给出的数据来看.

不用游标是可以的.但因为没有具体数据,所以也不好写.


不过,在游标定义上,可以不用临时表的.直接定义:

declare mycursor cursor for
select 序号,单位名称,模块号 from 系统_单位表
zjcxc 元老 2003-08-21
  • 打赏
  • 举报
回复
因为你的描述及提供的数据不是太详细.所以仅根据你提出的部分给一点自己的建议:

1.游标的定义不合理.不需要用到临时表,直接定义就行了

declare mycursor cursor for
select 序号,单位名称,模块号 from 系统_单位表


2.单从你上面的语句分析,是否可以不用游标来实现目的.
cnwhm 2003-08-21
  • 打赏
  • 举报
回复
to 8992026(8992026) :
  上面的描述可能存在问题,但下面的示例代码是不会有问题的,我只是想确认一下示例代码部分是可不可以优化的,尤其是我是用视图将有用的数据从表中筛选出来进行操作的,我不知道这样做是不是影响了速度,因为在几天前,这个存储过程的执行速度是非常快的,但从昨天的情况来看,速度慢了下来。也就是上面示例代码部分拖了时间。
  另外你说不用游标,我实在想不出什么办法对表中的记录进行循环读取。请教?
8992026 2003-08-21
  • 打赏
  • 举报
回复
可以不用游标,
但是你的描述很难理解,业务是不是没有了解清楚?
CrazyFor 2003-08-21
  • 打赏
  • 举报
回复
优化索引:

索引与系统性能
索引可以加快数据检索的速度但它会使数据的插入删除和更新变慢尤其是簇索
引数据是按照逻辑顺序存放在一定的物理位置当变更数据时根据新的数据顺序需
要将许多数据进行物理位置的移动这将增加系统的负担对非簇索引数据更新时也需
要更新索引页这也需要占用系统时间因此在一个表中使用太多的索引会影响数据库
的性能对于一个经常会改变的表应该尽量限制表只使用一个簇索引和不超过3~4 个
非簇索引对事务处理特别繁重的表其索引应尽量不超过3 个

索引调整向导Index Tuning Wizard
索引调整向导可以帮助选择并创建一个最优化的索引集合以提高数据库的性能
要使用索引调整向导需要一个工作负荷记录Workload 工作负荷记录由SQL 脚
本或SQL Server Profiler 创建的存储在文件或表中的跟踪组成如果没有现存的针对要进
行索引调整的数据库或表的工作负荷记录可以通过SQL Server Profiler 来创建一个其
具体方法请参见第19 章中SQL Server Profiler 的用法可以用Sample 1 – TSQL 跟踪定
义来创建或新建一个跟踪索引调整向导可以使用查询优化器根据工作负荷记录分析索引
的性能并提出相应的调整建议可以立即让系统根据建议修改索引也可以将任务列入
计划以后再创建

34,587

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧