说不出「通过」的校验器,不算校验器
一句话总结
验证器的价值不是在于抓住什么,而是在于能否对正常文件说它是正常的。
为什么需要这个?
精炼脚本用一次就扔掉。验证器每周都会帮忙。这种差异会改变设计。
在客户公司连接数据后,从下个月开始每周都会收到相同格式的文件。其中,在某个周,上游系统会发生变化,增加一个热度,日期格式会发生变化,编码会发生变化。人们发现这些变化的时机通常是在收到报告称统计数字异常后。
验证器是为了消除那个时差。
怎么行动
有用的验证器有四种类型的规则。
结构规则 — 列的数量和名称、必填值的存在、类型。“必须有5个字段,customer不能为空,amount必须是整数。”
重复规则 — 键是否唯一。这里要注意的是前面模块看到的陷阱。如果键有缺失,缺失行应单独接受。
范围规则 — 值是否在常识范围内。amount0或负数或9,900万韩元以上的行为在形式上是有效的整数,但在业务上几乎肯定是错误的数据。没有范围规则的验证器只要类型正确就全部通过,将小数点偏移一个位置的值直接通过。
参考规则 — 与其他数据的整合性。订单的客户编号是否实际存在于客户表中。
还有比这四个更重要的特性之一。对于正常文件,必须说必须通过。
在现场相遇的样子
验证器有两种失败方式,两种方式都很常见。
**过度检测。**规则太严格了,正常文件也失败。然后人们开始每周都说“又是那个吧”,开始无视它,两个月后真正出现问题时也一样无视它。在那个时候,没有验证器比没有更糟糕。因为让人相信有,实际上却什么也阻止不了。
**过少检测。**规则松散,什么都抓不住。通常“先不死”的验证器就是这样的。
所以制作验证器时,一定要向两方向测试。是否能转回正常文件通过,是否能转回破损文件失败。只确认其中一个的验证器就制作了一半。
最后是输出格式。验证器必须用结束代码说。通过的话不是0,失败的话不是0的值。这样才能直接插到CI或排版管道中。人读的消息是放在上面,机器读的信号是先来的。
验证器必须具备的东西
只说“错了”的验证器是半个。一个人要想改正,需要四个条件。
| 要素 | 如果没有的话 |
|---|---|
| 哪一行·哪一列? | 为了找到100万行中的哪一行,花了一整天时间。 |
| 期待了什么 | 不知道该用什么来改正 |
| 实际价格是什么 | 需要重新打开原件看看 |
| 是几件呢 | 不知道是单件的例外还是结构性问题 |
❌ 검증 실패: 잘못된 데이터가 있습니다
✅ 행 4213, 컬럼 order_date: '2026-13-45' 가 날짜 형식이 아닙니다 (기대: YYYY-MM-DD)
같은 오류 1,842건 — 원본의 8행 이후 전부. 인코딩이나 구분자를 먼저 확인하세요.
最后一句是核心。如果错误集中在特定点之后,那么就是个别值的问题。 不是,而是破解问题。如果验证器识别并告知那个模式的话,调查方向就会 马上纠正。
在哪里阻止呢?
在多个层面上进行同样的检查并不是浪费。它们分别阻止了不同的东西。
1. 수집 경계 형식·필수 필드·인코딩 → 나쁜 데이터가 들어오지 못하게
2. 변환 중 비즈니스 규칙·참조 무결성 → 조용히 잘못된 결과를 만들지 못하게
3. 적재 후 행 수·합계·분포 대조 → 옮기다 잃어버린 것을 잡게
经常遗漏第3个。如果原来的12,043行装载后是12,041行,那么2行在哪里呢? 消失的东西。对比行数和金额总和的一行就能抓住这些。
-- 적재 후 대조
select
(select count(*) from staging_orders) as src,
(select count(*) from orders where load_id = :id) as dst,
(select sum(amount) from staging_orders) as src_amt,
(select sum(amount) from orders where load_id = :id) as dst_amt;
如何处理坏行
全部失败的话连好的数据都写不下来。一点都不阻止的话就会被污染。实际工作的 答案是隔离。
읽은 행 12,043
├ 통과 11,998 → 적재
└ 격리 45 → quarantine 표 + 사유
隔离行为请随理由一起留下,**隔离次数达到临界值。**平时是0.1%的 如果上升5%,说明原来的东西发生了变化,所以这本身就是警报。安静地 丢掉的话,这个信号就会消失。
下次实习要做的事情
故意将三个以不同方式破损的文件和一个完整的文件放在一起,分别计算几行违反规则,最后制作一个可以判断通过和失败的验证脚本。