23

SERIAL ID を持つ postgres テーブルがあります。

id (serial) name age

通常、挿入は Web アプリケーションから行われます。

ID を max (id)+1 ****に設定して、2 つの新しいレコードを手動で挿入しました。

これらの 2 つの挿入後、Web アプリが 2 つのレコードを挿入すると、重複キー エラーが発生します。

2レコードだけ。その後、すべて正常に動作します。

問題は、手動挿入でシリアルがインクリメントされなかったのはなぜですか?

オートインクリメントとシリアルは違うのですか?

ここで何が欠けていますか?MySQL またはその他の SQL に同じ問題がありますか?

4

3 に答える 3

54

serialまたはbigserial列を作成すると、PostgreSQL は実際に次の 3 つのことを行います。

  1. intまたはbigint列を作成します。
  2. 列の値を生成するシーケンス (列が所有) を作成します。
  3. 列のデフォルト値をシーケンスの に設定しますnextval()

列を指定せずに値を INSERT する場合(またはその値としてserial明示的に指定する場合)は、シーケンスで次のように呼び出されます。DEFAULTnextval

  1. 列で次に使用可能な値を返します。
  2. シーケンスの値を増やします。

列にデフォルト以外の値を手動で指定するserialと、シーケンスは更新されず、列で既に使用されnextvalている値が返される可能性があります。serialしたがって、このようなことを行う場合は、nextvalまたはsetvalを呼び出してシーケンスを手動で修正する必要があります。

また、レコードは削除できるため、列のギャップserialが予想されるため、max(id) + 1同時実行性の問題がなくても使用することはお勧めできません。

serialまたはを使用している場合bigserial、最善の策は PostgreSQL に値の割り当てを任せて、それらがたまたま特定の順序で出てくる不透明な数字であるかのように見せかけることです。それらについて、一意性以外は何も仮定しません。この経験則は、すべてのデータベース IMO に適用されます。


MySQLauto_incrementがすべての異なるデータベースタイプでどのように機能するかはわかりませんが、おそらく細かいマニュアルが役立つでしょう.

于 2013-08-22T20:08:03.567 に答える
8

列のあるテーブルにレコードを挿入する場合serialは、クエリから省略してください。自動的に生成されます。

または、次のような方法でデフォルト値を挿入できます。

insert into your_table(id, val)
values (default, '123');

3番目のオプションは、シリアルシーケンスから値を直接取得することです。

insert into your_table(id, val)
values (nextval(pg_get_serial_sequence('your_table','id')), '123');
于 2013-08-22T20:11:13.140 に答える
3

ID を max (id)+1* に設定して 2 つの新しいレコードを手動で挿入しました*

このアプローチは完全に間違っており、どのデータベースでも機能しません。これまでのところ、MySQL では運が良かっただけです。

2 つの接続が同時にこれを実行すると、同じ ID が取得されます。一度に 1 つの接続のみが ID を取得できるように、同時読み取りに対してテーブルをロックする場合にのみ、確実に機能します。

それもひどく非効率です。

これがシーケンスが存在する理由であり、同時挿入子が存在する場合でも ID を確実に取得できます。

使用するだけです:

INSERT INTO my_table(data1, data2) VALUES ('a','b') RETURNING id;

また:

INSERT INTO my_table(id, data1, data2) VALUES (DEFAULT, 'a','b') RETURNING id;

DEFAULTテーブル定義からその列のデフォルトを取得するようにデータベースに指示する特別なプレースホルダーです。デフォルトはnextval('my_table_id_seq')であるため、次のシーケンス値が挿入されます。

シーケンスに関する基本的な質問をしているため、シーケンスはギャップレスではないことも考慮することをお勧めします。シーケンスに「穴」があり、テーブルの値が 1、3、4、5、9、10、... になるのは正常です。

于 2013-08-23T00:57:01.900 に答える