Oracle 数据库一张表有如下字段:
FOO
| 字段 | 类型 | 说明 |
| LOCATION | VARCHAR2(512) | 地点,可以为多个,格式如:北京|上海 |
| STARTTIME | VARCHAR2(20) | 开始时间,格式为:YYYYMMDD24HHMISS |
| ENDTIME | VARCHAR2(20) | 结束时间,格式为:YYYYMMDD24HHMISS |
| FILED_A | VARCHAR2(30) | 字段 A,有可能为空 |
| FILED_B | VARCHAR2(30) | 字段 B,有可能为空 |
| FILED_C | VARCHAR2(30) | 字段 C,有可能为空 |
| FILED_D | VARCHAR2(30) | 字段 D,有可能为空 |
需求是用文件导入的方式批量对这张表进行新增操作,但导入时需要对数据执行一系列校验。
其中有一个步骤是 重复性校验。若同时满足以下条件,则说明导入的数据已经存在,校验失败:
原先的方案是在内存中比较,但由于导入的数据往往较大,如果取一条数据查一次数据库看存不存在,5000 条数据就要查 5000 次,性能比较差。 于是考虑把待校验的数据放在一张临时表中,一次性对所有数据进行对比。
临时表与正式表结构基本一致,但多了下面一个字段:
TEMP_FOO
| 字段 | 类型 | 说明 |
| CHECKRESULT | VARCHAR2(20) | 校验结果 |
目前写出的重复性校验 SQL 如下(如果临时表 TEMP_FOO 待校验的数据已经存在正式表 FOO 中,则将其校验结果字段更新为 Repeat ):
UPDATE TEMP_FOO t
SET t.CHECKRESULT = 'Repeat'
WHERE EXISTS (
SELECT 1 FROM FOO o
WHERE regexp_like(o.LOCATION, t.LOCATION)
AND o.STARTTIME >= concat(to_char(to_date(t.STARTTIME,'yyyymmddhh24miss'),'yyyymmdd'),'000000')
AND o.STARTTIME < concat(to_char(to_date(t.STARTTIME,'yyyymmddhh24miss')+1,'yyyymmdd'),'000000')
AND o.ENDTIME >= concat(to_char(to_date(t.ENDTIME,'yyyymmddhh24miss'),'yyyymmdd'),'000000')
AND o.ENDTIME < concat(to_char(to_date(t.ENDTIME,'yyyymmddhh24miss')+1,'yyyymmdd'),'000000')
AND nvl(t.FILED_A, '0') = nvl(o.FILED_A, '0')
AND nvl(t.FILED_B, '0') = nvl(o.FILED_B, '0')
AND nvl(t.FILED_C, '0') = nvl(o.FILED_C, '0')
AND nvl(t.FILED_D, '0') = nvl(o.FILED_D, '0')
)
现在有几个问题想请教大家:
有任何一点建议都可以提出,非常感谢!
1
canbingzt 2017-11-16 17:37:55 +08:00
感觉把校验内容单独建表是不是效率更高
1.建一张时间表,保存已有的时间,你的例子时间只到天,那么就把所有存在的天保存起来,不保存时间段 2.建一张地点表,保存已有的地点 |
2
picone 2017-11-16 19:11:11 +08:00
时间方面,字段类型改成是 TIMESTAMP 或 DATE。
如果要放在内存做验证也不是不可以,做一个链表存放时间返回,详细的可以参考操作系统的内存管理是怎么做的。 |