如果要存储的数据可能导致数据丢失,DuckDB将抛出错误
在DuckDB将大数字插入到 REAL (FLOAT4) 字段时会悄无声息地导致数据丢失或舍入误差。我猜这也会发生在其他数据类型的取值超出范围时,但遇到 REAL 的例子很容易。例如,下面的代码片段尝试将值 30000001 存储到几个字段中,但值 30000000 被错误地存储在 REAL 字段中,且没有抛出错误。
import {DuckDBInstance} from "@duckdb/node-api";
(async () => {
// CREATE A DUCKDB INSTANCE AND CONNECT TO IT
const db_instance = await DuckDBInstance.create(":memory:");
const connection = await db_instance.connect();
// CREATE A TABLE WITH REAL, DOUBLE, AND INTEGER VALUES
await connection.run(`
DROP TABLE IF EXISTS "my_data";
CREATE TABLE "my_data" (
"real" REAL,
"double" DOUBLE,
"integer" INTEGER
);
`);
await connection.run(
"INSERT INTO my_data VALUES (30000001, 30000001, 30000001)",
);
// QUERY THE TABLE TO VERIFY THE DATA WAS INSERTED CORRECTLY
const res = await connection.run("Select * from my_data");
const rows = await res.getRowObjectsJson();
console.log("stored data:", rows.length, rows[0]);
// prints: { real: 30000000, double: 30000001, integer: 30000001 }
})();
是否有办法让DuckDB在插入 / 更新时对会导致数据丢失的数值抛出错误?
解决方案
超出取值范围的数值会产生错误:
SELECT CAST(9999 AS TINYINT);
-- Conversion Error:
-- Type INT32 with value 9999 can't be cast because the value is out of range
-- for the destination type INT8
Floating-Point Types 本质上就是不精确的数据类型:
与定点数据类型类似,从字面量转换或从其他数据类型强制转换为浮点类型时,都会将不能被精确表示的输入存储为近似值
在大多数平台上,FLOAT类型的取值范围至少为1E-37到 1E+37,精度至少为6 位十进制数字。 DOUBLE类型通常的取值范围大约为1E-307到 1E+308,精度至少为15位
一般来说:
如果你需要对具有已知小数位数的数字进行精确存储,并且需要对加法、减法和乘法(如货币金额)进行精确运算,请改用DECIMAL数据类型或其NUMERIC别名。
没有溢出:
SELECT CAST(30000001 AS FLOAT);
┌─────────────────────────┐
│ CAST(30000001 AS FLOAT) │
│ float │
├─────────────────────────┤
│ 30000000.0 │
└─────────────────────────┘
PostgreSQL:
SELECT CAST(30000001 AS FLOAT4);
--float4
--3e+07
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。