トップ回答者
Sql Server2012 の シーケンスについて

質問
-
現在 Java5 + SQL Server2012 で開発をしています。
シーケンスは以下のHPの CREATE SEQUENCE とほぼ同じで、キャッシュなしで作成しています。
http://msdn.microsoft.com/ja-jp/library/hh272694(v=vs.103).aspx
問題となっているのは、JavaからJDBC経由でシーケンス番号を取得すると、増分が余計に加算されて取得されることです。
上記HPのシーケンスで現在値10 とした場合に、シーケンス番号を「SELECT NEXT VALUE FOR dbo.Seq1 AS SEQ」のSQLで
取得する値と、"11"が返却されるのではなく、"12"が返却されます。SQL Server Management Studio や JDBCを使用してDBアクセスするツール「dbvisualizer」などから、上述のSQLを実行すると、
Javaのように余分に加算されず、+1された値が取得できます。jdbcの設定では、特別なプロパティで値を指定していません。
何かご存知の方がいましたら、教えてください。
よろしくお願いいたします。
※確認に使用したサンプルソースを添付します。
import java.sql.Connection; import java.sql.Driver; import java.sql.ResultSet; import java.sql.Statement; import java.util.Properties; public class SqlserverConnTest { public static void main(String[] args) { try { Driver d = (Driver) Class.forName( "com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance(); String connUrl = "jdbc:sqlserver://localhost:1433;DatabaseName=soil;ProgramName=geds;SelectMethod=cursor;" + "integratedSecurity=false;user=****;password=****"; Connection con = d.connect(connUrl, new Properties()); String SQL = "SELECT NEXT VALUE FOR dbo.Seq1 AS seq_no"; Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(SQL); while (rs.next()) { System.out.println( rs.getString("seq_no")); } rs.close(); stmt.close(); } catch (Exception e) { e.printStackTrace(); } } }
回答
-
以下、ご参考までに連携します。
個人的に、ResultSetで取得して、next()関数が1回かまされることで、「SELECT NEXT VALUE FOR」がもう一度評価されてしまっているからでは、、と思いました。
※ 私の環境にはSQLServer 2012が入っていないため、実際に動かしてみたわけではないのですが。。
上記の仮定を検証するため、以下のような操作を実施するのはいかがでしょうか。
【前提】
Seq1シーケンスの現在値が「10」
【実施操作】
上記プログラムのwhile文をコメントアウトし、実行。
【確認内容】
Seq1シーケンスの現在値が「11」(前提の値+1)になっているか、確認。
※ シーケンスのカレント値の確認
参考サイト:CREATE SEQUENCE (Transact-SQL)
SELECT current_value FROM sys.sequences WHERE name = 'Seq1' ;
-
少し時間が空いてしまいましたが、以下補足させていただきます。
やはり、「ResultSet rs = stmt.executeQuery(SQL);」を実行した時点と、「while (rs.next()) {」の両方でシーケンスがインクリメントされていたためであることがわかりました。
シーケンスのインクリメントした値を取得したい場合は、
SELECT NEXT VALUE FOR dbo.Seq1 AS seq_no
を実行した後に、
SELECT current_value FROM sys.sequences s WHERE s.name = 'Seq1'
というかたちで、カレント値を別途取得するなどの対応がよいかと思います。
SQLServer 2012をインストールできるPCに変更したため、せっかくなので検証させていただきました。
シーケンスは、インクリメントが正常に動くことが機能の根幹ですから、きちんと解決しておきたいと思ったためです。
- 回答としてマーク 佐伯玲 2013年3月4日 1:21
すべての返信
-
以下、ご参考までに連携します。
個人的に、ResultSetで取得して、next()関数が1回かまされることで、「SELECT NEXT VALUE FOR」がもう一度評価されてしまっているからでは、、と思いました。
※ 私の環境にはSQLServer 2012が入っていないため、実際に動かしてみたわけではないのですが。。
上記の仮定を検証するため、以下のような操作を実施するのはいかがでしょうか。
【前提】
Seq1シーケンスの現在値が「10」
【実施操作】
上記プログラムのwhile文をコメントアウトし、実行。
【確認内容】
Seq1シーケンスの現在値が「11」(前提の値+1)になっているか、確認。
※ シーケンスのカレント値の確認
参考サイト:CREATE SEQUENCE (Transact-SQL)
SELECT current_value FROM sys.sequences WHERE name = 'Seq1' ;
-
少し時間が空いてしまいましたが、以下補足させていただきます。
やはり、「ResultSet rs = stmt.executeQuery(SQL);」を実行した時点と、「while (rs.next()) {」の両方でシーケンスがインクリメントされていたためであることがわかりました。
シーケンスのインクリメントした値を取得したい場合は、
SELECT NEXT VALUE FOR dbo.Seq1 AS seq_no
を実行した後に、
SELECT current_value FROM sys.sequences s WHERE s.name = 'Seq1'
というかたちで、カレント値を別途取得するなどの対応がよいかと思います。
SQLServer 2012をインストールできるPCに変更したため、せっかくなので検証させていただきました。
シーケンスは、インクリメントが正常に動くことが機能の根幹ですから、きちんと解決しておきたいと思ったためです。
- 回答としてマーク 佐伯玲 2013年3月4日 1:21
-