我使用触发器填充同一个表的其他两列中的
SDO_POINT_TYPE
或 SDO_GEOMETRY
列。DROP TABLE test;
CREATE TABLE test (LONGITUDE BINARY_DOUBLE, LATITUDE BINARY_DOUBLE, p SDO_point_type);
CREATE OR REPLACE TRIGGER TEST_TRIGGER
BEFORE UPDATE OF LATITUDE, LONGITUDE ON TEST
FOR EACH ROW
BEGIN
:new.p := sdo_point_type(:new.LONGITUDE, :new.LATITUDE, NULL);
END;
INSERT INTO test(p) VALUES(NULL);
UPDATE test SET longitude=-14.19, latitude=48.33; -- use trigger
INSERT INTO test(p, longitude, latitude) VALUES(sdo_point_type(-14.19, 48.33, NULL), -14.19, 48.33); -- no trigger
SELECT CAST(latitude AS VARCHAR2(100)) AS lat, CAST(t.p.y AS VARCHAR2(100)) AS point_lat FROM test t;
-- LAT POINT_LAT
-- 4,8329999999999998E+001 48,329999999999998 -- with trigger
-- 4,8329999999999998E+001 48,33 -- without trigger
停止使用
BINARY_DOUBLE
并使用 NUMBER
。
来自 Oracle 数据类型文档:
代码 数据类型 描述 2 NUMBER [ (p [, s]) ]
具有精度 和小数位数p
的数字。精度s
的范围可以从 1 到 38。小数位数p
的范围可以从 -84 到 127。精度和小数位数都是十进制数字。s
值需要 1 到 22 个字节。NUMBER
101 BINARY_DOUBLE
64 位浮点数。该数据类型需要 8 个字节。
浮点数
[...]
二进制浮点数与
的不同之处在于 Oracle 数据库内部存储值的方式。值使用NUMBER
的十进制精度存储。所有在NUMBER
支持的范围和精度内的文字都完全按照NUMBER
存储。因为文字是使用十进制精度(数字 0 到 9)表示的,所以文字被精确存储。二进制浮点数使用二进制精度(数字 0 和 1)存储。这种存储方案无法精确地使用十进制精度表示所有值。通常,将值从十进制精度转换为二进制精度时发生的错误在将值从二进制精度转换回十进制精度时会被撤消。字面上的 0.1 就是这样一个例子。NUMBER
这意味着:
BINARY_DOUBLE
存储数字的最接近的近似值。NUMBER
存储准确的数字(前提是该数字在精度和小数位数指定的范围内)。48.33
不可能使用 IEEE 64 位浮点数精确存储,最接近的可能表示是 48.329999999999998
。您可以使用 NUMBER
数据类型准确存储它。
因此,如果您想精确存储值,请使用精确的数据类型。