Oracle Number 数据类型的 Clickhouse 数据类型模拟

问题描述 投票:0回答:1

(Clickhouse - 23.11.2.11,Oracle - 11.2.0.3.0)。 我的任务是将数据从 Oracle 表加载到 Clickhouse 表中(使用 scala 代码)。

在 Oracle 中,表是用脚本创建的:

create table EAIST_LOT_SS
(
  id             NUMBER not null,
  registrynumber VARCHAR2(19) not null,
  tendersubject  VARCHAR2(2048),
  lotnumber      NUMBER not null,
  lotprice       NUMBER
);

column COLUMN_NAME format a15
column DATA_TYPE format a15

select column_name, data_type, nullable, data_length, data_precision, data_scale
from user_tab_columns where table_name ='EAIST_LOT_SS';

COLUMN_NAME     DATA_TYPE       NULLABLE DATA_LENGTH DATA_PRECISION DATA_SCALE
--------------- --------------- -------- ----------- -------------- ----------
ID              NUMBER          N                 22                
REGISTRYNUMBER  VARCHAR2        N                 19                
TENDERSUBJECT   VARCHAR2        Y               2048                
LOTNUMBER       NUMBER          N                 22                
LOTPRICE        NUMBER          Y                 22                

在 clickhouse 中,表格是用脚本创建的:

create table data.eaist_lot
(
  id                  UInt8 not null,
  registrynumber      FixedString(19) not null,
  tendersubject       FixedString(2048),
  lotnumber           Decimal64(18) not null,
  lotprice            Decimal64(18)
)ENGINE = MergeTree()
PRIMARY KEY (id);

scala 代码,尝试向表中添加一行。

  def saveToClickhouse(table: String, chConn: ClickHouseConnection): Unit = {
    val ps: PreparedStatement = chConn.prepareStatement(
      s"""insert into ${table}
        |select id, registrynumber, tendersubject, lotnumber, lotprice
        |from
        |input('id             UInt8,
        |       registrynumber FixedString(19),
        |       tendersubject  FixedString(2048),
        |       lotnumber      Decimal64(18),
        |       lotprice       Decimal64(18)
        |      ')
        |""".stripMargin)

    ps.setInt(1,1)
    ps.setString(2,"str 222")
    ps.setString(3,"str 333")
    ps.setDouble(4,1.2)
    ps.setDouble(5,2.3)

    ps.addBatch()
    ps.executeBatch()
  }

我有错误: 线程“main”中的异常 java.lang.IllegalArgumentException: BigDecimal(1200000000000000000.0) 应该介于 -1000000000000000000 和 1000000000000000000 之间,不包括这两个值

Clickhouse 中数字(不设置精度和小数位数)的最佳模拟是什么?

oracle scala numbers clickhouse
1个回答
0
投票

在 Oracle 中,

NUMBER
数据类型 是:

内置数据类型摘要

代码 数据类型 描述
2
NUMBER [ (p [, s]) ]
具有精度
p
和小数位数
s
的数字。精度
p
的范围可以从 1 到 38。小数位数
s
的范围可以从 -84 到 127。精度和小数位数都是十进制数字。
NUMBER
值需要 1 到 22 个字节。

...

使用以下形式指定一个整数:

NUMBER(p)

这表示精度为

p
且小数位数为
0
的定点数,相当于
NUMBER(p,0)

使用以下形式指定浮点数:

NUMBER 

缺少精度和小数位指示符指定了 Oracle 数字的最大范围和精度。

因此,不指定精度或小数位数的

NUMBER
相当于具有最大精度和未指定小数位数的
NUMBER(38,*)
,并且是浮点数。


Clickhouse 包含数字数据类型:

  • 整数类型:有符号和无符号整数(UInt8、UInt16、UInt32、UInt64、UInt128、UInt256、Int8、Int16、Int32、Int64、Int128、Int256)
  • 浮点数:浮点数(Float32 和 Float64)和十进制值

其中

DECIMAL
文档指出:

有符号定点数,可在加法、减法和乘法运算中保持精度。对于除法,最低有效数字将被丢弃(不四舍五入)。

参数

  • P
    - 精度。有效范围:[1:76]。确定数字可以有多少个小数位(包括分数)。默认精度为 10。
  • S
    - 规模。有效范围:[ 0 : P ]。确定分数可以有多少位小数。

Decimal(P)
相当于
Decimal(P, 0)
。同样,语法
Decimal
相当于
Decimal(10, 0)

取决于 P 参数值 Decimal(P, S) 是以下同义词:

  • P
    来自 [ 1 : 9 ] - 对于
    Decimal32(S)
  • P
    来自 [ 10 : 18 ] - 对于
    Decimal64(S)
  • P
    来自 [ 19 : 38 ] - 对于
    Decimal128(S)
  • P
    来自 [ 39 : 76 ] - 对于
    Decimal256(S)

因此

DECIMAL
是一个定点数。


Clickhouse 似乎没有与 Oracle

NUMBER
数据类型相同的等效数据类型。

如果您的

NUMBER
栏:

  • 仅包含整数值,那么您可以有效地将
    NUMBER
    用作
    NUMBER(38,0)
    ,并且在 Clickhouse 中可能是
    Int128
  • 如果您的数字列包含定点十进制值,并且将该列指定为
    NUMBER(38, s)
    是合适的,那么在 Clickhouse 中,这将是
    Decimal128(s)
    (假设 0 ≤
    s
    ≤ 38)。
  • 如果您确实使用 Oracle 中
    NUMBER
    (或
    NUMBER(38,*)
    )支持的全部精度和小数位数,那么 Clickhouse 似乎不支持该范围的值,您可以使用
    Float64
    来近似该值,或者可以将值存储为字符串。
© www.soinside.com 2019 - 2024. All rights reserved.