高分求一存储过程代码!!!(200分)

  • 主题发起人 主题发起人 zhahongyi
  • 开始时间 开始时间
Z

zhahongyi

Unregistered / Unconfirmed
GUEST, unregistred user!
小弟刚刚入门sql,最近写一药品销售的程序,对这个存储过程不知如何下手,非常希望得到各位前辈的指点,先谢过各位了。以下是我的思路:<br>一:表结构:<br>1.库存表: kcb <br> &nbsp;bh,ph,mc,gg,dw,kcl,lsj (编号,批号,名称,规格,单位,库存,零售价)<br>2.明细表: mxb <br> &nbsp;djh,bh,ph,sl (单据号,编号,批号,数量)<br>3.销售表: xsb <br> &nbsp;djh,rq,je (单据号,日期,金额)<br>4.临时表: lsb <br> &nbsp;bh,sl (编号,数量) temp库中建立的一临时表记录录入的数据<br><br>库存表中的示例数据:<br> &nbsp;库存表(kcb)中一个编号(bh)对应一个品种,一个品种可以有多个不同批号(ph)。名称(mc),规格(gg),单位(dw)相同,但零售价(lsj)可以不同<br>bh &nbsp; ph &nbsp; mc &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gg &nbsp; &nbsp; dw &nbsp;kcl lsj<br>----------------------<br>001 &nbsp;001 &nbsp;葡萄糖液 &nbsp; &nbsp; 500ml &nbsp;瓶 &nbsp; 1 &nbsp;2.5<br>001 &nbsp;002 &nbsp;葡萄糖液 &nbsp; &nbsp; 500ml &nbsp;瓶 &nbsp; 5 &nbsp;2.4<br>001 &nbsp;003 &nbsp;葡萄糖液 &nbsp; &nbsp; 500ml &nbsp;瓶 &nbsp; 2 &nbsp;2.0<br>002 &nbsp;004 &nbsp;0.9%生理盐水 250ml &nbsp;瓶 &nbsp;17 &nbsp;1.8<br>003 &nbsp;005 &nbsp;青霉素针 &nbsp; &nbsp; 80万 &nbsp; 支 &nbsp;12 &nbsp;0.5<br>004 &nbsp;006 &nbsp;止血敏针 &nbsp; &nbsp; 0.5g &nbsp; 支 &nbsp; 3 &nbsp;1.6<br>----------------------<br>临时表中的示例数据:<br>bh &nbsp; &nbsp;sl<br>-----<br>001 &nbsp; 8<br>002 &nbsp; 2<br>-----<br><br>二:程序思路:<br> &nbsp;根据临时表(lsb)的数据首先减去库存表(kcb)中的库存(kcl),写入销售表(xsb)汇总记录,最后将明细写入明细表(mxb)中。<br>三:需要解决的问题:<br> &nbsp;1.减库存表的库存,有多个工作站运行。如何安全可靠的修改记录。<br> &nbsp;2.程序界面录入lsb的数据时,sl小于库存表(kcb)中的kcl。修改库存表(kcb)的数据时,按照对应的bh来减kcl<br> &nbsp; &nbsp;(1):库存表(kcb)中对应记录为单条:<br> &nbsp; &nbsp; &nbsp; kcb中的kcl大于sl,直接减数后并返回 ph,lsj 值。 &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; kcb中的kcl小于sl,将之前修改的数据回滚。并返回信息。<br> &nbsp; &nbsp;(2):库存表(kcb)中对应记录为多条:<br> &nbsp; &nbsp; 如果sum(kcl)的值小于sl时,将之前修改的数据回滚并返回信息。<br> &nbsp; &nbsp; &nbsp;当前记录kcl小于sl时,当前记录kcl写零,返回ph,lsj,kcl值。然后寻找下一条对应的记录继续减kcl,返回ph,lsj,kcl值。直到sl为零。<br> &nbsp; &nbsp;(3):写入销售表(xsb)记录。如果写入失败,回滚前面所有的修改并返回信息。<br> &nbsp; &nbsp;(4):根据前面步骤返回的单条(ph,lsj,sl),多条(ph,lsj,kcl)值增加mxb记录。如果写入失败,回滚前面所有的修改并返回信息。<br><br>先感谢各位。希望高手不吝赐教!
 
我的这个问题好多天了,没有一个人发表意见.如果嫌分少我可以再开个帖子另外再加200分
 
触发器 视图都可以的
 
主要是问题太长,字段名又不好理解,看了头天没看明白 .
 
帮你顶下,俺没看懂[:D]
 
不管是不是高手,一看到你的问题就会马上跑的(有可能)<br>但是你提出的问题比较乱,尽量简洁明了!<br>要不你重新组织一下语言!
 
初接触库存的你设计思路比较乱。<br>1、你应当有个出库表等同于你的临时表;<br>2、在录入完成后需要一个审核过程,只有审核过的单据才可以从库存中减去<br>3、你应当下载个简易进销存软件参考一下
 
老兄:<br> &nbsp; 看懂你的問題都得半小時!人家都還要工作的呢。簡單點吧。
 
我也做过医药,楼主还忽略了一个问题,产品有效期或进货日期,象这种有使用期限的商品,必须按照先进先出的原则进行销售.<br>需解决的问题,我看你思路挺清淅的呀,把上面的文字转成代码就OK啦,<br>至于库存表(kcb)中对应记录为多条如果用存储过程写用个游标就OK了.
 
大哥,真的看不下去啊,,看你的问题就像看小说啊。。。你能不能分开问啊,,我头都大了啊、、
 
[:D]同勇者<br>这种存储过程大半要用到游标,其实就是程序中的<br>while not dataset.eof do<br>begin<br> &nbsp; //工作<br> &nbsp; dataset.next;<br>end<br>while @@FETCH_STATUS=0 <br>begin<br> &nbsp; //工作<br> &nbsp; fetch next into 参数<br>end<br>看看SQL 帮助就知道了,这个不用我说了,<br>你的东西一会也搞不定,要定下心来好好的写,自已来吧
 
感谢勇者,Clearboy,你们的回答让我很受鼓舞.我刚刚入门,属于有思路没办法的那种.面对这个问题我是无法下手.勇者清楚我的思路.能不能按我的想法给个大概的框架,细节我可以再翻书找帮助完成.我有体会学习一门语言光靠自己死读书是不行的,各位热心的回答可以让我受益非浅.期待大家的热心回答
 
&quot;1、减库存表的库存,有多个工作站运行。如何安全可靠的修改记录。&quot;<br>客户端提交先验证,提交数据加个事务。<br><br>2、不知道有没有理解错,<br> &nbsp; 你要实现库存的批次管理..? 还有按先进先出的方式出库。。?<br> &nbsp; 还有部分看得不是很明白。。<br><br>以下是我以前写的,实现批次和先进先出。。希望对你有帮助。<br>实现方式:存储过程(实现功能)+触发器调用<br><br>//出库算法<br>CREATE PROCEDURE OutWarehouse<br>@BIllName varchar(20),------------- 单据名称<br>@BillNo varchar(20),------------------ 单据编号<br>@AuditFlag varchar(10),-------------- 审核标志<br>@BillDate smallDateTime-------------单据日期<br>AS<br>begin<br> &nbsp;Declare @Warehouse varchar(50),--------仓库编号<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Material varchar(40),---------------物料编号<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Quantity Float,--------------------------数量<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @BatchQuantity Float,-----------------批次数量<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Amount float,---------------------------金额<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @BatchNo Varchar(30),----------- -批次<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @instoctDate smallDatetime,-----入库日期<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @ProductDate smalldatetime,----生产日期<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @voidDate smalldatetime,----------失效日期<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @OutProcedure varchar(20)------物料出库方式<br> &nbsp;DECLARE @Detail_Cursor CURSOR<br><br> &nbsp;if @AuditFlag&lt;&gt;'审核'<br> &nbsp;begin<br> &nbsp; &nbsp;Delete From CKKCCK_TMP Where Djlx=@BillName and Djbh=@BillNo<br> &nbsp; &nbsp;Return<br> &nbsp;end<br>---------------------------------------------------销售出库-----------------------------------------------------<br> &nbsp;if @BillName='销售出库' <br> &nbsp;begin<br> &nbsp; &nbsp;Set @Detail_Cursor=cursor for <br> &nbsp; &nbsp;Select ChCK,Wlbh,CkSl,CKSl*DJ,Pc,RkRq,ScRq,SxRq<br> &nbsp; &nbsp;from CKXSCK a,CKxsckMx b where a.Djbh=b.Djbh and a.Djbh=@BIllNo<br> &nbsp;end<br>----***************************领料单*************************************<br> &nbsp;else if @BillName='领料单'<br> &nbsp;begin<br> &nbsp; &nbsp;Set @Detail_Cursor=cursor for <br> &nbsp; &nbsp;Select CK,Wlbh,Sfsl,SfSl*Dj,Pc,RkRq,ScRq,SxRq<br> &nbsp; &nbsp;from CkLlD a,CkLlDMX b where a.Djbh=b.Djbh and a.Djbh=@BIllNo<br> &nbsp;end<br>----****************************其它出库*************************************<br> &nbsp;else if @BillName='其它出库'<br> &nbsp;begin<br> &nbsp; &nbsp;Set @Detail_Cursor=cursor for <br> &nbsp; &nbsp;Select CK,Wlbh,SfSl,SfSl*DJ,Pc,RkRq,ScRq,SxRq<br> &nbsp; &nbsp;from CKQTCK a,CKQTCKMX b where a.Djbh=b.Djbh and a.Djbh=@BIllNo<br> &nbsp;end<br>---------------------------------------------调拨-----------------------------------------------------------------<br> &nbsp;else if @BillName='仓库调拨入'<br> &nbsp;begin<br> &nbsp; &nbsp; Set @Detail_Cursor=cursor for <br> &nbsp; &nbsp; Select ZrCK,Wlbh,Sl*-1,Sl*DJ*-1,Pc,RkRq,ScRq,SxRq<br> &nbsp; &nbsp; from CkCkDb a,CkCkDbMX b where a.Djbh=b.Djbh and a.Djbh=@BIllNo<br> &nbsp;end<br> &nbsp;else if @BillName='仓库调拨出'<br> &nbsp;begin<br> &nbsp; &nbsp;Set @Detail_Cursor=cursor for <br> &nbsp; &nbsp;Select ZcCK,Wlbh,Sl,Sl*DJ,Pc,RkRq,ScRq,SxRq<br> &nbsp; &nbsp;from CkCkDb a,CkCkDbMX b where a.Djbh=b.Djbh and a.Djbh=@BIllNo <br> &nbsp;end &nbsp;<br> &nbsp;else<br> &nbsp; &nbsp; Return<br>--------------------------------------------End--------------------------------------------------------------------<br><br> &nbsp;OPEN @Detail_Cursor<br> &nbsp;<br> &nbsp;FETCH NEXT FROM @Detail_Cursor<br> &nbsp;Into @warehouse,@Material,@Quantity,@Amount,@BatchNo,@instoctDate,@ProductDate,@voidDate<br><br> &nbsp;WHILE @@FETCH_STATUS = 0<br> &nbsp;BEGIN<br> &nbsp; &nbsp;update JCWLZL Set Zjcksj=@BillDate where Wlbh=@Material -------------------------------------出库时更新物料表最近出库日期<br> &nbsp; &nbsp;Select @OutProcedure=CkFs from Jcwlzl where Wlbh=@Material<br> &nbsp; &nbsp;If @OutProcedure='正常' or @OutProcedure='手工选择' &nbsp; <br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; Insert into CKKCCK_TMP(DjLx,Djbh,CKbh,Wlbh,CKSl,CKJe,Pc,RkRq,ScRq,SxRq)<br> &nbsp; &nbsp; &nbsp; Values(@BillName,@BillNO,@warehouse,@Material,@Quantity,@Amount,@BatchNo,@instoctDate,@ProductDate,@voidDate)<br> &nbsp; &nbsp;end<br> &nbsp; &nbsp;else if @OutProcedure= '先进先出' &nbsp;or @OutProcedure= '后进先出' ----------------------------物料出库方式为先进先出<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;Declare &nbsp;@BatchCur Cursor <br><br> &nbsp; &nbsp; &nbsp;if @OutProcedure= '先进先出'<br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;Set @BatchCur=cursor for &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp;Select Sl,PC,RkRq,ScRq,SxRq from CKKCXL <br> &nbsp; &nbsp; &nbsp; &nbsp;Where CKBH=@Warehouse and Wlbh=@Material and &nbsp;Sl&lt;&gt;0 order by ScRq Asc<br> &nbsp; &nbsp; end<br> &nbsp; &nbsp; else if @OutProcedure= '后进先出'<br> &nbsp; &nbsp; begin<br> &nbsp; &nbsp; &nbsp; &nbsp;Set @BatchCur=cursor for &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp;Select Sl,PC,RkRq,ScRq,SxRq from CKKCXL <br> &nbsp; &nbsp; &nbsp; &nbsp;Where CKBH=@Warehouse and Wlbh=@Material and &nbsp;Sl&lt;&gt;0 order by ScRq Desc<br> &nbsp; &nbsp; end<br><br> &nbsp; &nbsp; &nbsp;open @BatchCur<br><br> &nbsp; &nbsp; &nbsp;fetch next from @BatchCur<br> &nbsp; &nbsp; &nbsp;Into @BatchQuantity,@BatchNo,@InstoctDate,@ProductDate,@voidDate<br><br> &nbsp; &nbsp; &nbsp;while @@FETCH_STATUS = 0 and @Quantity&gt;0<br> &nbsp; &nbsp; &nbsp;begin<br><br> &nbsp; &nbsp; &nbsp; &nbsp; if @Quantity&gt;@BatchQuantity <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set @Quantity=@Quantity-@BatchQuantity<br> &nbsp; &nbsp; &nbsp; &nbsp; else <br> &nbsp; &nbsp; &nbsp; &nbsp; begin<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Set @BatchQuantity=@Quantity<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Set @Quantity=0<br> &nbsp; &nbsp; &nbsp; &nbsp; end<br><br> &nbsp; &nbsp; &nbsp; &nbsp; Insert into CKKCCK_TMP(DjLx,Djbh,CKbh,Wlbh,CKSl,CKJe,Pc,RkRq,ScRq,SxRq)<br> &nbsp; &nbsp; &nbsp; &nbsp; Values(@BillName,@BillNO,@warehouse,@Material,@BatchQuantity,@Amount,@BatchNo,@instoctDate,@ProductDate,@voidDate) <br> &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; fetch next from @BatchCur<br> &nbsp; &nbsp; &nbsp; &nbsp; Into @BatchQuantity,@BatchNo,@InstoctDate,@ProductDate,@voidDate<br> &nbsp; &nbsp; &nbsp;end &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp;if @Quantity&gt;0 <br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp; Insert into CKKCCK_TMP(DjLx,Djbh,CKbh,Wlbh,CKSl,CKJe,Pc,RkRq,ScRq,SxRq)<br> &nbsp; &nbsp; &nbsp; &nbsp; Values(@BillName,@BillNO,@warehouse,@Material,@Quantity,@Amount,@BatchNo,@instoctDate,@ProductDate,@voidDate) <br><br> &nbsp; &nbsp; &nbsp;end<br> &nbsp; &nbsp; &nbsp;close @BatchCur<br> &nbsp; &nbsp; &nbsp;deallocate @BatchCur &nbsp;<br> &nbsp; &nbsp;end<br> &nbsp; &nbsp;else<br> &nbsp; &nbsp; &nbsp; Return<br><br> &nbsp; &nbsp;--set @Quantity=@Quantity*@Flag<br> &nbsp; &nbsp;--exec UpdateWarehouse @warehouse,@Material,@Quantity,@Amount,@BatchNo,@instoctDate,@ProductDate,@voidDate<br> &nbsp; &nbsp;FETCH NEXT FROM @Detail_Cursor<br> &nbsp; &nbsp;Into @warehouse,@Material,@Quantity,@Amount,@BatchNo,@instoctDate,@ProductDate,@voidDate &nbsp;<br> &nbsp;END<br><br> &nbsp;CLOSE @Detail_Cursor<br> &nbsp;DEALLOCATE @Detail_Cursor &nbsp;<br><br>end<br>GO<br><br><br><br>//更新库存<br>CREATE PROCEDURE UpdateWarehouse<br>@warehouse varchar(50),-------------仓库编号<br>@material varchar(40),------------------ 物料编号<br>@quantity float,----------------------------- 数量<br>@Amount float,----------------------------- 金额<br>@BatchNo Varchar(30),---------------- 批次<br>@instoctDate smallDatetime,---------入库日期<br>@ProductDate smalldatetime,--------生产日期<br>@voidDate smalldatetime--------------失效日期<br>As<br>Set @BatchNo=isNull(@BatchNo,'')<br>if exists(Select 1 from CKKCXl &nbsp;Where Ckbh=@warehouse and Wlbh=@material and Pc=@BatchNo)<br>begin<br> &nbsp; &nbsp;UPDATE &nbsp;CKKCXl <br> &nbsp; &nbsp;SET SL=SL+@quantity,Je=Je+@Amount<br> &nbsp; &nbsp;WHERE Ckbh=@warehouse and Wlbh=@material &nbsp;and Pc=@BatchNo<br>end<br>else<br>begin<br> &nbsp; Insert Into CKKCXl(ckbh,Wlbh,Sl,Je,Pc,RkRq,ScRq,SxRq)<br> &nbsp; Values(@Warehouse,@material,@quantity,@Amount,@BatchNo,@InstoctDate,@ProductDate,@VoidDate)<br>end<br>GO<br><br><br>这个部分代码是触发器引用<br>CREATE TRIGGER XsAudit ON [dbo].[CKXSCK] <br>FOR UPDATE<br>AS<br> &nbsp;Declare @BillNo varchar(20),@AuditFlag varchar(10),@BillDate SmallDateTime<br> &nbsp;Select @BillNo=DJbh,@AuditFlag=Shbz,@BillDate=DjRq from inserted<br> &nbsp;if Update(Shbz)<br> &nbsp;begin<br> &nbsp; &nbsp;if (Select ChBs &nbsp;from inserted )=1<br> &nbsp; &nbsp; &nbsp;exec OutWarehouse '销售出库',@BillNo,@AuditFlag,@BillDate<br> &nbsp; &nbsp;else<br> &nbsp; &nbsp; &nbsp;exec inWarehouse '销售退货',@BillNo,@AuditFlag,@BillDate<br> &nbsp;end
 
看了下,原贴在字面上算得上提问的地方只有一处:减库存表的库存,有多个工作站运行。如何安全可靠的修改记录。并发控制主要就是用好锁和事务。关于这方面的资料很多,你可以上网找找。基础概念介绍的比较全面的是Martin Fowler的《企业应用架构模式》里关于并发的章节。<br><br>其他地方思路都挺清晰,我觉得照着思路做就是了。如果一定要鸡蛋里挑骨头,在细节方面有以下建议:<br><br>1. 数据库的字段名最好详细点。例如 名称。如果不想用英文NAME,可以用拼音MINGCHENG.如果觉得MINGCHENG太长,甚至可以简写为MINCEN,虽然别人可能一下看不懂,至少自己三个月后一眼看去还能知道是什么。反正MC肯定是别人和自己都看不懂的。<br><br>2. 首次开发时,主键名最好能尽量有意识做到全局唯一。例如库存表的编号可以叫KBIANHAO,人员表的编号可以叫RBIANHAO。因为主键很可能要放到别的表做外键,如果两个表的主键刚好重复,到头来还是要想另一个名字,而且SQL的写法会麻烦很多。当然如果以后的改动或者根据命名规则的确会冲突,也不用太在意。<br><br>3. 你的库存表设计好象有点问题,第一,名称,规格,单位 很明显是重复字段。第二,因为PH的存在,每条记录都是绝对唯一的。如果表里某条记录数量变零了,因为下次进货批号不同,这条记录就永远都是零了。如果你每次都把变0的记录删掉,那么如果你卖出了最后一瓶葡萄糖,葡萄糖的记录完全就没有了。如果库存编号是某个表的一个外键,就破坏了参照完整性。就算不是,如果刚卖出去的最后一瓶葡萄糖又退回来了,就要重新输入MC,GG,DW,而且编号就不同了。所以建议把(编号,名称,规格,单位)分出去做一个药品表。<br><br>4. 不知道库存表里的零售价是指成本价还是卖出价。但很少会这样在库存表里放卖出零售价的,最多是参考零售价。不知道你在这里是不是这个意思。<br><br>5. 提醒一下,录入lsb表时,尽量不要锁库存表。如果要锁,也不要用悲观锁。因为你在求总数时用了SUM,会引起锁表。这样在你录入过程中其他人连插入新记录都做不到了。录入完后,如无意外,你只要在第(1)步时开始事务,在(4)之后提交事务。应该问题不大了。由于其他人的插入动作对你的减去动作没有影响,因此幻记录也无关紧要,所以事务隔离级别用“可重复读”级别就行了。<br><br>6. 其实单条和多条不用分开处理,一律按多条处理就行了。如勇者所说,可以先按有效期排序,然后从第一条开始逐渐条减就行了。减到0的可以当场删掉(如果批号固定的话),也可以隔一段时间后删掉(如果批号由系统生成,应过了退货期限再删,以保证退回的货品与原来的记录一样)。
 
确实是哈,你把整个事情拿来别人做,谁有那么多的时间来看,我看了20分钟,实在是看不下去了.你可以自己做撒,遇到难点再来讨论了.我们也不做你的项目,对整个设计实在是没有兴趣哈.我的建议是自己先做.
 
你干脆外包算了,直接投标
 
对效率要求不高的话可以用事物来解决,如果并发情况多的话可以考虑使用中间件。
 
谢谢各位的热心解答.谢谢天使鬼差,kidneyball,我整理一下思路.这两天出差没空.我回头弄出个东西大家评评.
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
928
SUNSTONE的Delphi笔记
S
后退
顶部