Last active
October 7, 2017 03:20
-
-
Save eezis/7681066 to your computer and use it in GitHub Desktop.
A code snippet to update the "last_value" of postgres's sequence generator when it is out of sync with the actual values in your tables.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This utility addresses the InegrityError that occurs when you try to add a new record to | |
(probably a recently ported) postgres database while using Django, here's more . . . | |
duplicate key value violates unique constraint "<app>_<table>_pkey" | |
DETAIL: Key (id)=(2) already exists. | |
The problem here is that the Postgres sequence generators are out of sync with your data. | |
Here's a good overview: http://www.vlent.nl/weblog/2011/05/06/integrityerror-duplicate-key-value-violates-unique-constraint/ | |
I had a large number of tables and apps, so I wrote the script below to fix them all at once | |
Keep the alter_the_db flag set to False. Inspect the output, and only flip the flag when you are | |
certain all looks well. | |
Obviously, use the script at your own risk. It worked well for me, hope it saves others some time | |
""" | |
from django.db import connection | |
from south.db import db | |
tables = connection.introspection.table_names() | |
seen_models = connection.introspection.installed_models(tables) | |
def increase_last_value(appname): | |
for t in tables: | |
if appname in t: | |
q = "select id from %s order by id desc limit 1;" % (t) | |
highest_value = db.execute(q)[0][0] | |
alter_statement = "alter sequence %s_id_seq restart with %d;" % (t, highest_value+1) | |
# to inspect the "last_value" currently used by postgress, go to the psql prompt | |
# or python manage.py dbshell and issue this command: \d <app>_<table>_id_seq | |
# e.g. => \d poll_question_id_seq | |
print "tablename=> %s, highest_value_used=> %s, alter_statement=> %s" % (t, highest_value, alter_statement) | |
# flip this flag when you are ready to make actualy changes to the db | |
alter_the_db = False | |
if alter_the_db: | |
db.execute(alter_statement) | |
# substitue 'app[x]' with the name of your applications | |
increase_last_value('app1') | |
increase_last_value('app2') | |
increase_last_value('app3') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment