问一个比较复杂的问题

有三个表,一个Ytfwh表,一个是cgddmxb, 一个是自己创建的#cgddmxb
cgddmxb和#cgddmxb的结构是一样的。

cgddh, key_id, cbh, sl, dj
2002-02-01 1 3 2 5
2002-02-01 2 3 5 5
以 cgddh+key_id+cbh(作为唯一标识这条记录的键).
用临时表也就是把cgddmxb表的内容调出到#cgddmxb来改,改完之后又写回到cgddmxb ,

在这改的过程有可能修改了 dj,sl, cbh,也有可能删除掉某条记录, 或者增加了某条记录。
(cgddmxb有非常多的记录,但调出来的可能是其中的一些数据, 以(cgddh='...' and key_id='001' and cbh='0001'过滤出来的数据。)

最后要#cgddmxb和cgddmxb的内容一至
第三个的结构是Ytfwh表,结构
whbh, cbh, sl
仓库1 001 10

每次对cgddmxb增加,删除, 修改 他的sl会发生变化, 会增加或者增少,
增加了多少,减少了多少都写到 Ytfwh表。

大侠你们能明白我的意思吗?

针对#cgddmxb的修改,增加,删除,最后都会更新到cgddmxb.
在更新的过程中,
1.在#cgddmxb中有,在cgddmxb中没有的记录就把 (#cgddmxb的该条记录写入到cgddmxb中,(同时还要更新ytfwh表,把#cgddmxb.cbh这条记录添加到ytfwh表,ytfwh表以whbh+cbh为主键(如果以whbh+cbh的记录在ytfwh中已经存在,就update这条记录,让ytfwh的sl+当前#cgddmxb的sl, 不存在,就添加进去。)

2.要更新 cgddmxb中对应#cgddmxb中已经存在的记录, (同时会发生sl的变化,数据增加,减少了多少要修改到ytfwh表对应的 whbh+cbh的这条记录).但在ytfwh表中不增加记录。

3.在cgddmxb中有 但在#cgddmxb中没有的记录,(首先要把在cgddmxb中的
whbh+cbh对应的ytfwh表里的whbh+cbh的这条记录sl的 值 减去cgddmxb中的
这条记录的sl的值) 然后再删除在 cgddmxb 中有,但在#cgddmxb中没有的记录。

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

create procedure xxx
@cgddh date,@key_id int,@cbh int,@sl int,@dj int,@whbh int,
as
begin tran
If not exists (select * from cgddmxb c where c.cgddh=@cgddh and c.key_id=@key_id and c.cbh=@cbh )
begin
Insert into cgddmxb(@cgddh,@key_id,@cbh,@sl,@dj)
if exist (select * from ytfwh y where y.........)
update ytfwh set...........
else
Insert into ytfwh(.....)
end
else
update cgddmxb set(........)
commit
declare @1 date,@2 int,@3 int,@4 int,@5 int,
declare xxx_cur cursor for
select * from cgddmxb c inner join #cgddh g where c.cgddh=g.cgddh....
for update
open xxx_cur
fetch next from xxx_cur into @1,@2,@3,@4,@5
while @@fetch_status=0
begin
update ytfwh y
set y.sl=y.sl-@4
delete from cgddmxb where current of xxx_cur
end
close xxx_cur
deallocate xxx_cur
go
不过有个问题,cgddmxb中没有whbh,它如何跟ytfwh对应起来呢?(对应你说的第3条).

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

--创建一个存储过程,每次修改结束的时候执行这个存储过程:

create proc myproc1
@whbh char(100) --将whbh赋值给这个存储过程
as

begin tran --定义一个事务

-------------------------------------------------------------------------------
if exists( --首先判断是否别人已修改了数据

select 1
from (select a.* --得到本人修改了的行,先不管本人插的新行。
from #cgddmxb1 a
left join #cgddmxb b
on a.cgddh = b.cgddh and
a.key_id = b.key_id and
a.cbh = b.cbh
where b.key_id is null --表示本人删除了
or a.sl <> b.sl --本人修改了数量
or a.dj <> b.dj --本人修改了单价
) as c

left join cgddmxb d
on c.cgddh = d.cgddh and c.key_id = d.key_id and c.cbh = d.cbh
where d.key_id is null --表示提交的时候别人已将他删除了
or c.sl <> d.sl --别人已修改了数量
or c.dj <> d.dj) --别人已修改了单价
begin
rollback
raiserror 20001 '你修改的数据别人已经修改过了。'
return -1
end
---------------------------------------------------------------------------
delete cgddmxb --将本人删除的行删除cgddmxb
from (select a.*
from #cgddmxb1 a left join #cgddmxb b
on a.cgddh = b.cgddh and a.key_id = b.key_id and a.cbh = b.cbh
where b.key_id is null) as c
where cgddmxb.cgddh = c.cgddh and
cgddmxb.key_id = c.key_id and
cgddmxb.cbh = c.cbh
---------------------------------------------------------------------------
--将本人插入的行插入cgddmxb,此节要根据你的实际情况作修改,否则会错
insert into cgddmxb
select a.*
from #cgddmxb a left join #cgddmxb1 b
on a.cgddh = b.cgddh and a.key_id = b.key_id and a.cbh = b.cbh
where b.key_id is null
---------------------------------------------------------------------------
update cgddmxb --将本人修改的行修改cgddmxb
set sl = c.sl,
dj = c.dj
from (select a.*
from #cgddmxb a,#cgddmxb1 b
where a.cgddh = b.cgddh and a.key_id = b.key_id and a.cbh = b.cbh
and (a.sl <> b.sl or a.dj <> b.dj)) as c
where cgddmxb.cgddh = c.cgddh and
cgddmxb.key_id = c.key_id and
cgddmxb.cbh = c.cbh
----------------------------------------------------------------------------
insert into ytfwh --将ytfwh没有的列插入
select distinct whbh=@whbh,cbh=isnull(a.cbh,b.cbh),sl=0
from #cgddmxb a full join #cgddmxb1 b
on a.cgddh = b.cgddh and a.key_id = b.key_id and a.cbh = b.cbh
where a.sl is null or b.sl is null or a.sl <> b.sl
and cast(@whbh as char(100))+cast(isnull(a.cbh,b.cbh) as char(100))
not in (select cast(whbh as char(100))+cast(cbh as char(100))
from ytfwh)
----------------------------------------------------------------------------
update ytfwh --将ytfwh的sl更新
set sl = c.sl
from (select whbh=@whbh,
cbh =isnull(a.cbh,b.cbh),
sl=sum( isnull(a.sl,0) - isnull(b.sl,0) )
from #cgddmxb a full join #cgddmxb1 b
on a.cgddh = b.cgddh and a.key_id = b.key_id and a.cbh = b.cbh
where a.sl is null or b.sl is null or a.sl <> b.sl
group by isnull(a.cbh,b.cbh) ) as c
where ytfwh.whbh = c.whbh and ytfwh.cbh = c.cbh
-----------------------------------------------------------------------------
commit --提交。头也晕晕的了。不过我是一路测下来的。

go

如果你打算做成一个共用模板的话,就得用到动态语句。如下格式:
create proc myproc1
@whbh char(100), --将whbh赋值给这个存储过程
@表名 char(100),
@动态语句 varchar(2000)
as
set @动态语句 = 'select * from '+@表名
exec(@动态语句)
......
这样做的结果会导致效率很低,不如多创建几个存储过程。

或者按如下方式也可供参考,这样就只要创建一个存储过程:
create proc myproc1
@whbh char(100), --将whbh赋值给这个存储过程
@单据类型 int
as
if @单据类型 = 1
begin
--将那大段语句写进去
end
if @单据类型 = 2
begin
--将另一种单据的处理写进去
end
......

Published At
Categories with 数据库类
Tagged with
comments powered by Disqus