ITPUB论坛-中国最专业的IT技术社区

 找回密码
 注册
查看: 3769|回复: 3

[PL/SQL] 判断子表中完全一样的数据

[复制链接]
论坛徽章:
3
火眼金睛
日期:2017-08-01 17:00:03技术图书徽章
日期:2017-07-25 17:34:38目光如炬
日期:2017-07-30 22:00:00
发表于 2017-7-25 16:58 | 显示全部楼层 |阅读模式
本帖最后由 net205 于 2017-7-25 17:34 编辑

Oracle数据库中有2个表, 主表d, 子表w,通过INVOICECODE关联,1对多的关系

表d
    INVOICECODE    VARCHAR2(32 BYTE)     PRIMARY KEY  
    COMBINATIONNAME    NVARCHAR2(100 CHAR)      
    STARTTIME    DATE      
    ENDTIME    DATE      
   STATUS    NUMBER(10,0)   
    .....  

表w
    SERIALID  VARCHAR2(32 BYTE)  PRIMARY KEY  
    INVOICECODE  VARCHAR2(32 BYTE)  
    WARECODE  VARCHAR2(20 BYTE)  
    WARENAME  NVARCHAR2(100 CHAR)  
    ....

在页面中新增一条数据或编辑一条数据,当保存的时候需要验证当前添加的数据不能与数据库中已经有的数据时间上存在重叠或交叉的情况, 添加的商品WareCode也不能完全在子表w中, 多一条或少一条则没关系

比方新加的数据是这样的
CombinationName: aaaaaa  
StartTime: 2017/07/25  
EndTime: 2017/07/28  

WareCode   WareName  

123        A   
222        B  

如果数据库中status为1并且时间有重叠或交叉的情况,或者新增加的WareCode完全与数据库中某个数据的w表数据完全一样,则不允许添加。 交叉时间的判断使用以下条件好像可以,但与子表中的数据是不是完全一样,这个不会写:
select count(1)
from d
where status = 1
and (StartTime BETWEEN '2017-07-25' AND '2017-07-28'
     OR EndTime BETWEEN '2017-07-25' AND '2017-07-28'     
     OR '2017-07-25' Between StartTime AND EndTime      
     OR '2017-07-28' BETWEEN StartTime AND EndTime)
  or (/*....*/)




论坛徽章:
480
榜眼
日期:2015-09-09 10:34:21秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12状元
日期:2015-11-23 10:04:09举人
日期:2015-11-23 10:04:09
发表于 2017-7-25 22:06 | 显示全部楼层
你应该建立两个REFRESH ON COMMIT的物化视图。第一个是防止D表上出现交叉的,用D表自连接实现,加上个永远为假的检查约束,这样一旦有交叉数据,刷新就会报错。
第二个是在W表上对WARECODE进行LISTAGG, GROUP BY INVOICECODE, 然后对拼接后的WARECODE建立唯一约束。
注意报错会发生在COMMIT的时候,所以操作时是不会报错的,界面不是那么友好,但是它能够严密的保证数据的正确性。
你自己的做法,COUNT的时候是看不见未提交数据的,所以有漏洞,最终还是可能出现交叉数据。

使用道具 举报

回复
论坛徽章:
3
火眼金睛
日期:2017-08-01 17:00:03技术图书徽章
日期:2017-07-25 17:34:38目光如炬
日期:2017-07-30 22:00:00
 楼主| 发表于 2017-7-26 09:18 | 显示全部楼层
newkid 发表于 2017-7-25 22:06
你应该建立两个REFRESH ON COMMIT的物化视图。第一个是防止D表上出现交叉的,用D表自连接实现,加上个永远 ...

首先多谢你的回复。
你说的第1个没太明白你的意思, 第2个建立唯一约束, 但这样只是在w表上约束同一个INVOICECODE不能有重复数据, 并没有考虑主表中Status和时间交叉的问题吧, 这样不就不答我要求。
更正一下, Status、时间重叠、子表数据完全相同当约束条件,条件是且的关系 。
昨天后来我又想了一下, 好像以下sql满足我的要求,但还需要仔细验证才知道, 就是提交后,服务端代码对WareCode进行排序组成字符串,然后使用以下sql检查,如果存在,则当前保存操作不能进数据库,还需要验证一下看有没有问题:
  1. Select Count(1) From (
  2.     Select (
  3.         Select
  4.             listagg(WareCode, ';') within group (Order by WareCode) as mergeWareCode
  5.         From w
  6.         Where InvoiceCode = d.InvoiceCode
  7.         Group by InvoiceCode
  8.     ) as mergeWareCode, d.InvoiceCode From d
  9.   Where d.Status = 1 and ( StartTime Between to_date('2017-07-25','yyyy-mm-dd hh24:mi:ss') and to_date('2017-07-28','yyyy-mm-dd hh24:mi:ss')
  10.     or EndTime Between to_date('2017-07-25','yyyy-mm-dd hh24:mi:ss') and to_date('2017-07-28','yyyy-mm-dd hh24:mi:ss')
  11.     or to_date('2017-07-25','yyyy-mm-dd hh24:mi:ss') Between StartTime and EndTime
  12.     or to_date('2017-07-28','yyyy-mm-dd hh24:mi:ss') Between StartTime and EndTime )
  13. ) Where mergeWareCode='123;222'
  14. ;
复制代码


使用道具 举报

回复
论坛徽章:
480
榜眼
日期:2015-09-09 10:34:21秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12状元
日期:2015-11-23 10:04:09举人
日期:2015-11-23 10:04:09
发表于 2017-7-26 09:34 来自手机 | 显示全部楼层
你没看懂我的意思。先看下这个贴给出脚本:http://www.itpub.net/thread-1348543-1-1.html

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则

TOP技术积分榜 社区积分榜 徽章 电子杂志 团队 统计 虎吧 老博客 知识索引树 读书频道 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档 | IT博客
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛 | SAP ERP系统
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 网站律师 隐私政策 知识产权声明
京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表