PostgreSQL multiple upsert without duplicates rises an error
我使用PostgreSQL 9.5,Ubuntu 16.04
我有一张空桌子:
1 2 3 4 5 6 7 8 | CREATE TABLE IF NOT EXISTS candles_1m( TIMESTAMP REAL PRIMARY KEY, OPEN REAL, close REAL, high REAL, low REAL, volume REAL ); |
然后我尝试做多个upsert(没有重复的'timestamp' - 主键):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | INSERT INTO candles_1m ( TIMESTAMP, OPEN, close, high, low, volume ) VALUES (1507804800, 5160, 5158.7, 5160, 5158.7, 5.40608574), (1507804740, 5157.5, 5160, 5160, 5156.1, 39.03357813), (1507804680, 5156.5, 5157.4, 5157.4, 5156, 33.54458319), (1507804620, 5151.3, 5156.5, 5157.5, 5151.2, 19.75590599) ON CONFLICT (TIMESTAMP) DO UPDATE SET OPEN = EXCLUDED.open, close = EXCLUDED.close, high = EXCLUDED.high, low = EXCLUDED.low, volume = EXCLUDED.volume; |
我收到并收到错误:
1 2 | ERROR: ON CONFLICT DO UPDATE command cannot affect ROW a SECOND TIME HINT: Ensure that no ROWS proposed FOR insertion WITHIN the same command have duplicate constrained VALUES. |
我不懂为什么? 那里没有重复! 但我的下一步将是创建一个请求,逐步添加(或更新)每一行(独立于重复项存在)。
正如其他人所指出的那样,这是因为您输入的两个值在转换为
Why?
因为浮点数在其范围内没有统一的精度 - 接近于零,它们可以更准确地表示非常小的分数,并且远非零,它们可以不准确地表示非常大的值。您的值高于精确表示每个整数的范围,因此只要插入它们,您的值就会有效地舍入到最接近的可表示值。
请注意,这不仅仅是重复问题,每次插入该表时实际上都会丢失数据。
How to fix it?
为列选择更合适的数据类型。如果您的时间戳永远不会有小数组件,则
从文档:
real 4 bytes variable-precision, inexact 6 decimal digits precision
你有两对相等的实数值:
1 2 3 4 5 6 7 8 | SELECT 1507804800::REAL = 1507804740::REAL AS r1r2, 1507804680::REAL = 1507804620::REAL AS r3r4 r1r2 | r3r4 ------+------ t | t (1 ROW) |
使用具有更好精度的类型。