H2 - CREATE TABLE 创建错误的数据类型

Posted

技术标签:

【中文标题】H2 - CREATE TABLE 创建错误的数据类型【英文标题】:H2 - CREATE TABLE creates wrong data type 【发布时间】:2017-03-20 15:28:55 【问题描述】:

目前无法使用 H2 内存数据库测试我的 DAL,因为数据类型 BINARY 已转换为 VARBINARY:

CREATE TABLE test (
  pk_user_id INT AUTO_INCREMENT(1, 1) PRIMARY KEY,
  uuid BINARY(16) UNIQUE NOT NULL
);

如果我检查具有预期数据类型的列是否存在,则会导致错误的数据类型:

2017-03-20 16:24:48 persistence.database.Table 检查意外列 (UUID) 或类型 (-3, VARBINARY)

【问题讨论】:

【参考方案1】:

tl;博士

导致错误的数据类型

不,不是错误类型,只是同一类型的另一个标签

二进制类型有五个同义词: BINARY | VARBINARY | LONGVARBINARY | RAW | BYTEA

所有五个名字都表示the same type,并且在Java中都映射到byte[]

数据类型名称的同义词

数据类型在 SQL 世界中没有严格定义。 SQL 规范只定义了几种类型。许多数据库系统通过许多名称定义了许多类型。为了使客户更容易从一个数据库系统移植到他们的数据库系统,数据库供应商通常会为数据类型实施同义词,以匹配其竞争对手的同义词类型。

与许多其他数据库系统一样,H2 具有多个数据类型的名称。对于将整个值加载到内存中的二进制类型,H2 为相同的单一数据类型定义了五个名称

二进制 |变量 | LONGVARBINARY |生 |白茶

同样,H2 通过五个同义词中的任何一个提供带符号的 32 位整数数据类型:

整数 |整数 |中型 | INT4 |签名

因此,您可以指定这五个名称中的任何一个,但您将获得相同的效果,即 H2 提供的相同基础数据类型。

确实,我自己运行代码来使用这五个二进制类型名称中的每一个来创建列。在每种情况下,列名称的元数据都将数据类型报告为VARBINARY

虽然在内部使用这五个中的哪一个来跟踪列的数据类型并不重要,但我对VARBINARY 的使用有点惊讶,因为H2 datatype documentation page 标题将此类型宣传为BINARY。所以我希望BINARY 默认在元数据中使用。如果您真的关心,您可能需要为此记录一个错误/问题,因为似乎应该将文档标题更改为 VARBINARY 或 H2 的数据类型内部标签应更改为 BINARY

以下是一些示例 Java JDBC 代码,用于确认您在问题中报告的行为。

我建议您更改您的数据类型检查代码以查找此数据类型的五个可能名称中的 任何一个,而不是仅检查一个特定名称。

try 
    Class.forName ( "org.h2.Driver" );
 catch ( ClassNotFoundException e ) 
    e.printStackTrace ( );

try ( Connection conn = DriverManager.getConnection ( "jdbc:h2:mem:" ) ;
      Statement stmt = conn.createStatement ( ) ; ) 
    String tableName = "test_";
    String sql = "CREATE TABLE " + tableName + " (\n" +
            "  pk_user_id_ INT AUTO_INCREMENT(1, 1) PRIMARY KEY,\n" +
            "  uuid_ BINARY(16) UNIQUE NOT NULL\n" +
            ");";
//            String sql = "CREATE TABLE " + tableName +
//                    "(" +
//                    " id_ INT AUTO_INCREMENT(1, 1) PRIMARY KEY, " +
//                    " binary_id_ BINARY(16) UNIQUE NOT NULL, " +
//                    " uuid_id_ UUID, " +
//                    " age_ INTEGER " + ")";
    stmt.execute ( sql );

    // List tables
    DatabaseMetaData md = conn.getMetaData ( );
    try ( ResultSet rs = md.getTables ( null, null, null, null ) ) 
        while ( rs.next ( ) ) 
            System.out.println ( rs.getString ( 3 ) );
        
    

    // List columns of our table.
    try ( ResultSet rs = md.getColumns ( null, null, tableName.toUpperCase ( Locale.US ), null ) ) 
        System.out.println ( "Columns of table: " + tableName );
        while ( rs.next ( ) ) 
            System.out.println ( rs.getString ( 4 ) + " | " + rs.getString ( 5 ) + " | " + rs.getString ( 6 ) ); // COLUMN_NAME, DATA_TYPE , TYPE_NAME.
        
    
 catch ( SQLException e ) 
    e.printStackTrace ( );

目录

校对

用户

观看次数

测试_

表格的列:test_

PK_USER_ID_ | 4 |整数

UUID_ | -3 |变量

提示:

为所有 SQL 名称添加尾随下划线可避免与 SQL 世界中发现的一千多个保留字中的任何一个发生冲突。 SQL 规范承诺 SQL 系统永远不会使用尾随下划线。例如,您使用的列名 uuid 可能与 H2 的 UUID 数据类型冲突。 您的代码uuid BINARY(16) 表明您正在尝试存储UUID(一个128 位值,其中某些位已定义语义)。注意H2 supports UUID natively 作为数据类型as does Postgres 和其他一些数据库系统。所以把uuid_ BINARY(16)改成uuid_ UUID

【讨论】:

以上是关于H2 - CREATE TABLE 创建错误的数据类型的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 函数 Create Table 给了我一个语法错误

SQL Server 中“CREATE TABLE table AS”中的“分发选项”错误

MySQL 语法错误中的 CREATE TABLE

SQL 语句“CREATE TABLE TRIP...”中的语法错误

org.h2.jdbc.JdbcSQLSyntaxErrorException:SQL 语句“CREATE[*] SCHEMA DATABASE”中的语法错误; SQL 语句:

数据库“tempdb”中的 CREATE TABLE 权限被拒绝