web-dev-qa-db-ja.com

OracleのSEQUENCE.NEXTVALに相当するMySQL

次の表のIDの次の値を返すクエリを実行できるようにする必要があります。

CREATE TABLE animals (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     name CHAR(30) NOT NULL,
     PRIMARY KEY (id)
)

Oracleでは、シーケンスでNEXTVALを呼び出すことができ、次のシーケンスを提供します(注:テーブルで挿入を行う必要はありません)。

いろいろ調べてみたら、次のクエリを使用してauto_incrementの現在の値を見つけることができることがわかりました。

SELECT Auto_increment 
FROM information_schema.tables 
WHERE table_name='animals';

問題は、値が照会されるたびに値を増分したいことです。 Oracleでは、nextvalを呼び出すと、テーブルに行を挿入しなくてもシーケンスの値が増加します。

上記のクエリを変更して、返される値がクエリが最後に呼び出されたときと常に異なるようにする方法はありますか?つまり、Auto_incrementはチェックされるたびにインクリメントされ、クエリで使用されると新しい値が使用されます。

私はSpring JDBCTemplateを使用しているので、1つのクエリで実行できる場合はより良いです。

14
ziggy

InnoDBを使用したこの例は、インターロッククエリを使用して独自のカウンターを実装する方法を示しています。

http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

ギャップを作るには何が必要ですか? IDを予約するには?むしろ、すべてのコストで設計を「修正」し、シーケンスに触れるのではなく、他のモジュールを更新します。

シーケンスを明示的にインクリメントするのではなく、IDを割り当てて返すために各IDにデフォルト行(無効とマークされている)を挿入することでそれを暗示します。このアプローチは一貫性があり移植性があります。後で、明示的なシーケンス値を使用して挿入を強制する代わりに、一致するシーケンス値でこれらのデフォルト行を更新できます。これにはより多くのメモリが必要ですが、ロックは必要ありません。期限切れの行でのガベージコレクションがここで役立ちます。 「挿入または更新」ステートメントは、ガベージコレクションされた行を再作成できますが、私はこれを行いません。

6
Sam

http://docs.Oracle.com/cd/E17952_01/refman-5.5-en/example-auto-increment.html

3.6.9。 AUTO_INCREMENTを使用する

AUTO_INCREMENT属性を使用して、新しい行の一意のIDを生成できます。

CREATE TABLE animals (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     name CHAR(30) NOT NULL,
     PRIMARY KEY (id)
);

INSERT INTO animals (name) VALUES
    ('dog'),('cat'),('penguin'),
    ('lax'),('whale'),('ostrich');

SELECT * FROM animals;
Which returns:

+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  3 | penguin |
|  4 | lax     |
|  5 | whale   |
|  6 | ostrich |
+----+---------+

AUTO_INCREMENTカラムに値が指定されていないため、MySQLはシーケンス番号を自動的に割り当てました。列にNULLまたは0を明示的に割り当てて、シーケンス番号を生成することもできます。

LAST_INSERT_ID()SQL関数またはmysql_insert_id()C API関数を使用して、最新のAUTO_INCREMENT値を取得できます。これらの関数は接続固有であるため、その戻り値は、挿入も実行している別の接続の影響を受けません。

AUTO_INCREMENTカラムには、必要な最大シーケンス値を保持するのに十分な大きさの最小整数データ型を使用してください。列がデータ型の上限に達すると、シーケンス番号を生成する次の試行は失敗します。可能であれば、UNSIGNED属性を使用して、より大きな範囲を許可します。たとえば、TINYINTを使用する場合、最大許容シーケンス番号は127です。TINYINTUNSIGNEDの場合、最大は255です。セクション11.2.1「整数型(正確な値)-INTEGER、INT、SMALLINT、TINYINT、MEDIUMINT、BIGINT」を参照してくださいすべての整数型の範囲について。

注複数行の挿入の場合、LAST_INSERT_ID()およびmysql_insert_id()は実際に、挿入された最初の行からAUTO_INCREMENTキーを返します。これにより、レプリケーション設定の他のサーバーで複数行の挿入を正しく再現できます。

AUTO_INCREMENTカラムが複数のインデックスの一部である場合、MySQLはAUTO_INCREMENTカラムがある場合、AUTO_INCREMENTカラムで始まるインデックスを使用してシーケンス値を生成します。たとえば、animalsテーブルにPRIMARY KEY(grp、id)およびINDEX(id)のインデックスが含まれている場合、MySQLはシーケンス値を生成するためのPRIMARY KEYを無視します。その結果、テーブルにはgrp値ごとのシーケンスではなく、単一のシーケンスが含まれます。

1以外のAUTO_INCREMENT値で開始するには、次のようにCREATE TABLEまたはALTER TABLEでその値を設定します。

mysql> ALTER TABLE tbl AUTO_INCREMENT = 100; InnoDBノート

InnoDBテーブルの場合、一連のINSERTステートメントの途中で自動インクリメント値を含む列を変更する場合は注意してください。たとえば、UPDATEステートメントを使用して自動インクリメント列に新しいより大きな値を入力すると、後続のINSERTで「重複エントリ」エラーが発生する可能性があります。自動インクリメント値がすでに存在するかどうかのテストは、DELETEを実行した後、さらにINSERTステートメントを実行した場合、またはUPDATEステートメントの後ではなく、トランザクションをコミットした場合に発生します。

MyISAMノート

MyISAMテーブルの場合、複数列インデックスのセカンダリ列でAUTO_INCREMENTを指定できます。この場合、AUTO_INCREMENTカラムの生成値は、MAX(auto_increment_column)+ 1 WHERE prefix = given-prefixとして計算されます。これは、データを順序付けられたグループに入れたい場合に便利です。

CREATE TABLE animals (
    grp ENUM('fish','mammal','bird') NOT NULL,
    id MEDIUMINT NOT NULL AUTO_INCREMENT,
    name CHAR(30) NOT NULL,
    PRIMARY KEY (grp,id)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;
Which returns:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+

この場合(AUTO_INCREMENTカラムが複数カラムインデックスの一部である場合)、いずれかのグループで最大のAUTO_INCREMENT値を持つ行を削除すると、AUTO_INCREMENT値が再利用されます。これは、通常AUTO_INCREMENT値が再利用されないMyISAMテーブルでも発生します。

参考文献

AUTO_INCREMENTの詳細については、次を参照してください。

AUTO_INCREMENT属性を列に割り当てる方法:セクション13.1.17「CREATE TABLE構文」およびセクション13.1.7「ALTER TABLE構文」。

NO_AUTO_VALUE_ON_ZERO SQLモードに応じたAUTO_INCREMENTの動作:セクション5.1.7「サーバーSQLモード」。

LAST_INSERT_ID()関数を使用して、最新のAUTO_INCREMENT値を含む行を見つける方法:セクション12.14「情報関数」。

使用するAUTO_INCREMENT値の設定:セクション5.1.4「サーバーシステム変数」。

AUTO_INCREMENTとレプリケーション:セクション16.4.1.1「レプリケーションとAUTO_INCREMENT」。

レプリケーションに使用できるAUTO_INCREMENTに関連するサーバーシステム変数(auto_increment_incrementおよびauto_increment_offset):セクション5.1.4「サーバーシステム変数」。

http://search.Oracle.com/search/search?q=auto_increment&group=Documentation&x=0&y=

12
Ivan M.

http://www.microshell.com/database/mysql/emulating-nextval-function-to-get-sequence-in-mysql/ -で示されているように、独自のMySQL関数を追加できます。あなたはこのようなことをする:

SELECT nextval('sq_my_sequence') as next_sequence;
4
ziesemer

MySQLは、目的に役立つAUTO_INCREMENTを使用します。ただし、以下の違いがあります。

MySQL AUTO_INCREMENTとOracle SEQUENCEの違い

  • AUTO_INCREMENTはテーブルごとに1列に制限されています
  • AUTO_INCREMENTを特定のtable.columnに割り当てる必要があります(複数テーブルの使用を許可しない)
  • AUTO_INCREMENTは、指定されていない列またはNULLの値として挿入されます

mySQLでSEQUENCEの実装を確認したい場合は、SPで実行できます。

あなたが望むすべてを説明した以下のリンクを参照してください。

http://ronaldbradford.com/blog/sequences-in-mysql-2006-01-26/

2
user319198

自動インクリメントを使用している他のプロセスを妨害することなく、まだ挿入されていない行を作成できるように、THATテーブルに次の値が必要ですか?

いくつかのオプション:

先に進み、「シーケンスを使い果たす」ために行を挿入し、保留としてマークし、後で更新します。

トランザクションに挿入し、トランザクションを中止します-自動番号シーケンスは使い果たされ、通常はテーブルに「ギャップ」を作成するはずです-その番号は使用できるようになりました。

Oracleでは、シーケンスはテーブルから完全に独立しているため、プロセスはシーケンスを使用しても使用しなくてもかまいません(異なるテーブルに対して同じシーケンスを使用することもできます)。その流れで、ある種の関数を通じてアクセスするシーケンス専用テーブルを実装し、自動インクリメントに依存する必要がある他のプロセスについては、自動インクリメントを削除し、同じものから割り当てるトリガーを使用することができますIDが提供されない場合のシーケンス関数。

1
Cade Roux
1.) create table query
2.) Insert query
3.) Update query
4.) Select query for that table e.g. SELECT next_val FROM hib_sequence;
5.) Before each select update first, like this you can achieve similar

-- CREATE TABLE hib_sequence (next_val INT NOT NULL);
-- UPDATE hib_sequence SET next_val=LAST_INSERT_ID(next_val+1);
-- select last_insert_id();
-- INSERT INTO hib_sequence VALUES (0);

-- select next_val from hib_sequence;
0
Sumit

MariaDBs SEQUENCE Engineをご覧ください。それを使用すると、次のように簡単にシーケンスを生成できます

SELECT seq FROM seq_1_to_5;
+-----+
| seq |
+-----+
|   1 |
|   2 |
|   3 |
|   4 |
|   5 |
+-----+

詳細 ここ:https://mariadb.com/kb/en/mariadb/sequence/

これにより、次のようなことができるはずです

SELECT min(seq) as nextVal FROM seq_1_to_500 
WHERE seq NOT IN (SELECT ID FROM customers)
0
Benvorth