80

私が以前に尋ねた質問に関してフォローアップしています。この質問では、間抜けな/不十分に記述された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側の問題だと思いますが、よくわかりません。フィードバックをいただければ幸いです。

4

14 に答える 14

172

これは私に起こりました-Postgresの主キーフィールドを再同期する必要があることがわかりました。重要なのはSQLステートメントです。

SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1);
于 2012-06-19T01:41:00.280 に答える
38

これは、MySQL と SQLite (明示的な ID を持つオブジェクトを挿入する場合でも、次に利用可能な主キーを更新する) バックエンドと、Postgres、Oracle などの他のバックエンドの間の動作の既知の違いのようです ... (それらはありません) .

同じ問題を説明するチケットがあります。無効としてクローズされましたが、次に使用可能なキーを更新する Django 管理コマンドがあることを示唆しています。

アプリケーションMyAppのすべての次の ID を更新する SQL を表示するには:

python manage.py sqlsequencereset MyApp

ステートメントを実行するために、dbshel​​l管理コマンドの入力としてそれを提供できます。bash の場合、次のように入力できます。

python manage.py sqlsequencereset MyApp | python manage.py dbshell

管理コマンドの利点は、基礎となる DB バックエンドを抽象化するため、後で別のバックエンドに移行した場合でも機能することです。

于 2016-05-12T10:18:50.520 に答える
8

解決策は、SQL コードの例を書いた「Hacking Life」によって報告されたように、主キー フィールドを再同期する必要があることですが、「Ad N」で提案されているように、Django コマンドを実行しsqlsequenceresetて正確な SQL コードを取得することをお勧めします。コピーして貼り付けるか、別のコマンドで実行します。

これらの回答のさらなる改善として、SQLコードをコピーして貼り付けないで、より安全に、sqlsequenceresetこの方法でPythonコード内から生成された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.6Django 2.0、およびPostgreSQL 10でテストしました。

于 2018-05-10T15:34:42.673 に答える
3

データベースを手動でコピーした場合は、ここで説明されている問題が発生している可能性があります。

于 2012-06-18T20:00:04.930 に答える
0

OPと同じエラーが発生していました。

いくつかの Django モデルを作成し、モデルに基づいて Postgres テーブルを作成し、Django Admin を介して Postgres テーブルにいくつかの行を追加しました。次に、モデルのいくつかの列をいじりました (ForeignKeys などの変更) が、変更を移行するのを忘れていました。

移行コマンドを実行すると問題が解決しました。これは、上記の SQL の回答を考えると理にかなっています。

実際に適用せずに、どのような変更が適用されるかを確認するには:
python manage.py makemigrations --dry-run --verbosity 3

これらの変更に満足している場合は、次を実行します。
python manage.py makemigrations

次に実行します。
python manage.py migrate

于 2018-12-15T01:08:51.517 に答える