您的位置:首页 > 编程语言 > Delphi

由Delphi程序改写Sql(2000)的存储过程

2020-02-15 13:57 471 查看
各位前辈大家好,请帮我解决一个棘手的问题,我不会写SQL存储过程,现在一个Delphi程序执行非常的慢,想将其用SQL存储过程替代
请各位前辈帮忙,在线等
主要 资料表单有 MRPplan,MRPplantou (生产单资料表), mrpplanpsn(物料需求单资料表),bom(BOM 资料表) 四个,
其中关联字段为Psn(生产单号),materysn(物料编号)

从 MRPplan 中依据Psn查找资料进行循环,
a:假如mrpplanpsn 中有对应Psn的materysn则将MRPplan.planshu数量加到 mrpplanpsn.gr上
b:假如mrpplanpsn 中没有有对应Psn的materysn则将MRPplan中相关资料写入 mrpplanpsn
c:进行对MRPplan.materysn 资料进行BOM分解,若有子项则对子项进行以上动作

1: Select psn.materysn,planshu from MRPplan where psn=xxx (xxx 为传入参数),对应数据集为rsq1
If rsq1.RecordCount> 0 then
Begin
For I:=1 To rsq1.RecordCount Do
Begin
fstr:=rsq1.materysn
Select * From mrpplanpsn where materysn=fstr and psn=xxx (xxx 为传入参数),对应数据集为rst1
If rst1.RecordCount> 0 Then 将对应 rst1.gr=rst1.gr rsq1.planshu
Else
Begin
rst1.Append //新写入对应内容
rst1.materysn=rsq1.materysn
rst1.gr=rsq1.planshu //数量
rst1.consigndate=rsq1.consigndate //交获日期
...
End;

进行BOM资料对应查找,rsq2.SQL.Add('select materysn from bom where fmaterysn=fstr)
If Rsq2.RecordCount Then SGmaterysn(Fstr;rsq1.planshu) 进行循环
Rsq2.Next
End //For I:=1 To rsq1.RecordCount Do
End;


SGmaterysn 过程如下:

select materysn,useshu from bom where fmaterysn=Fstr and useshu> 0
n:=Rsq2.RecordCount
If n > 0 Then
Begin
For i:= 1 To n do
begin
Fstr=Rsq2.Materysn
planshu:=Rsq2.Materysn
select materysn,gr,fu,psn,consigndate,remark from mrpplanpsn where materysn=Rsq2.Materysn and

psn=xxx

If rst2.RecordCount > 0 Then 则将对应 rst2.gr=rst2.gr rsq2.planshu
Else
Begin
rst2.Append //新写入对应内容
rst2.materysn=rsq2.materysn
rst2.gr=rsq2.planshu
rst2.consigndate=rsq2.consigndate //交获日期
...
End;

进行BOM资料对应查找,rsq2.SQL.Add('select materysn from bom where fmaterysn=fstr)
If Rsq2.RecordCount > 0 Then SGmaterysn(Fstr;planshu) 进行递归循环
SGmaterysn(Fstr;planshu);
rsq2.Next ;
end; //For i:= 1 To n do
end;//If n > 0 Then

网友回复:看着真累
网友回复:其实看看前面一小段就大概明白了,后面是伪代码,加强说明的.麻烦大哥看看,帮帮忙.谢谢
网友回复:请高手支招啊.看看前面几行就大概明白了
网友回复:1.BOM表中有个字段是 fmaterysn ? 记录父级materysn?
2.MRPplan,MRPplantou 这两个表什么关系?


网友回复:大体写了一个流程
主要的思路是先循环出所有的materysn
再更新,而不是找一层,更新一层
MRPplantou 表没有用上,我估计可能MRPplan,MRPplantou 两个表要关联起来使用吧?
这个你自己改改就行

SQL code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/







create proc p_1

@Psn varchar(100) --改成你自己的类型

as

begin

--建立临时表(跟你的MRPplan表结构一样就行)

declare @MRPplan table

(

Psn varchar(100),

materysn varchar(100),

planshu int,

....

)



--根据psn导入数据

insert into @MRPplan(...)

select *

from MRPplan

where Psn = '你的参数'



--循环导入子项

while (@@rowcount > 0)

begin

insert into @MRPplan(...)

select a.*

from MRPplan a inner join bom b on a.materysn = b.materysn

inner join @MRPplan c on b.fmaterysn = c.materysn

where a.materysn not in (select distinct materysn from @MRPplan)

end



--有对应的话就更新

update a

set a.gr = a.gr b.planshu

from mrpplanpsn a inner join @MRPplan b

on a.psn = b.psn and a.materysn = b.materysn



--没有对应的话就插入

insert into mrpplanpsn(....)

select ...

from @MRPplan a left join mrpplanpsn b

on a.psn = b.psn and a.materysn = b.materysn

where b.materysn is null



end
***********************************************
楼主假如看了上面的思路还是没法下手的话,建议楼主把四个表的结构贴出来,
每个表再抓20条数据出来,然后告诉大家你想要的结果,以及其中的算法

这样的话马上就会有人给你答案的
网友回复:我先测试看看 真是感激不尽
网友回复:仍然没有解决 期待帮忙 谢谢
资料表结构如下:

MRPplantou 生产单表头

psn varchar(20) NOT NULL 生产单号
rev smallint(2) NOT NULL 版本号
makeren varchar(20) NOT NULL 制单人
makedate datetime(8) NOT NULL 制单日期
sureren varchar(20) NOT NULL 审核人
suredate datetime(8) NOT NULL 审核日期
state int(4) NOT NULL 审核状态 (0:未审核;1:已删除;2:已审核;3:已算毛需求;4:已算可用量;5:已算净需求 6:净需求已审核 8:

已结单 )

psn 20080104 生产单号


MRPplan 生产单表身

line smallint(2) NOT NULL 项次
psn varchar(20) NOT NULL 生产单号
materysn varchar(30) NOT NULL 物料编号
planshu numeric NOT NULL 批量 生产数量
consigndate smalldatetime(4) NOT NULL 交货日期
remarks varchar(50) NULL 备注

Psn 20080104 (生产单号)
materysn 38912 (产品编号)
planshu 100 (生产数量)


BOM 基本信息
fmaterysn char (30) 货号编号
materysn char (30) 物料编号
son char (30)
useshu real (4) 用量
unit varchar (10) 单位


fmaterysn materysn useshu unit

38912 38912-1 10 pcs
38912-1 38912-1-1 10 pcs
38912 38912-2 10 pcs
38912-2 38912-2-1 10 pcs
38912-1 38912-1-2 10 pcs


mrpplanpsn MRP需求计算档

psn varchar(20) NOT NULL 生产单号
materysn char (30) 物料遍号
son char (1)
gr numeric(9) NOT NULL 毛需求 (初始植为MRPPlan的Planshu 批量数 )
fu numeric(9) NULL 父阶冲销
stocks numeric(9) NULL 在库量
sastocks numeric(9) NULL 安全库存量
sr numeric(9) NULL 在途量
al numeric(9) NULL 保留量
ky numeric(9) NULL 可用量
nr numeric(9) NULL 净需求
consigndate datetime NOT NULL 需求日期
remark varchar (200) 备注



网友回复:我参照写了一些 但是执行很慢 等了很久很久不见结果 ,请帮我看看
use yw
go

if exists(select name from sysobjects where name ='bom_level_ext1' and type='p') --判定是否存在该过程,存

在则删除
drop proc dbo.bom_level_ext1
go

create procedure dbo.bom_level_ext1 --创建过程
@tmppsn varchar(20) --传入参数

--with encryption
as --创建变量
declare @min_no varchar(20)

declare @rows_count integer

select @min_no = ''

create table #t_psn(psn varchar(20), materysn varchar(50) null,planshu float,consigndate

datetime,flag char(1) )

create index idex1 on #t_psn(materysn)

insert into #t_psn (psn, materysn,planshu,consigndate,flag)
select psn,materysn,isnull(planshu,0),consigndate ,'N' from MRPplan where psn=@tmppsn --传入PSN 合同

编号

select @rows_count = count(#t_psn.materysn) from #t_psn --查询#t_psn 资料笔数

if (@rows_count > 0 )
begin
select @min_no =min(#t_psn.materysn) from #t_psn where #t_psn.flag = 'N'
while not(@min_no is null or @min_no ='')
begin
--插入临时表格数据
insert into #t_psn(materysn,planshu,flag) --对BOM查找 看是否有子项
select dbo.bom.materysn,isnull(dbo.bom.useshu,0),'N'
from dbo.bom
where dbo.bom.fmaterysn = @min_no
******************************************
end


update #t_psn set #t_psn.flag = 'Y' where #t_psn.materysn = @min_no and #t_psn.flag='N'
select @min_no =min( #t_psn.materysn) from #t_psn where flag = 'N'

end



-- drop table #t_pno
select * from #t_psn order by materysn
--select * from #t_materysn
go

--grant all on dbo.bom_level_ext to users --赋权
--go



网友回复:--这里插入临时表的flag列的数据都是'N'
insert into #t_psn (psn, materysn,planshu,consigndate,flag)
select psn,materysn 20000 ,isnull(planshu,0),consigndate ,'N'
from MRPplan
where psn=@tmppsn --传入PSN 合同编号

--这里判定有没有数据没有错,不过可以改为判定@@rowcount
select @rows_count = count(#t_psn.materysn) from #t_psn --查询#t_psn 资料笔数

if (@rows_count > 0 )
begin
select @min_no =min(#t_psn.materysn) from #t_psn where #t_psn.flag = 'N'
--这里判定是也是记录数吧?上面不是已经判定了吗?为什么要再一次判定?
--而且为什么要加条件呢,上面你插入的数据,只要有数据,就是'N'了
--这个while是个死循环吧,假如条件满足的话,在循环体中间并没有重新对变量进行赋值,所以会一直执行下去 while not(@min_no is

null or @min_no ='')
begin
--插入临时表格数据
insert into #t_psn(materysn,planshu,flag) --对BOM查找 看是否有子项
select dbo.bom.materysn,isnull(dbo.bom.useshu,0),'N'
from dbo.bom
where dbo.bom.fmaterysn = @min_no
end


update #t_psn set #t_psn.flag = 'Y' where #t_psn.materysn = @min_no and #t_psn.flag='N'
select @min_no =min( #t_psn.materysn) from #t_psn where flag = 'N'

end

网友回复:我的本来意思是第一次插入 状态标志 Flag='N',满足条件后将Flag='Y'
循环判定 while 中的参数 @min_no 前面已经赋值
网友回复:--这两句似乎也有点问题,@min_no 是查询出的某个materysn值吧,楼主为什么要对每个materysn逐条处理呢?
这个不能放在一起进行处理?
没看懂业务,呵呵,猜得

update #t_psn set #t_psn.flag = 'Y' where #t_psn.materysn = @min_no and #t_psn.flag='N'
select @min_no =min( #t_psn.materysn) from #t_psn where flag = 'N'

网友回复:循环判定while中的参数@min_no前面已经赋值

对阿,就是因为前面已经赋值了

所以比如@min_no = '112233',那么它不是null,也不为空('')
然后就执行while里的语句
执行完了以后一看,@min_no 值还是 '112233',
然后就又执行一次。。。
这不就是死循环嘛?
网友回复:下班了,明天来关注! :)
网友回复:要已manterysn 作为条件去BOM 中查找是否有子项 有的话继续循环
网友回复:也就是要将 MRPplan.materysn 的产品38912 进行分解,分解依据是产品的BOM表, 计算出每个物料的用量,将其结果写入

mrpplanpsn 物料需求计算表格
网友回复:要已manterysn 作为条件去BOM 中查找是否有子项 有的话继续循环

--那这样的思路有问题吗?当然可能关联条件是有问题的,具体的要楼主自己分析
--循环导入子项
while (@@rowcount > 0)
begin
insert into @MRPplan(...)
select a.*
from MRPplan a inner join bom b on a.materysn = b.materysn
inner join @MRPplan c on b.fmaterysn = c.materysn
where a.materysn not in (select distinct materysn from @MRPplan)
end

楼主说这个思路不行,也要说出什么地方不行来吧 。。。。
网友回复:也就是要将 MRPplan.materysn 的产品38912 进行分解,分解依据是产品的BOM表, 计算出每个物料的用量,将其结果写入

mrpplanpsn 物料需求计算表格
************************************
过程是不是这样的???

select * from bom where fmaterysn = '38912'
比如结果集中有两种物料
3891201 3891202
那就判定mrpplanpsn 表中有没有,有就更新,没有就插入

然后再看看3891201 3891202在bom表中有没有子物料,有的话再重复



网友回复:是的,的确是这样.一直循环到 BOM 中没有相关资料为止
网友回复:冷箫轻笛 有在吗? 继续请教问题.昨天没有上班
网友回复:我略懂DELPHI,干脆你要做什么,直接给出来,给出表结构就OK
网友回复:资料表结构如下:
我要做的事情就是要将MRPplan 中的产品依据BOM进行分解,然后将其资料与 mrpplanpsn (物料需求表)进行比对,假如有相同条件资料就对数

量想加 否则就新增. 比对条件是 PSN,Materysn 两个要害字,MRPplan跟BOMDE的关联字段为materysn,fmaterysn.


MRPplantou 生产单表头

psn varchar(20) NOT NULL 生产单号
rev smallint(2) NOT NULL 版本号
makeren varchar(20) NOT NULL 制单人
makedate datetime(8) NOT NULL 制单日期
sureren varchar(20) NOT NULL 审核人
suredate datetime(8) NOT NULL 审核日期
state int(4) NOT NULL 审核状态 (0:未审核;1:已删除;2:已审核;3:已算毛需求;4:已算可用量;5:已算净需求 6:净需求已审核 8:

已结单 )

psn 20080104 生产单号


MRPplan 生产单表身

line smallint(2) NOT NULL 项次
psn varchar(20) NOT NULL 生产单号
materysn varchar(30) NOT NULL 物料编号
planshu numeric NOT NULL 批量 生产数量
consigndate smalldatetime(4) NOT NULL 交货日期
remarks varchar(50) NULL 备注

Psn 20080104 (生产单号)
materysn 38912 (产品编号)
planshu 100 (生产数量)


BOM 基本信息
fmaterysn char (30) 货号编号
materysn char (30) 物料编号
son char (30)
useshu real (4) 用量
unit varchar (10) 单位


fmaterysn materysn useshu unit

38912 38912-1 10 pcs
38912-1 38912-1-1 10 pcs
38912 38912-2 10 pcs
38912-2 38912-2-1 10 pcs
38912-1 38912-1-2 10 pcs


mrpplanpsn MRP需求计算档

psn varchar(20) NOT NULL 生产单号
materysn char (30) 物料遍号
son char (1)
gr numeric(9) NOT NULL 毛需求 (初始植为MRPPlan的Planshu 批量数 )
fu numeric(9) NULL 父阶冲销
stocks numeric(9) NULL 在库量
sastocks numeric(9) NULL 安全库存量
sr numeric(9) NULL 在途量
al numeric(9) NULL 保留量
**************************************
ky numeric(9) NULL 可用量
nr numeric(9) NULL 净需求
consigndate datetime NOT NULL 需求日期
remark varchar (200) 备注

网友回复:假如从上面看下来,能基本了解到我的意图.
假如仁兄肯帮忙,欲看Delphi 的源码,我可以发给你,
谢谢
网友回复:产品依据BOM进行分解
===================
这是什么意思?
网友回复:来了
网友回复:MRPplantou表 是不是没有用阿?
因为你需要的流程是根据psn生产单号查找planshu,然后更新mrpplanpsn表
对吧?
网友回复:bom表中的三个字段

fmaterysn char (30) 货号编号
materysn char (30) 物料编号
son char (30)

哪两个是用来标示父子关系的阿?
网友回复:fmaterysn(父亲) materysn(儿子) useshu(数量) unit(单位)

38912 38912-1 10 pcs
38912-1 38912-1-1 10 pcs
38912 38912-2 10 pcs
38912-2 38912-2-1 10 pcs
38912-1 38912-1-2 10 pcs

产品38912
1:将产品编号38912,PSN=xxx 至 之mrpplanpsn MRP需求计算档查找,没有相关资料 则将将产品编号38912,PSN=xxx 写入

mrpplanpsn中
2:对38912 至BOM 中查找 是否有儿子,有 38912-1,38912-2 两个,分别将其PSN=xxx至mrpplanpsn中比,假如有则进行数量想加否则

新增
3:对38912-1,38912-2至BOM中查找....
网友回复:MRPplantou表 该处可以不考虑,是执行完后将MRPplantou.state 状态标志改写 为已经算料的状态的意思
网友回复:

SQL code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





--把上面的修改了一下,楼主看看还有什么地方不妥

--有地方需要楼主自己改,比如找不到的话,就要插入到mrpplanpsn,但是mrpplanpsn表的列有好多阿。。。

--思路跟楼主的有点不一样:我是先找产品编号38912,然后接着就找他的下级38912-1,38912-2,

--循环取到最低级,再进行数据处理。这样的效率肯定会更好,但是不知道会不会符合楼主的需求



create proc P_UpdateMrpplanpsn

@Psn varchar(100) --改成你自己的类型

as

begin

--建立临时表

declare @MRPplan table

(

Psn varchar(100),

materysn varchar(100),

planshu int

)



--根据psn导入一级数据

insert into @MRPplan(psn,materysn,planshu)

select psn,materysn,planshu

from MRPplan

where Psn = @Psn



--循环导入子项

while (@@rowcount > 0)

begin

insert into @MRPplan(psn,materysn,planshu)

select a.psn,a.materysn,a.planshu

from MRPplan a inner join bom b on a.materysn = b.materysn

inner join @MRPplan c on b.fmaterysn = c.materysn

where not exists (select 1 from @MRPplan where psn = a.psn and materysn = a.materysn)

end



--有对应的话就更新

update a

set a.gr = a.gr b.planshu

from mrpplanpsn a inner join @MRPplan b

on a.psn = b.psn and a.materysn = b.materysn



--没有对应的话就插入

--这个就看你具体的需求了,因为mrpplanpsn表还有其他的列,这里并不知道取值方法

insert into mrpplanpsn(psn,materysn,gr)

select a.psn,a.materysn ,a.planshu

from @MRPplan a left join mrpplanpsn b

on a.psn = b.psn and a.materysn = b.materysn

where b.materysn is null

end





网友回复:先测试看看,真心感谢 冷箫轻笛.
网友回复:@@rowcount 怎么没有赋值啊,他应该是谁的值
网友回复:@@rowcount 是系统变量,记录的是上一条sql语句执行后对数据库影响的行数
网友回复:MRPplan中 的materysn 可能只有2笔
但经过BOM分解后可能有50笔 ,所以 marplan.materysn=bom.materysn 应该是不对的
比如Mrpplan 只有38912 一笔
而由此产品 38912 分解出来的物料则有 38912,38912-1,38912-2,38912-1-1,38912-1-2,38912-2-1,38912-2-2
等等.
网友回复:对阿,分解以后确实可能有很多笔
但是楼主别忘了,marplan.materysn=bom.materysn是写在循环里的

38912是在循环的上一步查到的,
循环中第一次查的是38912-1,38912-2
第二次查的是38912-1-1,38912-1-2,38912-2-1,38912-2-2
。。。。

为什么会有问题呢?

网友回复:结果是写到@MRPplan 中吧,我最后用了一条 select * from @MRPplan 语句
我测试了,结果不对 但是不知原因
***********************************
===========================
他的子项38912-1,38912-2,38912-1-1,38912-1-2,38912-2-1,38912-2-2
在Mrpplan表里没有??????
网友回复:是的,Mrpplan中只有38912一笔,但该产品进行分解在BOM中是有多笔的
网友回复:少什么记录?
楼主可以这样调试:
注重:一定要一步一步的执行,每执行一步就查看数据是否正确
这样可以查找出问题出在什么地方了

SQL code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





--1.表变量改成临时表

create table #MRPplan

(

Psn varchar(100),

materysn varchar(100),

planshu int,

)



--2.根据psn导入数据

insert into #MRPplan(psn,materysn,planshu)

select psn,materysn,planshu

from MRPplan

where Psn = '你的参数'



--3.查询数据,看看数据是否正确,假如正确就执行第4步

select * from #MRPplan



--4.导入子项

insert into #MRPplan(psn,materysn,planshu)

select a.psn,a.materysn,a.planshu

from MRPplan a inner join bom b on a.materysn = b.materysn

inner join #MRPplan c on b.fmaterysn = c.materysn

where not exists (select 1 from #MRPplan where psn = a.psn and materysn = a.materysn)



--5.执行第3步







网友回复:是的,Mrpplan中只有38912一笔,但该产品进行分解在BOM中是有多笔的
----------------------------
哦,这样啊
那你已开始说的是:
a:假如mrpplanpsn 中有对应Psn的materysn则将MRPplan.planshu数量加到 mrpplanpsn.gr上
b:假如mrpplanpsn 中没有有对应Psn的materysn则将MRPplan中相关资料写入 mrpplanpsn
c:进行对MRPplan.materysn 资料进行BOM分解,若有子项则对子项进行以上动作

这样的话c步骤中的子项的操作跟父项其实是不一样的阿!
网友回复:请问如何单步执行.谢谢
网友回复:本来要用MRPplan.planshu字段来更新mrpplanpsn.gr

但是子项没有planshu,要用哪个字段来更新阿?
网友回复:--你是在查询分析器里测试吧?
选中你要执行的步骤语句,然后再点执行,不要直接点执行或者全选以后执行。
网友回复:Bom 中的数量是useshu real (4) 用量

请问如何单步执行.谢谢
网友回复:我指是一条一条语句执行
网友回复:那子项中的psn是否也是取的开始传入的@Psn变量呢?
假如是的话,把循环改成这样:

SQL code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





--循环导入子项

while (@@rowcount > 0)

begin

insert into @MRPplan(psn,materysn,planshu)

select @Psn,a.materysn,a.useshu

from bom a inner join @MRPplan b on a.fmaterysn = b.materysn

where not exists (select 1 from @MRPplan where psn = @Psn and materysn = a.materysn)

end





网友回复:先把循环改了以后测试一下吧,不行的话再单步测试
网友回复:
请问如何单步执行.谢谢
我指是一条一条语句执行

你指的是调试程序那种单步执行?
这个sqlserver可不支持,呵呵,就得手动一条一条的执行
网友回复:冷箫轻笛 您好:

1: 计算出来的结果是对的,但是有以下两个问题需要解决。恳请继续帮忙。不胜感激

2:结果表中的@MRPplan的materysn 为唯一值

也就是说假如有相同的要进行数量的累加.如下 mrpplanpsn.gr=mrpplanpsn.gr 分解该Bom的父亲数量 * bom.useshu 即为

mrpplanpsn.gr=10(mrpplanpsn.gr 之前的) 传入的materysn*bom.useshu

3:需要写入日期 mrpplay.consigndate日期
网友回复:1.不客气

2.“分解该Bom的父亲数量”

这个值是如何取出来的呢?

3.日期好办,语句的最前面用
declare @date datetime
select @date = consigndate from mrpplan where psn = @psn

就可以了
然后表变量加上这列,插入数据的时候直接插入变量@date就可以了
网友回复:哦,有点明白了,是不是这个意思?
比如:
38912-1,38912-2
子项38912-1-1,38912-1-2,38912-2-1,38912-2-2

假如38912-1的useshu = 10
那么计算38912-1-1 的时候要用10 * useshu ?然后加在mrpplanpsn.gr上,而不是直接加useshu?
网友回复:但是这句又不懂了。。。
即为 mrpplanpsn.gr=10(mrpplanpsn.gr 之前的) 传入的materysn * bom.useshu

网友回复:哦,consigndate 是mrpplan表里的?那同一个psn里不同的物料交货时间不同?
假如这样的话,那子项的consigndate如何来确定?
网友回复:比如 A 是 A1,A2的父亲 ,在BOM 中 为
fmaterysn materysn, useshu
A A 10
A A1 5
A A2 8
而且
mrpplanpsn 中已经有
psn materysn gr, consigndate
20080104 A1 20 2008/01/04

则下一个动作是进行gr累计
mrpplanpsn.gr=mrpplanpsn.gr 10*5
mrpplanpsn.gr=10 10*5
简单的就是说 要做10个桌子,(1个桌子假如要4个脚) 则总脚数为 10 *4 =40
****************************************##########
然后再加其他产品需要这个脚的数目就是该定单或一些产品需要总脚的数目
总脚数据:=之前脚数据 10*40

网友回复:

SQL code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





--再修改

create proc P_UpdateMrpplanpsn

@Psn varchar(100) --改成你自己的类型

as

begin

--建立临时表

declare @MRPplan table

(

Psn varchar(100),

materysn varchar(100),

planshu int,

f_planshu int,

cdate datetime

)



--获取consigndate

declare distinct @date = consigndate from mrpplay where psn = @psn



--根据psn导入一级数据

insert into @MRPplan(psn,materysn,planshu,f_planshu,cdate)

select psn,materysn,planshu,1,@date

from MRPplan

where Psn = @Psn



--循环导入子项

while (@@rowcount > 0)

begin

insert into @MRPplan(psn,materysn,planshu,f_planshu,cdate)

select @Psn,a.materysn,a.useshu,b.planshu,@date

from bom a inner join @MRPplan b on a.fmaterysn = b.materysn

where not exists (select 1 from @MRPplan where psn = @Psn and materysn = a.materysn)

end



--有对应的话就更新

update a

set a.gr = a.gr b.planshu * b.f_planshu

from mrpplanpsn a inner join @MRPplan b

on a.psn = b.psn and a.materysn = b.materysn



--没有对应的话就插入

--这个就看你具体的需求了,因为mrpplanpsn表还有其他的列,这里并不知道取值方法

insert into mrpplanpsn(psn,materysn,gr)

select a.psn,a.materysn ,a.planshu * a.f_planshu

from @MRPplan a left join mrpplanpsn b

on a.psn = b.psn and a.materysn = b.materysn

where b.materysn is null

end







网友回复:fmaterysn materysn, useshu
A A 10
A A1 5
A A2 8
A1 A11 12

那么计算A11的时候是否是 (5*10)*12 ?
假如是的话,上面的语句没有问题,呵呵
网友回复:哦,consigndate 是mrpplan表里的?那同一个psn里不同的物料交货时间不同?
假如这样的话,那子项的consigndate如何来确定?
网友回复:过30了没有?
网友回复:consigndate 一个个固定的值 ,是mrpplan表里的
网友回复:哈哈,过了点点
网友回复:上面的sql有问题,修改中
网友回复:

SQL code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





--楼主,你给的数据库俺用不了,公司的权限管的严,呵呵,自己建了三个表,测试一下,楼主看看

--环境

create table mrpplan

(

psn varchar(20),

materysn varchar(30),

planshu numeric,

consigndate smalldatetime

)

insert into mrpplan(psn,materysn,planshu,consigndate)

select '20080104','38912',100,'2008-02-01'



create table bom

(

fmaterysn char (30), -- 货号编号(父亲)

materysn char (30), --物料编号(儿子)

useshu real , --用量

unit varchar (10) --单位

)

insert into bom(fmaterysn,materysn,useshu,unit) select '38912', '38912-1' , 10, 'pcs'

insert into bom(fmaterysn,materysn,useshu,unit) select '38912-1', '38912-1-1', 10, 'pcs'

insert into bom(fmaterysn,materysn,useshu,unit) select '38912', '38912-2' , 10, 'pcs'

insert into bom(fmaterysn,materysn,useshu,unit) select '38912-2', '38912-2-1', 10, 'pcs'

insert into bom(fmaterysn,materysn,useshu,unit) select '38912-1', '38912-1-2', 10, 'pcs'



CREATE TABLE [dbo].[MRPplanpsn] (

[psn] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,

[materysn] [char] (30) COLLATE Chinese_PRC_CI_AS NOT NULL ,

[son] [char] (1) COLLATE Chinese_PRC_CI_AS NULL ,

[gr] [numeric](14, 4) NULL ,

[fu] [numeric](14, 4) NULL ,

[stocks] [numeric](14, 4) NULL ,

[sastocks] [numeric](14, 4) NULL ,

[sr] [numeric](14, 4) NULL ,

[al] [numeric](14, 4) NULL ,

[ky] [numeric](14, 4) NULL ,

[nr] [numeric](14, 4) NULL ,

[consigndate] [datetime] NULL ,

[remark] [varchar] (200) COLLATE Chinese_PRC_CI_AS NULL

) ON [PRIMARY]

GO



--建立存储过程



create proc P_UpdateMrpplanpsn

@Psn varchar(100) --改成你自己的类型

as

begin

--建立临时表

declare @MRPplan table

(

Psn varchar(100),

materysn varchar(100),

planshu int,

f_planshu int,

cdate datetime

)



--根据psn导入一级数据

insert into @MRPplan(psn,materysn,planshu,f_planshu,cdate)

select psn,materysn,planshu,1,consigndate

from MRPplan

where Psn = @Psn



--循环导入子项

while (@@rowcount > 0)

begin

insert into @MRPplan(psn,materysn,planshu,f_planshu,cdate)

select @Psn,a.materysn,a.useshu,b.planshu * b.f_planshu,b.cdate

from bom a inner join @MRPplan b on a.fmaterysn = b.materysn

where not exists (select 1 from @MRPplan where psn = @Psn and materysn = a.materysn)

end



--有对应的话就更新

update a

set a.gr = a.gr b.planshu * b.f_planshu

from mrpplanpsn a inner join @MRPplan b

on a.psn = b.psn and a.materysn = b.materysn



--没有对应的话就插入

--这个就看你具体的需求了,因为mrpplanpsn表还有其他的列,这里并不知道取值方法

insert into mrpplanpsn(psn,materysn,gr)

select a.psn,a.materysn ,a.planshu * a.f_planshu

from @MRPplan a left join mrpplanpsn b

on a.psn = b.psn and a.materysn = b.materysn

where b.materysn is null

end



--执行

exec P_UpdateMrpplanpsn '20080104'



--结果

psn materysn gr

-------------------- ------------------------------ ----------------

20080104 38912 100.0000

20080104 38912-1 1000.0000

20080104 38912-2 1000.0000

20080104 38912-1-1 10000.0000

20080104 38912-1-2 10000.0000

20080104 38912-2-1 10000.0000



(所影响的行数为 6 行)



--下班了,再有问题只好等下个周了,呵呵
**************************************************
网友回复:冷箫轻笛 正解......
网友回复:其中更新部分(如下)没有执行任何动作
--有对应的话就更新
update a
set a.gr = a.gr b.planshu * b.f_planshu
from mrpplanpsn a inner join @MRPplan b
on a.psn = b.psn and a.materysn = b.materysn


以上代码疲敝与否结果是一样的,也就是说 写入 mrpplanpsn 中的资料与@MRPplan中的资料笔数是一样的.
我测试了您以上数据,但是假如加入调整资料时就有问题
假如某产品(如产品 389122的产品结构对应的BOM)进行分解有对应 如下资料
insert into bom(fmaterysn,materysn,useshu,unit) select '38912-1', '38912-1-1', 20, 'pcs'
则计算出来资料是 7 笔 而非 6笔

--结果
psn materysn gr
-------------------- ------------------------------ ----------------
20080104 38912 100.0000
20080104 38912-1 1000.0000
20080104 38912-2 1000.0000
20080104 38912-1-1 10000.0000
20080104 38912-1-2 10000.0000
20080104 38912-2-1 10000.0000
20080104 38912-1-1 20000.0000

正确结果应为

--结果
psn materysn gr
-------------------- ------------------------------ ----------------
20080104 38912 100.0000
20080104 38912-1 1000.0000
20080104 38912-2 1000.0000
20080104 38912-1-1 30000.0000
20080104 38912-1-2 10000.0000
20080104 38912-2-1 10000.0000


望解



网友回复:其中更新部分(如下)没有执行任何动作
--有对应的话就更新
update a
set a.gr = a.gr b.planshu * b.f_planshu
from mrpplanpsn a inner join @MRPplan b
on a.psn = b.psn and a.materysn = b.materysn
以上代码疲敝与否结果是一样的,也就是说 写入 mrpplanpsn 中的资料与@MRPplan中的资料笔数是一样的.
-----------------------------------------------
这个你是用我的数据测试的?
那肯定是有没有都一样啊,我的测试环境本来里面就灭有数据,当然只做插入不做更新阿
假如不是,请说明什么情况下的什么数据不能更新
==================================================================

你的bom表答应这样的纪录同时存在????
'38912-1', '38912-1-1', 10, 'pcs'
'38912-1', '38912-1-1', 20, 'pcs'
假如是的话,那跟我理解的bom表是不一样的。

SQL code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





--循环导入子项

while (@@rowcount > 0)

begin

insert into @MRPplan(psn,materysn,planshu,f_planshu,cdate)

select @Psn,a.materysn,a.useshu,b.planshu * b.f_planshu,b.cdate

from bom a inner join @MRPplan b on a.fmaterysn = b.materysn

where not exists (select 1 from @MRPplan where psn = @Psn and materysn = a.materysn)

end

--改成这个试试:

--循环导入子项

while (@@rowcount > 0)

begin

insert into @MRPplan(psn,materysn,planshu,f_planshu,cdate)

select @Psn,a.materysn,sum(a.useshu),sum(b.planshu * b.f_planshu) ,b.cdate

from bom a inner join @MRPplan b on a.fmaterysn = b.materysn

where not exists (select 1 from @MRPplan where psn = @Psn and materysn = a.materysn)

group by a.materysn,b.cdate

end
****************************************************************
网友回复:--好累,盖了六十多楼了,问题还没有叙述明白。。。。 -_-!!
网友回复:楼主,给贴子加分吧!!

冷箫轻笛好人!
网友回复:非常感激 冷箫轻笛 .非常非常
我认为我应该给您加500分,可惜我没有这么多分,资料笔数已经正确.但其有三笔数量不正确.我正在查证.
分数我将稍后奉上.真心感谢
网友回复:

SQL code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





--数量不正确的 可以查一下是否是更新语句的问题

--因为更新语句同样需要合计的,之前没有来得及写

--有对应的话就更新

update a

set a.gr = a.gr b.planshu * b.f_planshu

from mrpplanpsn a inner join @MRPplan b

on a.psn = b.psn and a.materysn = b.materysn

---=======

--这样改:

update a

set a.gr = a.gr sum(b.planshu * b.f_planshu)

from mrpplanpsn a inner join @MRPplan b

on a.psn = b.psn and a.materysn = b.materysn

group by a.psn,a.materysn



--其实合计在插入临时表的时候合计也可以,但是忘记当时为什么不在那个地方做了,思考ing...





网友回复:冷箫轻笛您好 我将Excl 资料给您 您可以导入您的SQL 数据库吗?
计算出来的数据不对,恳请您再次帮助我,谢谢
网友回复:冷箫轻笛您好 我已发邮件给您 ,请查收
网友回复:回复:
--这样改:
update a
set a.gr = a.gr sum(b.planshu * b.f_planshu)
from mrpplanpsn a inner join @MRPplan b
on a.psn = b.psn and a.materysn = b.materysn
group by a.psn,a.materysn

这样语法是错误的,现在 Update 疲敝于否没有任何变化.也就是说没有起到作用

网友回复:已经找到问题所在
思考中
网友回复:mrpplanpsn表没有数据对吧?
网友回复:是的 我给您的mrpplanpsn表没有结果,我只给了这个表的部分要害字段
但目的是将结果写到该表中
现在程序能做到将结果写入mrpplanpsn 中, 给您的execl表 Sql2008 就是由 mrpplanpsn 导出来的
要害问题是 有几笔资料数据不对 这是致命的地方
谢谢您

网友回复:

SQL code





Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





--重新搞了一下

CREATE proc P_UpdateMrpplanpsn

@Psn varchar(100) --改成你自己的类型

as

begin

--建立临时表

declare @MRPplan table

(

layer int,

Psn varchar(100),

materysn varchar(100),

planshu decimal(8,2),

f_planshu int,

cdate datetime

)



declare @lay int

set @lay = 1



--根据psn导入一级数据

insert into @MRPplan(layer,psn,materysn,planshu,f_planshu,cdate)

select @lay,psn,materysn,planshu,1,consigndate

from MRPplan

where Psn = @Psn



while (@@rowcount > 0)

begin

select @lay = @lay 1



insert into @MRPplan(layer,psn,materysn,planshu,f_planshu,cdate)

select @lay,@Psn,a.materysn,a.useshu,b.planshu * b.f_planshu ,b.cdate

from bom a inner join @MRPplan b on a.fmaterysn = b.materysn

where b.layer = @lay - 1 --not exists (select 1 from @MRPplan where psn = @Psn and

materysn = a.materysn)

end



--有对应的话就更新

update a

set a.gr = a.gr b.planshu

from mrpplanpsn a inner join (select psn,materysn,sum(planshu * f_planshu) as planshu,cdate

from @MRPplan

group by psn,materysn,cdate) b

on a.psn = b.psn and a.materysn = b.materysn



--没有对应的话就插入

--这个就看你具体的需求了,因为mrpplanpsn表还有其他的列,这里并不知道取值方法

insert into mrpplanpsn(psn,materysn,gr)

select a.psn,a.materysn ,sum(a.planshu * a.f_planshu) as planshu

from @MRPplan a left join mrpplanpsn b

on a.psn = b.psn and a.materysn = b.materysn

where b.materysn is null

group by a.psn,a.materysn

end

GO



--跟楼主的结果还有差异

/*

01-358M0101

01-358M0101-03B

01-358M0101-04B

01-358M0101-05B

*/

--这四种我这里根本查不出来,但是楼主的结果里有





--29-Z

--这个的计算结果跟楼主不一样



--楼主可以用这个语句来手动计算

declare @m varchar(100)

set @m = '29-Z'



select a.psn as psn1,a.materysn as materysn1,a.planshu as planshu1,

b.materysn as materysn2,b.useshu as planshu2,

c.materysn as materysn3,c.useshu as planshu3,

d.materysn as materysn4,d.useshu as planshu4,

e.materysn as materysn5,e.useshu as planshu5,

f.materysn as materysn6,f.useshu as planshu6,

g.materysn as materysn7,g.useshu as planshu7

from mrpplan a left join bom b on a.materysn = b.fmaterysn

left join bom c on b.materysn = c.fmaterysn

left join bom d on c.materysn = d.fmaterysn

left join bom e on d.materysn = e.fmaterysn

left join bom f on e.materysn = f.fmaterysn

left join bom g on f.materysn = g.fmaterysn

WHERE a.psn = '2008' and

a.materysn = @m OR b.materysn = @m OR c.materysn = @m OR d.materysn = @m OR

e.materysn = @m OR f.materysn = @m

order by materysn1,materysn2,materysn3,materysn4,materysn5,materysn6



--以上语句我这里的结果是(用文本打开比较好看一些):

/*

psn1 materysn1 planshu1 materysn2

planshu2 materysn3 planshu3

materysn4 planshu4 materysn5 planshu5

materysn6 planshu6 materysn7

planshu7

-------------------- ------------------------------ -------------------- ---------------------

--------- -------------------------- ------------------------------ -------------------------- ---

--------------------------- -------------------------- ------------------------------ ------------

-------------- ------------------------------ -------------------------- -------------------------

----- --------------------------

2008 356-D1 100 01-356M01A01-05A

1.00 01-356M01A01-04A 1.00 01-

356M01A01-03A 1.00 01-356M01A01 1.00

29-Z 33.00 NULL

NULL

2008 358-D1 100 01-250/6653M0101

1.00 29-Z 1.00 NULL

NULL NULL NULL

NULL NULL NULL

NULL

2008 362-D1 100 01-362/363M0101-05A

1.00 01-362/363M0101-04A 1.00 01-

362/363M0101-03A 1.00 01-362/363M0101 1.00

29-Z 31.00 NULL

NULL



(所影响的行数为 3 行)

*/



--计算结果6500



--这个存储过程依然没有涉及到更新数据那块,楼主最好搞点数据测下
**********************************************************
网友回复: declare @MRPplan table
(
layer int,
Psn varchar(100),
materysn varchar(100),
planshu decimal(8,2),
f_planshu int,
cdate datetime
)
--这里忘改了,改成这样
f_planshu decimal(8,2),
网友回复:真的是痛苦.这么长啊.精神可嘉!
网友回复:真心感谢 冷箫轻笛 .
您的专业,精神,让我遵崇.
谢谢您 冷箫轻笛

您写的以下代码就完全可以正确的计算出来结果

--重新搞了一下
CREATE proc P_UpdateMrpplanpsn
@Psn varchar(100) --改成你自己的类型
as
begin
--建立临时表
declare @MRPplan table
(
layer int,
Psn varchar(100),
materysn varchar(100),
planshu decimal(8,2),
f_planshu int,
cdate datetime
)

declare @lay int
set @lay = 1

--根据psn导入一级数据
insert into @MRPplan(layer,psn,materysn,planshu,f_planshu,cdate)
select @lay,psn,materysn,planshu,1,consigndate
from MRPplan
where Psn = @Psn

while (@@rowcount > 0)
begin
select @lay = @lay 1

insert into @MRPplan(layer,psn,materysn,planshu,f_planshu,cdate)
select @lay,@Psn,a.materysn,a.useshu,b.planshu * b.f_planshu ,b.cdate
from bom a inner join @MRPplan b on a.fmaterysn = b.materysn
where b.layer = @lay - 1 --not exists (select 1 from @MRPplan where psn = @Psn and materysn =

a.materysn)
end

--有对应的话就更新
update a
set a.gr = a.gr b.planshu
from mrpplanpsn a inner join (select psn,materysn,sum(planshu * f_planshu) as planshu,cdate
from @MRPplan
group by psn,materysn,cdate) b
on a.psn = b.psn and a.materysn = b.materysn

--没有对应的话就插入
--这个就看你具体的需求了,因为mrpplanpsn表还有其他的列,这里并不知道取值方法
insert into mrpplanpsn(psn,materysn,gr)
select a.psn,a.materysn ,sum(a.planshu * a.f_planshu) as planshu
from @MRPplan a left join mrpplanpsn b
on a.psn = b.psn and a.materysn = b.materysn
where b.materysn is null
group by a.psn,a.materysn
end
GO
(http://www.itzhe.cn/news/20080114/53236_10.html)[@more@]http://www.itzhe.cn/news/20080114/53236_10.html

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/93029/viewspace-1023016/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/93029/viewspace-1023016/

  • 点赞
  • 收藏
  • 分享
  • 文章举报
congdou2006 发布了0 篇原创文章 · 获赞 0 · 访问量 263 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: