oracle ORA-01722:无效号码(仅适用于MacOS PC)

vcirk6k6  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(173)

实体

@Entity
@Table(name = "policy_restriction_bound",
    uniqueConstraints = @UniqueConstraint(columnNames = {"policy_restriction_id", "upperBound", "currency"},
        name = "uq_policy_restriction_bound_restr_id_bound_currency"))
public class PolicyRestrictionBoundEntity {
    public static final int UPPER_BOUND_SCALE = 5;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence-generator")
    @SequenceGenerator(name = "sequence-generator", sequenceName = "hibernate_sequence", allocationSize = 5)
    private Long id;

    @NotNull
    @ManyToOne
    @JoinColumn(name = "policy_restriction_id", foreignKey = @ForeignKey(name = "fk_policy_restr_bound2policy_restr"))
    private PolicyRestrictionEntity policyRestriction;

    @NotNull
    private Integer minimumApprovesCount;

    @Positive
    @Access(AccessType.PROPERTY)
    private BigDecimal upperBound;

    @Size(min = 1, max = 3)
    private String currency;
}

容器

private static final OracleContainer DB_CONTAINER = new OracleContainer("gvenzl/oracle-xe:18.4.0-slim-faststart");

以下内容正在插入Oracle数据库

protected List<String> getInsertTestDataAfterMigrationCommands() {
        return List.of("""
            """
                INSERT into policy_restriction_bound(id, policy_restriction_id, minimum_approves_count, upper_bound, currency)
                VALUES ('1', '1', '2', '99.99000', 'USD')"""
        );
    }

误差

java.lang.RuntimeException: java.sql.SQLSyntaxErrorException: ORA-01722: invalid number
Caused by: Error : 1722, Position : 134, Sql = INSERT into policy_restriction_bound(id, policy_restriction_id, minimum_approves_count, upper_bound, currency)
VALUES ('1', '1', '2', '99.99000', 'USD'), OriginalSql = INSERT into policy_restriction_bound(id, policy_restriction_id, minimum_approves_count, upper_bound, currency)
VALUES ('1', '1', '2', '99.99000', 'USD'), Error Msg = ORA-01722: invalid number

    at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:637)

你好,我是
我通过上面的getInsertTestDataAfterMigrationCommands()方法插入数据。但我得到ORA-01722: invalid number错误。当我删除' 99.99000 '中的单引号时,错误消失了。但我想知道的是,我们只得到这个错误的所有MacBook用户在团队中。这不会在同样通过Jenkins Pipeline的Linux和Windows PC上发生错误。
同样,当我删除单引号时,再次通过Jenkins管道。同样有趣的是,我们只接收到具有BigDecimal值的单引号问题。其他领域没有问题。
我找不到为什么我们只在Macbook PC上得到这个错误的原因,你有什么想法吗?
补充:我注意到MacBook上的智能报价被打开了。我禁用了它,但我们继续得到错误。

gywdnpxw

gywdnpxw1#

摘要:Never依赖于隐式的字符串到数字的转换。如果你想传递一个数值,那么就把它作为数字传递,而NOT作为字符串传递。
当你在NUMBER列中插入一个字符串时,你要求Oracle执行一个隐式的字符串到数字的转换,如果十进制分隔符不是.,那么'99.99000'将给予错误:

ORA-01722: invalid number

(In Oracle 23,错误信息更多:ORA-01722: unable to convert string value containing '.' to a number: .)
如果您更改会话参数,您可以看到这一点:

CREATE TABLE policy_restriction_bound(
  id                     NUMBER(8,0),
  policy_restriction_id  NUMBER(8,0),
  minimum_approves_count NUMBER(8,0),
  upper_bound            NUMBER(10,5),
  currency               VARCHAR2(3)
);

然后又道:

ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ',.';
INSERT into policy_restriction_bound(id, policy_restriction_id, minimum_approves_count, upper_bound, currency)
VALUES ('1', '1', '2', '99.99000', 'USD');

输出:

ORA-01722: invalid number

以及:

ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,';
INSERT into policy_restriction_bound(id, policy_restriction_id, minimum_approves_count, upper_bound, currency)
VALUES ('1', '1', '2', '99.99000', 'USD');

工程.
你应该做的是永远不要依赖于隐式的字符串到数字的转换。如果你想传递一个数值,那么就把它作为数字传递,而NOT作为字符串传递。
如果必须传递字符串(不要),那么请确保所有测试容器都使用与生产数据库相同的会话参数,以便行为相同。
根据JDBC驱动程序的不同,这可能是:
1.连接的默认会话参数,可能来自操作系统中设置的language of the OSNLS_LANG环境变量。
1.启动Java时运行Java应用程序和explicitly specifying the language and locale

-Duser.country=en -Duser.language=en

这可能导致JDBC驱动程序覆盖任何默认数据库设置并设置NLS_LANGNLS_TERRITORY会话参数(这将为该区域设置默认的NLS_NUMERIC_CHARACTERS会话参数)。

  1. Setting a locale in the Java application
Locale.setDefault(Locale.<your locale here>);

这可能会导致JDBC驱动程序覆盖任何默认的数据库设置,并设置NLS_TERRITORY(可能还有NLS_LANG)会话参数(这将为该区域设置默认的NLS_NUMERIC_CHARACTERS会话参数)。
1.在Java应用程序的SQL中,在数据库会话中显式设置NLS_TERRITORY设置(这将隐式地为该区域设置默认的NLS_NUMERIC_CHARACTERS),并覆盖连接的任何默认设置。

ALTER SESSION SET TERRITORY = 'United States'

1.在Java应用程序的SQL中,显式设置NLS_NUMERIC_CHARACTERS会话参数(同样覆盖默认值)。

ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,'

但最好是永远不要依赖隐式转换。
fiddle

相关问题