在使用标准 SQL 或 InterSystems IRIS 中的对象层时,元数据的一致性通常通过内置验证和类型执行来保持。但是,绕过这些层直接访问global的传统系统会带来微妙而严重的不一致性。
了解驱动程序在这些边缘情况下的行为,对于诊断遗留数据问题和确保应用可靠性至关重要。DATATYPE_SAMPLE数据库旨在帮助分析列值不符合元数据中定义的数据类型或约束的错误情形。我们的目标是评估 InterSystems IRIS 及其驱动程序(JDBC、ODBC、.NET)和不同工具在发生此类不一致时的表现。 在本篇文章中,我将重点介绍JDBC 驱动程序。
问题出在哪里?
一些传统应用程序会直接写入globals。如果使用关系模型(通过 CREATE TABLE 创建或使用全局映射手动定义)来公开这些数据,那么映射定义 的底层值就会与每列的声明元数据一致。
当这一假设被打破时,可能会出现不同类型的问题:
- 访问失败(Access Failure):根本无法读取某个值,当驱动程序尝试访问该值时会抛出异常。
- 静默损坏(Silent Corruption):值已成功读取,但与预期的元数据不匹配。
- 未检测到的数据变异(Undetected Mutation):该值被读取且看似有效,但被驱动程序悄然修改以符合元数据要求,这使得这种不一致性难以被察觉。
模拟行为
为了演示这些情况,我创建了 DATATYPE_SAMPLE 数据库,该数据库可在 InterSystems Open Exchange 上获取:
软件包页面
🔗GitHub 代码库
用于演示的表格:
CREATE TABLE SQLUser.Employee (
ID BIGINT NOT NULL AUTO_INCREMENT,
Age INTEGER,
Company BIGINT,
DOB DATE,
FavoriteColors VARCHAR(4096),
Name VARCHAR(50) NOT NULL,
Notes LONGVARCHAR,
Picture LONGVARBINARY,
SSN VARCHAR(50) NOT NULL,
Salary INTEGER,
Spouse BIGINT,
Title VARCHAR(50),
Home_City VARCHAR(80),
Home_State VARCHAR(2),
Home_Street VARCHAR(80),
Home_Zip VARCHAR(5),
Office_City VARCHAR(80),
Office_State VARCHAR(2),
Office_Street VARCHAR(80),
Office_Zip VARCHAR(5)
);
示例 1:访问失败
为了模拟不一致,我使用直接全局访问向 DOB(出生日期/数据类型 DATE)列注入了无效值。具体来说,在主键101、180、181、182、183、184 和 185 的行中注入了不代表有效日期的值。
现在的值是这样的
可以看到,在 $H (Horolog) 值的末尾添加了一个字符串。根据表的元数据,该列应该包含日期,但存储的值显然不是日期。
那么,当你尝试读取这些数据时会发生什么呢?这取决于你使用的工具。 我测试了几种不同的工具,比较它们是如何处理这种不一致的。
1) SquirrelSQL(SQuirreL SQL 客户端主页)
当 SquirrelSQL 尝试访问数据时,会发生错误。它会尝试读取所有行和列,任何包含无效数据的单元格都会被简单地标记为 "ERROR"。遗憾的是,我找不到任何其他细节或错误信息来解释原因。

2) SQLWorkbench/J (SQL Workbench/J - Home)
SQL Workbench/J 一旦遇到第一个无效单元格,就会停止处理结果集。它会显示类似 "Invalid date" 的错误信息,但遗憾的是,它不会提供任何有关哪一行导致了该问题的信息。

3) DBVisualizer (dbvis) 和 DBeaver (dbeaver)
DBVisualizer 和 DBeaver 的行为类似。这两种工具都会继续读取结果集,并为每个受影响的单元格提供详细的错误信息。这样就可以轻松识别导致问题的相应行。


4) SQL DATA LENS(SQL Data Lens - InterSystems IRIS 和 Caché 的强大工具)
使用最新版本的SQL DATA LENS,你可以获得有关错误、受影响行和实际数据库值的详细信息。如截图所示,DOB 列中第一行的内部值是 "39146<Ruined>",无法转换为有效的 DATE。
SQL DATA LENS 还允许您配置结果处理是在第一个错误单元格处停止,还是继续读取以检索所有可用数据。
本文的下一部分将详细介绍以下内容:
静默损坏(Silent Corruption):值已成功读取,但与预期的元数据不匹配。
未检测到的数据变异(Undetected Mutation):该值被读取且看似有效,但被驱动程序悄然修改以符合元数据要求,这使得这种不一致性难以被察觉。
文 | Andreas
