40

Tôi đang theo dõi question that I asked earlier trong đó tôi tìm cách chuyển đổi từ truy vấn mysql bị lỗi/kém bằng văn bản sang postgresql. Tôi tin rằng tôi đã thành công với điều đó. Dù sao, tôi đang sử dụng dữ liệu được di chuyển thủ công từ một cơ sở dữ liệu mysql đến một cơ sở dữ liệu postgres. Tôi đang sử dụng truy vấn trông giống như vậy:Tính toàn vẹnGiá trị khóa trùng lặp lỗi vi phạm ràng buộc duy nhất - django/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) 
) 

Tôi có lý do để tin rằng điều này hoạt động tốt. Tuy nhiên, điều này đã dẫn đến một vấn đề mới. Khi cố gắng để gửi, tôi nhận được một lỗi từ django cho biết: Thao

IntegrityError at (some url): 
duplicate key value violates unique constraint "krypdos_value_pkey" 

Tôi đã xem xét một số các câu trả lời được đăng trên đây và tôi đã không hoàn toàn tìm thấy giải pháp cho vấn đề của tôi (mặc dù các câu hỏi có liên quan đã thực hiện cho một số đọc thú vị). Tôi thấy điều này trong nhật ký của tôi, đó là thú vị bởi vì tôi không bao giờ dứt khoát gọi Insert- django phải xử lý nó:

STATEMENT: INSERT INTO "krypdos_value" ("code_round_id", "variable_id", "option_id", "confidence", "freetext") 
    VALUES (1105935, 11, 55, NULL, E'') 
    RETURNING "krypdos_value"."id" 

Tuy nhiên, cố gắng chạy có kết quả trong các lỗi khóa trùng lặp. Lỗi thực tế được ném vào mã bên dưới.

# 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(

Tôi đã kiểm tra chuỗi và thứ tự như vậy và chúng dường như theo thứ tự. Tại thời điểm này tôi không chắc chắn phải làm gì- Tôi cho rằng đó là một cái gì đó vào cuối django nhưng tôi không chắc chắn. Bất kỳ thông tin phản hồi sẽ được nhiều đánh giá cao!

+1

Một bên: Theo luật của De Morgan, điều kiện của bạn là 'chìa khóa [0]! =' _ 'Hoặc khóa!= 'csrfmiddlewaretoken'' tương đương với' không (khóa [0] == '_' và khóa == 'csrfmiddlewaretoken') '. Nó sẽ dễ dàng thấy rằng tình trạng bên trong không bao giờ thỏa mãn, vì vậy nó tương đương với 'không (Sai)', hay nói cách khác là 'Đúng'. Nhưng tại sao lại bận tâm với 'if'? –

+0

'python manage.py sqlsequencereset | python manage.py dbshell' – Medorator

+0

Câu trả lời trước này cung cấp chi tiết và ánh sáng chi tiết hơn về chủ đề: http://stackoverflow.com/questions/244243/how-to-reset-postgres-primary-key-sequence-when-it-falls -out-of-sync – RedSands

Trả lời

94

Điều này làm tôi khó chịu - hóa ra bạn cần phải đồng bộ hóa các trường khóa chính của bạn trong Postgres. Điều quan trọng là câu lệnh SQL:

SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1) 
+0

Đó là nó! Tôi nghĩ rằng tôi đã giải quyết vấn đề đó nhưng nó quay ra tôi đặt lại giá trị sai. –

+1

Tôi biết một loạt những người đã gặp sự cố này - tôi rất vui vì bạn đã giải quyết vấn đề này! –

+0

Tôi sắp hỏi @ HackingLife nếu bạn biết thêm về lý do tại sao điều này xảy ra ... hóa ra cho chúng tôi, đó là vì chúng tôi đã đồng bộ hóa tất cả dữ liệu từ một cơ sở dữ liệu khác nhau bằng cách sao chép trực tiếp (đó là zaphod được đề cập trong câu trả lời của anh ấy). Khi chúng tôi ngừng làm điều đó và bắt đầu sử dụng cơ sở dữ liệu chính trực tiếp, chuỗi khóa chính đã không được tăng lên khi một mô hình mới được thêm vào, tạo ra lỗi này. – AJP

3

Nếu bạn đã sao chép cơ sở dữ liệu theo cách thủ công, bạn có thể đang chạy vào issue described here.

2

Tôi gặp phải lỗi này vì tôi đã chuyển các đối số thừa vào phương thức lưu không đúng cách.

Đối với bất cứ ai chạm trán này, hãy thử buộc CẬP NHẬT với:

instance_name.save(..., force_update=True) 

Nếu bạn nhận được một lỗi mà bạn không thể vượt qua force_insertforce_update cùng một lúc, có lẽ bạn đang đi qua một số đối số tùy chỉnh một cách sai lầm , như tôi đã làm.

+0

Đây là một giải pháp tốt đẹp trong django. Từ trình bao chỉ cần nhập lớp mô hình của bạn (nếu bạn không sử dụng shell_plus) và sau đó làm MyModelClass.objects.first(). Save (force_update = True) –

5

Ngoài zapphods trả lời:

Trong trường hợp của tôi việc lập chỉ mục là thực sự không chính xác, vì tôi đã xóa tất cả di cư, và các cơ sở dữ liệu có thể 10-15 lần khi đang phát triển như tôi không phải là trong giai đoạn di cư bất cứ điều gì.

Tôi đã nhận được một IntegrityError trên finished_product_template_finishedproduct_pkey

reindex bàn và khởi động lại runserver:

Tôi đã sử dụng pgadmin3 và cho bất cứ chỉ số không chính xác và ném lặp lại lỗi chính tôi điều hướng đến constraints và lập chỉ mục.

enter image description here

Và sau đó được lập lại.

enter image description here

11

Nó dường như là một sự khác biệt nổi tiếng về hành vi giữa MySQL và SQLite (họ cập nhật khóa chính có sẵn tiếp theo ngay cả khi chèn một đối tượng với một id rõ ràng) backends, và backends khác như Postgres, Oracle , ... (họ không).

There is a ticket describing the same issue. Mặc dù nó đã bị đóng là không hợp lệ, nó cung cấp một gợi ý rằng có một lệnh quản lý Django để cập nhật khóa khả dụng tiếp theo.

Để hiển thị SQL cập nhật tất cả id tiếp theo cho ứng dụng MyApp:

python manage.py sqlsequencereset MyApp 

Để có báo cáo kết quả thực hiện, bạn có thể cung cấp nó như là đầu vào cho lệnh dbshell quản lý. Đối với bash, bạn có thể nhập:

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

Lợi thế của các lệnh quản lý là tóm tắt phần phụ DB bên dưới, vì vậy nó sẽ hoạt động ngay cả sau đó chuyển sang một chương trình phụ trợ khác.

1

Tôi gặp vấn đề tương tự. Tôi đã có một bảng hiện có trong "kho" của tôi ứng dụng và tôi muốn thêm kỷ lục mới trong django quản trị và tôi đã nhận những thông báo này:

trị khóa trùng lặp vi phạm hạn chế duy nhất "inventory_part_pkey" CHI TIẾT: Key (part_id) = (1) đã tồn tại.

Như đã đề cập trước khi chạy đoạn code dưới đây để có được tạo ra một lệnh SQL để thiết lập lại id-s:

python manage.py sqlsequencereset inventory 

Trong trường hợp của tôi python manage.py sqlsequencereset MyApp | python manage.py dbshell không hoạt động

  • Vì vậy, tôi sao chép câu lệnh SQL đã tạo.
  • Sau đó mở pgAdmin cho postgreSQL và mở db của tôi.
  • Nhấp vào biểu tượng 6. (Thực hiện truy vấn SQL tùy ý)
  • Sao chép câu lệnh được tạo.

Trong trường hợp của tôi đó là:

BEGIN; SELECT setval (pg_get_serial_sequence ('"inventory_signup"', 'id'), coalesce (max ("id"), 1), max ("id") KHÔNG KHÔNG) TỪ "inventory_signup"; SELECT setval (pg_get_serial_sequence ('"inventory_supplier"', 'id'), coalesce (max ("id"), 1), max ("id") KHÔNG KHÔNG) TỪ "inventory_supplier"; COMMIT;

Thực thi nó bằng F5.

Điều này cố định tất cả các bảng của tôi và cuối cùng thêm bản ghi mới vào cuối không cố gắng thêm nó vào id = 1 nữa.

+0

Câu trả lời này vừa lưu lại ngày của tôi! – Gambit2007