You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从数据库获取DECIMAL类型小数点前后的位数限制?

解决DECIMAL类型随机值生成问题

核心问题

你当前只通过ResultSetMetaData.getPrecision()获取了DECIMAL列的总位数,但DECIMAL类型需要**总精度(precision)和小数位数(scale)**两个参数才能生成符合格式的随机值。比如DECIMAL(4,2),总精度是6(4+2),但小数位数是2,你需要分别生成4位整数和2位小数的组合。

解决方案步骤

1. 补充收集小数位数(scale)

在收集列限制信息时,同时调用ResultSetMetaData.getScale(int column)获取DECIMAL列的小数位数:

List<Integer> columnPrecisions = new ArrayList<>();
List<Integer> columnScales = new ArrayList<>();
ResultSetMetaData metaData = resultSet.getMetaData();

for (int i = 1; i <= metaData.getColumnCount(); i++) {
    columnPrecisions.add(metaData.getPrecision(i));
    columnScales.add(metaData.getScale(i));
    // 同时收集你已有的columnTypes列表
}

2. 修改随机值生成逻辑

修改createRecords方法,新增小数位数参数,针对DECIMAL类型拆分整数和小数部分生成:

public List<List<String>> createRecords(List<String> columnTypes, List<Integer> columnPrecisions, List<Integer> columnScales) {
    List<String> record = new ArrayList<>();
    ThreadLocalRandom random = ThreadLocalRandom.current(); // 复用随机实例,提升效率

    for (int j = 0; j < columnTypes.size(); j++) {
        switch (columnTypes.get(j)) {
            case "DECIMAL":
                int precision = columnPrecisions.get(j);
                int scale = columnScales.get(j);
                int integerDigits = precision - scale;
                String decimalStr;

                if (integerDigits <= 0) {
                    // 处理整数部分为0的情况,比如DECIMAL(2,2)
                    int decimalPart = random.nextInt((int) Math.pow(10, scale));
                    decimalStr = String.format("0.%0" + scale + "d", decimalPart);
                } else {
                    // 生成整数部分(1到10^integerDigits -1)
                    long integerPart = random.nextLong(1, (long) Math.pow(10, integerDigits));
                    // 生成小数部分(补零到指定位数)
                    int decimalPart = random.nextInt((int) Math.pow(10, scale));
                    decimalStr = String.format("%d.%0" + scale + "d", integerPart, decimalPart);
                }
                record.add(decimalStr);
                break;

            case "INTEGER":
                record.add(String.valueOf(random.nextInt()));
                break;

            case "CHAR":
                record.add("'" + common.randomString(columnPrecisions.get(j)) + "'");
                break;

            default:
                log.error("未知数据类型:" + columnTypes.get(j));
        }
    }
    return new ArrayList<>(Collections.singleton(record));
}

3. 优化辅助方法(可选)

替换原convertMaxValueForRandomizer方法,用更简洁的方式生成位数对应的最大值:

public long getMaxValueByDigits(int digitCount) {
    if (digitCount <= 0) return 1;
    return (long) Math.pow(10, digitCount);
}

说明

  • 用ThreadLocalRandom替代Random,避免多线程环境下的性能问题。
  • 通过String.format确保小数部分始终是指定的位数(不足补零)。
  • 处理了整数部分为0的边界情况,适配DECIMAL(s,s)这类特殊定义。

内容的提问来源于stack exchange,提问作者GreenLi9ht

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 22:57:27