私は 以前に尋ねた質問 についてフォローアップしています。この質問では、間抜けな/よく書かれていないmysqlクエリからpostgresqlへの変換を求めました。私はそれで成功したと信じています。とにかく、mysqlデータベースからpostgresデータベースに手動で移動したデータを使用しています。次のようなクエリを使用しています。
"""
UPDATE krypdos_coderound cru
set is_correct = case
when t.kv_values1 = t.kv_values2 then True
else False
end
from
(select cr.id,
array_agg(
case when kv1.code_round_id = cr.id
then kv1.option_id
else null end
) as kv_values1,
array_agg(
case when kv2.code_round_id = cr_m.id
then kv2.option_id
else null end
) as kv_values2
from krypdos_coderound cr
join krypdos_value kv1 on kv1.code_round_id = cr.id
join krypdos_coderound cr_m
on cr_m.object_id=cr.object_id
and cr_m.content_type_id =cr.content_type_id
join krypdos_value kv2 on kv2.code_round_id = cr_m.id
WHERE
cr.is_master= False
AND cr_m.is_master= True
AND cr.object_id=%s
AND cr.content_type_id=%s
GROUP BY cr.id
) t
where t.id = cru.id
""" % ( self.object_id, self.content_type.id)
)
これがうまくいくと信じる理由があります。ただし、これは新しい問題につながりました。送信しようとすると、Djangoからエラーが表示されます。
IntegrityError at (some url):
duplicate key value violates unique constraint "krypdos_value_pkey"
私はここに投稿されたいくつかの回答を見ましたが、私の問題の解決策はまだ見つかりませんでした(関連する質問は興味深い読書のために作られましたが)。私はログにこれを見るが、これは明示的にinsert- Djangoを処理する必要がある:
STATEMENT: INSERT INTO "krypdos_value" ("code_round_id", "variable_id", "option_id", "confidence", "freetext")
VALUES (1105935, 11, 55, NULL, E'')
RETURNING "krypdos_value"."id"
ただし、それを実行しようとすると、重複キーエラーが発生します。実際のエラーは、以下のコードでスローされます。
# Delete current coding CodeRound.objects.filter(object_id=o.id,content_type=object_type,is_master=True).delete()
code_round = CodeRound(object_id=o.id,content_type=object_type,coded_by=request.user,comments=request.POST.get('_comments',None),is_master=True)
code_round.save()
for key in request.POST.keys():
if key[0] != '_' or key != 'csrfmiddlewaretoken':
options = request.POST.getlist(key)
for option in options:
Value(code_round=code_round,variable_id=key,option_id=option,confidence=request.POST.get('_confidence_'+key, None)).save() #This is where it dies
# Resave to set is_correct
code_round.save()
o.status = '3'
o.save(
シーケンスなどを確認しましたが、順序どおりになっているようです。この時点で私は何をすべきかわからない-それはDjangoの終わりに何かがあると思うが、私にはわからない。フィードバックは大歓迎です!
これは私に起こります-Postgresで主キーフィールドを再同期する必要があることがわかりました。キーはSQLステートメントです。
SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1)
これは、MySQLとSQLite(明示的なIDを持つオブジェクトを挿入する場合でも、次に利用可能な主キーを更新する)バックエンドと、Postgres、Oracleなどの他のバックエンドとの間の動作の既知の違いのようです。 。
同じ問題を説明するチケットがあります 。無効として閉じられたとしても、次の利用可能なキーを更新するためのDjango=管理コマンドがあるというヒントを提供します。
アプリケーションの次のすべてのIDを更新するSQLを表示するにはMyApp:
python manage.py sqlsequencereset MyApp
ステートメントを実行するために、dbshell管理コマンドの入力としてステートメントを提供できます。 bashの場合、次のように入力できます。
python manage.py sqlsequencereset MyApp | python manage.py dbshell
管理コマンドの利点は、基盤となるDBバックエンドが抽象化されるため、後で別のバックエンドに移行しても機能することです。
同じ問題がありました。 「在庫」アプリに既存のテーブルがあり、Django adminに新しいレコードを追加したかったので、次のメッセージが表示されました。
重複したキー値が一意の制約「inventory_part_pkey」に違反しています詳細:キー(part_id)=(1)は既に存在します。
前述のように、以下のコードを実行して、id-sをリセットするSQLコマンドを生成します。
python manage.py sqlsequencereset inventory
私の場合 python manage.py sqlsequencereset MyApp | python manage.py dbshell
は機能していませんでした
私の場合、それは:
ベギン; SELECT setval(pg_get_serial_sequence( '"inventory_signup"'、 'id')、coalesce(max( "id")、1)、max( "id")IS NOT NULL)FROM "inventory_signup "; SELECT setval(pg_get_serial_sequence( '" inventory_supplier "'、 'id')、coalesce(max(" id ")、1)、max(" id ")IS NOT NULL)FROM "inventory_supplier"; COMMIT;
F5で実行しました。
これですべてのテーブルが修正され、最後に新しいレコードがid = 1に追加されずに最後に追加されました。
Zapphodsの答えに加えて:
私の場合、すべての移行を削除したため、インデックス作成は実際には正しくありませんでした。データベースは、移行の段階ではなかったため、開発時におそらく10〜15回削除されました。
finished_product_template_finishedproduct_pkey
でIntegrityErrorが発生していました
私はpgadmin3を使用していましたが、どちらのインデックスが間違っていても重複キーエラーをスローして、constraints
に移動してインデックスを再作成しました。
そして、インデックスを再作成しました。
解決策は、サンプルのSQLコードを書いた「Hacking Life」によって報告された主キーフィールドを再同期する必要があることですが、「Ad N」によって示唆されるように、Djangoコマンドsqlsequencereset
コピーして貼り付けるか、別のコマンドで実行できる正確なSQLコードを取得します。
これらの回答に対するさらなる改善として、SQLコードをコピーして貼り付けないで、より安全に、pythonコード内からsqlsequencereset
によって生成されたSQLクエリを実行することをお勧めします。このように(デフォルトのデータベースを使用して):
from Django.core.management.color import no_style
from Django.db import connection
from myapps.models import MyModel1, MyModel2
sequence_sql = connection.ops.sequence_reset_sql(no_style(), [MyModel1, MyModel2])
with connection.cursor() as cursor:
for sql in sequence_sql:
cursor.execute(sql)
Python3.6、Django 2.およびPostgreSQL 1でこのコードをテストしました。
データベースを手動でコピーした場合は、 ここで説明する問題 が実行されている可能性があります。
私のように、すべてのテーブルでPKをリセットする場合は、 PostgreSQLが推奨する方法 を使用できます。
SELECT 'SELECT SETVAL(' ||
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1) ) FROM ' ||
quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
FROM pg_class AS S,
pg_depend AS D,
pg_class AS T,
pg_attribute AS C,
pg_tables AS PGT
WHERE S.relkind = 'S'
AND S.oid = D.objid
AND D.refobjid = T.oid
AND D.refobjid = C.attrelid
AND D.refobjsubid = C.attnum
AND T.relname = PGT.tablename
ORDER BY S.relname;
このクエリを実行した後、クエリの結果を実行する必要があります。通常、メモ帳にコピーして貼り付けます。次に、"SELECT
を見つけてSELECT
に、;"
を;
に置き換えます。 pgAdmin IIIにコピーして貼り付け、クエリを実行します。データベース内のすべてのテーブルをリセットします。上記のリンクで、より「専門的な」指示が提供されています。
間違った方法でsaveメソッドに余分な引数を渡していたため、このエラーが発生しました。
これに遭遇した人のために、UPDATEを強制してみてください:
instance_name.save(..., force_update=True)
force_insert
とforce_update
を同時に渡すことができないというエラーが発生した場合、おそらく私がしたように、いくつかのカスタム引数を間違った方法で渡しています。
OPと同じエラーが表示されていました。
私はいくつかのDjango=モデルを作成し、モデルに基づいてPostgresテーブルを作成し、Django Admin。モデルの一部の列(ForeignKeysなどを変更)が、変更の移行を忘れていました。
移行コマンドを実行することで問題が解決しました。これは上記のSQLの答えを考えると理にかなっています。
実際に適用せずに、どの変更が適用されるかを確認するには:python manage.py makemigrations --dry-run --verbosity 3
これらの変更に満足している場合は、次を実行します。python manage.py makemigrations
次に実行します:python manage.py migrate