「エラー:重複キー値が一意制約に違反する」を回避するためにテーブル構造を修正する


14

この方法で作成されたテーブルがあります:

--
-- Table: #__content
--
CREATE TABLE "jos_content" (
  "id" serial NOT NULL,
  "asset_id" bigint DEFAULT 0 NOT NULL,
   ...
  "xreference" varchar(50) DEFAULT '' NOT NULL,
  PRIMARY KEY ("id")
);

その後、IDを指定していくつかの行が挿入されます。

INSERT INTO "jos_content" VALUES (1,36,'About',...)

後で、IDなしでいくつかのレコードが挿入され、エラーで失敗します: Error: duplicate key value violates unique constraint

どうやらidはシーケンスとして定義されました:

ここに画像の説明を入力してください

挿入に失敗するたびに、存在しない値に増分し、クエリが成功するまで、シーケンス内のポインターが増加します。

SELECT nextval('jos_content_id_seq'::regclass)

テーブル定義の何が問題になっていますか?これを修正するスマートな方法は何ですか?


PostgreSQLでは、列名とテーブル名がすべて小文字の場合、引用符で囲む必要はありません。
ロドリゴ

回答:


18

テーブルの定義に問題はありません。
jos_content_id説明のない列名の代わりに、または何かを使用する帽子を除きますid
そして、おそらくの代わりに使用しますtextvarchar(50)

あなたのINSERT声明が問題です。

あなたとid列のように定義serial、あなたがのために手動で値を挿入するべきではありませんid。これらは、関連するシーケンスの次の値と衝突する場合があります。

ターゲット列の明示的なリストを提供し(ほとんどの場合、永続化されたINSERTステートメントに適しています)、シリアル列を完全に省略します

INSERT INTO jos_content(asset_id, some_column, ...)
VALUES (36,'About',...);

自動的に生成された列の値がすぐに必要な場合は、次のRETURNING句を使用します。

INSERT ...
RETURNING id;  -- possibly more

SOに関するこの関連する回答の詳細:

serial後で競合する可能性のある列に手動エントリがある場合は、シーケンスを現在の最大値idに設定して、これを1回修正ます

SELECT setval('jos_content_id_seq', max(id))
FROM   jos_content;

where jos_content_id_seqは、jos_content.id列defaultですでに見つけたが所有するシーケンスのデフォルト名です。しているように見えるxhzt8_content_id_seqあなたのケースでは、


更新:同様の問題がSOに現れ、新しいソリューションを思い付きました:


テキストはvarchar(50)より遅くありませんか?
ロドリゴ

2
@ロドリゴ:Postgresではありません。:より詳細な説明への上記のリンクありdba.stackexchange.com/a/21496/3684が。またはここ。dba.stackexchange.com/a/89433/3684
アーウィンブランドステッター

最後のテスト< depesz.com/2010/03/02/charx-vs-varcharx-vs-varchar-vs-text >は、サイズの制限が便利なほとんどのフィールドでvarchar(n)の方が速いことを確信しました(人々名前、メール、アドレス、種名など)。長さをチェックしないと、テキストは高速(または同じ)になります。
ロドリゴ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.