使用 Sequelize 插入 SQL 服务器时,大的浮点值会丢失
Large float values are lost when inserted into SQL Server using Sequelize
每当我尝试使用 sequelize ORM 插入大于 ~50k 的浮点数时,数据库就会填充其他内容。
对于此值 123456789.123456
我将其插入 11186.78219
。
其他一些同事得到了不同的输出,但对于其他输入,接近 11186.78219
就像 11177.782191683797
。我不确定这暗示了什么。
当我通过 node-mssql
客户端执行相同的插入时,一切正常,Sequelize 也在内部使用该客户端
所以我追踪了从 Sequelize 的模型的创建语句到 node-mssql
的执行路径,通过乏味的,直到 node.js 网络请求库,只是为了看到我的初始输入数字被保留全程无变化。
但是,发送请求后,发生了一些事情,数据库收到了不同的值。
直接在数据库上设置一个大值并通过 Sequelize 检索它也可以正常工作。
我创建了 this repo 以查看是否有人可以复制它。
编辑:我想我应该澄清一下我是如何使用 Sequelize :)
这是一个失败的用户模型和创建示例:
const User = sequelize.define('User', {
networth: {
type: DataTypes.FLOAT,
// none of these work
// type: DataTypes.FLOAT(20, 5),
// type: DataTypes.DECIMAL(20, 5),
// type: DataTypes.DOUBLE,
},
}, {
timestamps: false,
});
User.create({ networth: 123456798.123456 });
这个 node-mssql
示例有效,但是:
await pool.request()
.input('networth', sql.Float, float_value)
.query(`insert into users (networth) values (@networth)`)
编辑 2:我从 SQL Server Profiler 中获取了一些数据,显示了 Sequelize 和 node-mssql
调用之间的差异:
node-mssql: exec sp_executesql @statement=N'insert into users (networth) values (@networth)',@params=N'@networth float',@networth=123456798,123456
续集:exec sp_executesql @statement=N'INSERT INTO [Users] ([networth]) OUTPUT INSERTED.* VALUES (@0);',@params=N'@0 numeric(30, 15)',@0=11186.782191684157440
因此数据确实损坏了...
编辑 3:我想我找到了问题的根源并打开了一个问题 here.
它是为我复制的。 运行 应用程序,并在 Profiler 中捕获了流量。应用已发送
exec sp_executesql @statement=N'INSERT INTO [Users] ([networth]) OUTPUT INSERTED.* VALUES (@0);',@params=N'@0 numeric(30, 15)',@0=11186.782191684157440
在 运行 应用之后,用户 table 包含:
id networth
----------- ----------------------
1 11186.7821916842
所以这是 Sequelize v5 上的错误,it is resolved 在 master 分支上。
我也计划提交 PR 以将其集成到 v5 中。
每当我尝试使用 sequelize ORM 插入大于 ~50k 的浮点数时,数据库就会填充其他内容。
对于此值 123456789.123456
我将其插入 11186.78219
。
其他一些同事得到了不同的输出,但对于其他输入,接近 11186.78219
就像 11177.782191683797
。我不确定这暗示了什么。
当我通过 node-mssql
客户端执行相同的插入时,一切正常,Sequelize 也在内部使用该客户端
所以我追踪了从 Sequelize 的模型的创建语句到 node-mssql
的执行路径,通过乏味的,直到 node.js 网络请求库,只是为了看到我的初始输入数字被保留全程无变化。
但是,发送请求后,发生了一些事情,数据库收到了不同的值。
直接在数据库上设置一个大值并通过 Sequelize 检索它也可以正常工作。
我创建了 this repo 以查看是否有人可以复制它。
编辑:我想我应该澄清一下我是如何使用 Sequelize :)
这是一个失败的用户模型和创建示例:
const User = sequelize.define('User', {
networth: {
type: DataTypes.FLOAT,
// none of these work
// type: DataTypes.FLOAT(20, 5),
// type: DataTypes.DECIMAL(20, 5),
// type: DataTypes.DOUBLE,
},
}, {
timestamps: false,
});
User.create({ networth: 123456798.123456 });
这个 node-mssql
示例有效,但是:
await pool.request()
.input('networth', sql.Float, float_value)
.query(`insert into users (networth) values (@networth)`)
编辑 2:我从 SQL Server Profiler 中获取了一些数据,显示了 Sequelize 和 node-mssql
调用之间的差异:
node-mssql: exec sp_executesql @statement=N'insert into users (networth) values (@networth)',@params=N'@networth float',@networth=123456798,123456
续集:exec sp_executesql @statement=N'INSERT INTO [Users] ([networth]) OUTPUT INSERTED.* VALUES (@0);',@params=N'@0 numeric(30, 15)',@0=11186.782191684157440
因此数据确实损坏了...
编辑 3:我想我找到了问题的根源并打开了一个问题 here.
它是为我复制的。 运行 应用程序,并在 Profiler 中捕获了流量。应用已发送
exec sp_executesql @statement=N'INSERT INTO [Users] ([networth]) OUTPUT INSERTED.* VALUES (@0);',@params=N'@0 numeric(30, 15)',@0=11186.782191684157440
在 运行 应用之后,用户 table 包含:
id networth
----------- ----------------------
1 11186.7821916842
所以这是 Sequelize v5 上的错误,it is resolved 在 master 分支上。 我也计划提交 PR 以将其集成到 v5 中。