为什么从 Java 代码获取时 SQL 服务器序列跳了两个?
Why is SQL Server sequence jumping by two when fetched from Java code?
假设在 SQL 服务器上创建了一个序列:
CREATE SEQUENCE dbo.my_seq
START WITH 1
INCREMENT BY 1
NO CYCLE;
GO
以及以下 Java 代码来获取下一个序列值:
Connection conn = ...;
String sql = "SELECT NEXT VALUE FOR my_seq;";
try (Statement statement = conn.createStatement();
ResultSet resultSet = statement.executeQuery(sql)) {
while (resultSet.next()) {
long seq = resultSet.getLong(1);
System.out.println(seq);
}
}
为什么重复执行此代码时序列会跳两个?
2
4
6
我试过打开和关闭 CACHE
选项。没区别。
如果我在 Azure Data Studio 上多次执行相同的查询,序列将递增 1。
我是 运行 Microsoft SQL Server 2019 (RTM-CU15) (KB5008996) - 15.0.4198.2 (X64)。我用 com.microsoft.sqlserver:mssql-jdbc:10.2.0.jre8
和 com.microsoft.sqlserver:mssql-jdbc:11.1.1.jre8-preview
驱动程序尝试了相同的代码并得到了相同的行为。
我分析了 SQL 服务器查询历史,Java 代码每次执行只进行一次查询以获取下一个序列值。
According to Gary's answer 到类似的问题,这是使用 selectMethod=cursor
选项时的已知行为。只需从连接中删除此选项 URL,序列号将不再跳过。
如果出于某种原因必须使用 selectMethod=cursor
怎么办?然后尝试 sys.sp_sequence_get_range
存储过程,如下所示。
Connection conn = ...;
String sequenceName = "my_seq";
try (CallableStatement statement = conn.prepareCall("{call sys.sp_sequence_get_range(?, ?, ?)}")) {
statement.setString("sequence_name", sequenceName);
statement.setLong("range_size", 1);
statement.registerOutParameter("range_first_value", microsoft.sql.Types.SQL_VARIANT);
statement.execute();
long seq = statement.getLong("range_first_value");
System.out.println(seq);
}
即使启用了 selectMethod=cursor
选项,它也不会跳过序列号。
假设在 SQL 服务器上创建了一个序列:
CREATE SEQUENCE dbo.my_seq
START WITH 1
INCREMENT BY 1
NO CYCLE;
GO
以及以下 Java 代码来获取下一个序列值:
Connection conn = ...;
String sql = "SELECT NEXT VALUE FOR my_seq;";
try (Statement statement = conn.createStatement();
ResultSet resultSet = statement.executeQuery(sql)) {
while (resultSet.next()) {
long seq = resultSet.getLong(1);
System.out.println(seq);
}
}
为什么重复执行此代码时序列会跳两个?
2
4
6
我试过打开和关闭 CACHE
选项。没区别。
如果我在 Azure Data Studio 上多次执行相同的查询,序列将递增 1。
我是 运行 Microsoft SQL Server 2019 (RTM-CU15) (KB5008996) - 15.0.4198.2 (X64)。我用 com.microsoft.sqlserver:mssql-jdbc:10.2.0.jre8
和 com.microsoft.sqlserver:mssql-jdbc:11.1.1.jre8-preview
驱动程序尝试了相同的代码并得到了相同的行为。
我分析了 SQL 服务器查询历史,Java 代码每次执行只进行一次查询以获取下一个序列值。
According to Gary's answer 到类似的问题,这是使用 selectMethod=cursor
选项时的已知行为。只需从连接中删除此选项 URL,序列号将不再跳过。
如果出于某种原因必须使用 selectMethod=cursor
怎么办?然后尝试 sys.sp_sequence_get_range
存储过程,如下所示。
Connection conn = ...;
String sequenceName = "my_seq";
try (CallableStatement statement = conn.prepareCall("{call sys.sp_sequence_get_range(?, ?, ?)}")) {
statement.setString("sequence_name", sequenceName);
statement.setLong("range_size", 1);
statement.registerOutParameter("range_first_value", microsoft.sql.Types.SQL_VARIANT);
statement.execute();
long seq = statement.getLong("range_first_value");
System.out.println(seq);
}
即使启用了 selectMethod=cursor
选项,它也不会跳过序列号。