Database H2数据库中的自动增量ID

Database H2数据库中的自动增量ID,database,auto-increment,h2,Database,Auto Increment,H2,有没有一种方法可以为表设置一个自动递增的BIGINT ID。 它可以这样定义 id bigint auto_increment 但这没有效果(它不会自动增加)。 我想插入除ID字段之外的所有字段-ID字段应由DBMS提供。 或者我需要调用一些东西来增加ID计数器吗?它适合我。JDBC URL:JDBC:h2:~/temp/test2 id bigint(size) zerofill not null auto_increment, drop table test; create table

有没有一种方法可以为表设置一个自动递增的BIGINT ID。 它可以这样定义

id bigint auto_increment
但这没有效果(它不会自动增加)。 我想插入除ID字段之外的所有字段-ID字段应由DBMS提供。
或者我需要调用一些东西来增加ID计数器吗?

它适合我。JDBC URL:
JDBC:h2:~/temp/test2

id bigint(size) zerofill not null auto_increment,
drop table test;
create table test(id bigint auto_increment, name varchar(255));
insert into test(name) values('hello');
insert into test(name) values('world');
select * from test; 
结果:

ID  NAME  
1   hello
2   world
非常简单:

id int auto_increment primary key

H2将自动创建序列对象

您也可以使用
默认值

create table if not exists my(id int auto_increment primary key,s text);
insert into my values(default,'foo');
IDENTITY
现代方法使用类型自动生成一个递增的64位长整数

H2中使用的单字语法是标准中定义的身份生成的缩写变体。见PDF文档中的摘要。其他数据库正在实现此功能

创建表事件\u
( 
pkey_uu标识不为空主键,--⬅ `标识“=自动递增的长整数。
name_uuchar不为空,
开始时间戳,时区不为空,
持续时间\uuvarchar不为空
) 
;
示例用法。无需为我们的
pkey
列值传递值,因为它是由H2自动生成的

插入事件(名称、开始、停止)
值(?,?)
;
还有Java

ZoneId z = ZoneId.of( "America/Montreal" ) ;
OffsetDateTime start = ZonedDateTime.of( 2021 , Month.JANUARY , 23 , 19 , 0 , 0 , 0 , z ).toOffsetDateTime() ; 
Duration duration = Duration.ofHours( 2 ) ;

myPreparedStatement.setString( 1 , "Java User Group" ) ;
myPreparedStatement.setObject( 2 , start ) ;
myPreparedStatement.setString( 3 , duration.toString() ) ; 
返回生成的密钥
语句。返回生成的密钥
您可以捕获执行insert命令期间生成的值。需要两个步骤。首先,在获取准备好的语句时传递标志

PreparedStatement pstmt = conn.prepareStatement( sql , Statement.RETURN_GENERATED_KEYS ) ;
语句::getGeneratedKeys
第二步是在执行准备好的语句后调用。您将获得一个
ResultSet
,其中的行是为创建的行生成的标识符

示例应用程序 下面是一个完整的示例应用程序。在Java14上运行,并启用以获得乐趣。使用H2版本1.4.200

package work.basil.example;

import org.h2.jdbcx.JdbcDataSource;

import java.sql.*;
import java.time.*;
import java.util.Objects;

public class H2ExampleIdentity
{
    public static void main ( String[] args )
    {
        H2ExampleIdentity app = new H2ExampleIdentity();
        app.doIt();
    }

    private void doIt ( )
    {
        JdbcDataSource dataSource = Objects.requireNonNull( new JdbcDataSource() );  // Implementation of `DataSource` bundled with H2.
        dataSource.setURL( "jdbc:h2:mem:h2_identity_example_db;DB_CLOSE_DELAY=-1" ); // Set `DB_CLOSE_DELAY` to `-1` to keep in-memory database in existence after connection closes.
        dataSource.setUser( "scott" );
        dataSource.setPassword( "tiger" );

        String sql = null;

        try (
                Connection conn = dataSource.getConnection() ;
        )
        {
            sql = """
                  CREATE TABLE event_
                     ( 
                        id_ IDENTITY NOT NULL PRIMARY KEY,  -- ⬅ `identity` = auto-incrementing integer number.
                        title_ VARCHAR NOT NULL ,
                        start_ TIMESTAMP WITHOUT TIME ZONE NOT NULL ,
                        duration_ VARCHAR NOT NULL
                      )
                  ;
                  """;
            System.out.println( "sql:  \n" + sql );
            try ( Statement stmt = conn.createStatement() ; )
            {
                stmt.execute( sql );
            }

            // Insert row.
            sql = """
                  INSERT INTO event_ ( title_ , start_ , duration_ )
                  VALUES ( ? , ? , ? )
                  ;
                  """;
            try (
                    PreparedStatement pstmt = conn.prepareStatement( sql , Statement.RETURN_GENERATED_KEYS ) ;
            )
            {
                ZoneId z = ZoneId.of( "America/Montreal" );
                ZonedDateTime start = ZonedDateTime.of( 2021 , 1 , 23 , 19 , 0 , 0 , 0 , z );
                Duration duration = Duration.ofHours( 2 );

                pstmt.setString( 1 , "Java User Group" );
                pstmt.setObject( 2 , start.toOffsetDateTime() );
                pstmt.setString( 3 , duration.toString() );

                pstmt.executeUpdate();
                try (
                        ResultSet rs = pstmt.getGeneratedKeys() ;
                )
                {
                    while ( rs.next() )
                    {
                        int id = rs.getInt( 1 );
                        System.out.println( "generated key: " + id );
                    }
                }
            }

            // Query all.
            sql = "SELECT * FROM event_ ;";
            try (
                    Statement stmt = conn.createStatement() ;
                    ResultSet rs = stmt.executeQuery( sql ) ;
            )
            {
                while ( rs.next() )
                {
                    //Retrieve by column name
                    int id = rs.getInt( "id_" );
                    String title = rs.getString( "title_" );
                    OffsetDateTime odt = rs.getObject( "start_" , OffsetDateTime.class );  // Ditto, pass class for type-safety.
                    Instant instant = odt.toInstant();  // If you want to see the moment in UTC.
                    Duration duration = Duration.parse( rs.getString( "duration_" ) );

                    //Display values
                    ZoneId z = ZoneId.of( "America/Montreal" );
                    System.out.println( "id_" + id + " | start_: " + odt + " | duration: " + duration + " ➙ running from: " + odt.atZoneSameInstant( z ) + " to: " + odt.plus( duration ).atZoneSameInstant( z ) );
                }
            }
        }
        catch ( SQLException e )
        {
            e.printStackTrace();
        }
    }
}
接下来,在运行时查看结果

Instant
OffsetDateTime
,&
zoneDateTime
在执行此操作时,我的JVM当前的默认时区是
America/Los_Angeles
。在存储时刻的时间点(2021年1月23日魁北克下午7点),美国/洛杉矶地区的
与UTC的偏移量落后8小时。因此,H2 JDBC驱动程序返回的
OffsetDateTime
对象被设置为偏移量
-08:00
。这确实是一种干扰,因此在实际工作中,我会立即将
OffsetDateTime
转换为UTC的
即时时间
,或是我心目中特定时区的
zoneDateTime
。要清楚地了解,
即时
偏移日期时间
分区日期时间
对象都将表示相同的同时时刻,即时间线上的相同点。每个人都通过不同的挂钟时间观看同一时刻。想象一下,加利福尼亚、魁北克和冰岛(其区域为UTC,偏移量为零)的3个人都在电话会议结束时交谈,他们每个人都在同一个巧合的时刻抬头看着各自墙上的时钟

生成的密钥:1

id|1 |开始|:2021-01-23T16:00-08:00 |持续时间:PT2H➙ 运行时间:2021-01-23T19:00-05:00[美国/蒙特利尔]至:2021-01-23T21:00-05:00[美国/蒙特利尔]


顺便说一下,在预订未来约会的应用程序的实际工作中,我们将在Java和数据库中使用不同的数据类型


我们会在Java中使用
LocalDateTime
ZoneId
。在数据库中,我们将使用一种类似于SQL标准类型的数据类型,即不带时区的时间戳,并使用第二列作为预期时区的名称。当从数据库中检索值以构建日程安排日历时,我们会将时区应用于存储的日期时间,以获得
ZonedDateTime
对象。这将允许我们在一天中的某个时间预订约会,而不考虑该管辖区的政客对UTC的偏移量所做的更改。

zerofill
不受H2数据库的支持。谢谢!我明白了,我的错误不在于create,而在于insert语句。我使用insert-into测试值('hello');如果你能+1,我会很高兴我的回答:-)它是在-1上的,我只能把它提高到0,我做到了。也许我错过了提高分数的机会。谢谢!你不需要把它抬高,没关系。我只是不明白为什么有人会投-1票给正确答案。。。可能有人不理解这个问题。存在另一种使用
default
的语法:
insert-into-test-values(默认为'hello')对于包含大量字段的表非常有用。如果您显示插入以及创建table@JesseBoyd谢谢你的建议。我添加了一个完整的示例应用程序,显示了表的创建、插入一行、检索生成的键以及将表转储到控制台。