Why the table is not created despite the Python script ran successfully in IDLE? - python-2.7

Here is my script that ran successfully, but still i cannot see the table being created in SQL Server's database.
import _mssql
conn = _mssql.connect(server='MAQSOOD-PC', user='sa', password='123', \
database='TestDB')
conn.execute_non_query('CREATE TABLE persons(id INT, name VARCHAR(100))')
conn.execute_non_query("INSERT INTO persons VALUES(1, 'John Doe')")
conn.execute_non_query("INSERT INTO persons VALUES(2, 'Jane Doe')")
What could be the issue?

I believe the issue is that you need to commit the transaction.
Try this version instead:
import pymssql
conn = pymssql.connect('MAQSOOD-PC', 'sa', '123', 'tempdb')
cur = conn.cursor()
cur.execute('CREATE TABLE persons(id INT, name VARCHAR(100))')
cur.commit()
cur.execute("INSERT INTO persons VALUES (1, 'John Doe')")
cur.execute("INSERT INTO persons VALUES (2, 'Jane Doe')")
cur.commit()
cur.execute('SELECT * FROM persons')
for row in cur:
print(row)

Related

Redshift table lock

I am trying to load Redshift table from stage table.
Whenever I try to insert data from the stage table, Redshift is locking table2 and it is not inserting any data.
Here is the python code:
insertSQL = "insert into table2 select c1,c2,c3,c4 FROM table_name "
load_redshift_table(insertSQL)
def load_redshift_table(insertSQL):
try:
conn = psycopg2.connect(
host="host",port="redshift_port",database="redshift_database",user="redshift_user",password="reshift_password")
cur = conn.cursor()
cur.execute(insertSQL)
conn.commit()
except Exception as e:
print("Error:", e)
finally:
cur.close()

How to delete duplicate rows from a table using Django ORM?

I have a database table bad_reviews and a corresponding Django model BadReviews. I want to delete duplicate records based on the fields client_id, survey_id, text, rating, privacy_agreement. I've come up with this query which works:
SELECT br.*
FROM bad_reviews br
JOIN (
SELECT client_id, survey_id, text, rating, privacy_agreement, COUNT(*)
FROM bad_reviews
GROUP BY client_id, survey_id, text, rating, privacy_agreement
HAVING count(*) > 1
) dupes
ON br.client_id = dupes.client_id
AND br.survey_id = dupes.survey_id
AND br.text = dupes.text
AND br.rating = dupes.rating
AND br.privacy_agreement = dupes.privacy_agreement
ORDER BY br.client_id, br.survey_id, br.text, br.rating, br.privacy_agreement, br.id
How to rewrite it using Django ORM?
I hope this will work.
from django.db.models import Count, Subquery
# Equivalent of this query in with Django ORM: SELECT client_id, survey_id, text, rating, privacy_agreement, COUNT(*)
# FROM bad_reviews
# GROUP BY client_id, survey_id, text, rating, privacy_agreement
# HAVING count(*) > 1
subquery = BadReviews.objects \
.values('client_id', 'survey_id', 'text', 'rating', 'privacy_agreement') \
.annotate(count=Count('id')).filter(count__gt=1)
# use the subquery as a filter in the main query
bad_reviews = BadReviews.objects.filter(
client_id=Subquery(subquery.values('client_id')),
survey_id=Subquery(subquery.values('survey_id')),
text=Subquery(subquery.values('text')),
rating=Subquery(subquery.values('rating')),
privacy_agreement=Subquery(subquery.values('privacy_agreement')),
).order_by('client_id', 'survey_id', 'text', 'rating', 'privacy_agreement', 'id')

Django ORM DB Query Optimization

I have a Query that consists of two DB hits.
which the first contains 'aggregate' - so it perform immediately.
I want to know if I can reduce it to only one DB hit.
The query is:
"Find customers that their id's numbers are bigger than all of texas's customers id's."
The two querysets are:
highest_tx_id = Customer.objects.filter(state='TX').aggregate(Max('id'))
res = Customer.objects.filter(id__gt=highest_tx_id['id_max'])
Adding an example:
>>> reset_queries()
>>> highest_tx_id = Customer.objects.filter(state='TX').aggregate(Max('id'))
>>> res = Customer.objects.filter(id__gt=highest_tx_id['id__max'])
>>> connection.queries
[{'sql': 'SELECT MAX("customer"."id") AS "id__max" FROM "customer" WHERE "customer"."state" = \'TX\'', 'time': '0.001'}]
>>> res
<QuerySet [<Customer: Customer object (550)>, <Customer: Customer object (551)>, <Customer: Customer object (552)>, <Customer: Customer object (553)>, <Customer: Customer object (555)>, <Customer: Customer object (661)>, <Customer: Customer object (665)>]>
>>> connection.queries
[{'sql': 'SELECT MAX("customer"."id") AS "id__max" FROM "customer" WHERE "customer"."state" = \'TX\'', 'time': '0.001'}, {'sql': 'SELECT "customer"."id", "customer"."fname", "customer"."lname", "customer"."address", "customer"."city", "customer"."state", "customer"."zip_code", "customer"."phone", "customer"."company_name" FROM "customer" WHERE "customer"."id" > 444 LIMIT 21', 'time': '0.001'}]
>>>
Any way to do these type of queries using 1 DB hit ?
Building up on #TaipanRex's answer, you can do something like this:
from django.db.models import Subquery
highest_tx_id = Customer.objects.filter(state='TX').order_by('-id').values('id')[:1]
res = Customer.objects.filter(id__gt=Subquery(highest_tx_id))
You can try using Subquery.
from django.db.models import Subquery
highest_tx_id = Customer.objects.filter(state='TX').aggregate(Max('id'))['id__max']
res = Customer.objects.filter(id__gt=Subquery(highest_tx_id))

Set Django auto-increment primary key to specific value [duplicate]

I have a User model, I want its id start from 10000, then its id should auto-increment like:
10001, 10002, 10003, 10004...
My User class:
class User(AbstractUser):
username = models.CharField(max_length=64)
...
Is it possible to make it come true?
EDIT-1
Before ask this question, I have read this link:Is there a way to set the id value of new Django objects to start at a certain value?
But I don't think the answers are good, so I mean if in Django there is a configuration for achieve this?
the way is the same as to do datamigrations with RAW_SQL, change APPNAME on your:
python manage.py makemigrations APPNAME --empty
inside the created file:
operations = [
migrations.RunSQL(
'ALTER SEQUENCE APPNAME_USER_id_seq RESTART WITH 10000;'
)
]
The solution is to set autoincrement field like:
user_id = models.AutoField(primary_key=True)
After this, you can run this command on the database side. You can run this python command by using signals:
ALTER SEQUENCE user_id RESTART WITH 10000;
You can do this by different method.
from django.db.models.signals import post_syncdb
from django.db import connection, transaction
cursor = connection.cursor()
cursor = cursor.execute(""" ALTER SEQUENCE user_id RESTART WITH 10000; """)
transaction.commit_unless_managed()
post_syncdb.connect(auto_increment_start, sender=app_models)
In Django, a model can't have more than one AutoField. And this is used to set a primary key different from the default key.
My solution is to do it manually:
$ ./manage.py shell
Python 3.6.5 (default, Apr 1 2018, 05:46:30)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: from django.contrib.auth.models import User
In [2]: u = User.objects.create_user('name', '', '')
In [3]: User.objects.filter(id=u.id).update(id=10000-1)
Out[3]: 1
In [4]: u.delete()
Out[4]:
(0,
{'admin.LogEntry': 0,
'auth.User_groups': 0,
'auth.User_user_permissions': 0,
'auth.User': 0})
In [5]: uu = User.objects.create_user('user', '', '')
In [6]: uu.id
Out[6]: 10000
For MySQL add this in your migration file:
Replace TABLE_NAME and START_VALUE with your table's name and value with which you want to start.
operations = [
migrations.RunSQL('ALTER TABLE TABLE_NAME AUTO_INCREMENT=START_VALUE ;')
]

Django + PostgreSQL: How to reset primary key?

I have been working on an application in Django. To begin with, for simplicity, I had been using sqlite3 for the database.
However, once I moved to PostgreSQL, I've run into a bit of a problem: the primary key does not reset once I clear out a table.
This app is a game that is played over a long time period (weeks). As such, every time a new game starts, all of the data is cleared out of the database and then new, randomized data is added.
I'd like to be able to "start over" with primary keys starting at 1 each time I clean/rebuild the game.
The code still works as-is, but integers are a pretty natural way for describing the objects in my game. I'd like to have each new game start at 1 rather than wherever the last game left off.
How can I reset the primary key counter in PostgreSQL? Keep in mind that I don't need to preserve the data in the table since I am wiping it out anyway.
In your app directory try this:
python manage.py help sqlsequencereset
Pipe it into psql like this to actually run the reset:
python manage.py sqlsequencereset myapp1 myapp2 | psql
Edit: here's an example of the output from this command on one of my tables:
BEGIN;
SELECT setval('"project_row_id_seq"', coalesce(max("id"), 1), max("id") IS NOT null) FROM "project_row";
COMMIT;
As suggested by "Van Gale" you can get the commands to solve your problem running sqlsequencereset.
or
You can execute the SQL query generated by sqlsequencereset from within python in this way (using the default database):
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)
I tested this code with Python3.6, Django 2.0 and PostgreSQL 10.
If you perform a raw sql, can do this:
ALTER SEQUENCE youApp_id_seq RESTART WITH 1;
docs:
http://www.postgresql.org/docs/8.2/static/sql-altersequence.html
I view auto-increment primary keys as purely internal identifiers for database records, and I don't like exposing them to users. Granted, it's a common design to use them as part of URLs, but even there slugs or other identifiers feel more appropriate.
If you do not want to have to manually grab the apps you need, or if you have a series of different databases, this command will dynamically gather all connections from settings.py and reset the sequence.
To run use: python manage.py reset_sequences
import psycopg2
from django.conf import settings
from django.core.management.base import BaseCommand
from django.db import connections
def dictfetchall(cursor):
"""Return all rows from a cursor as a dict"""
columns = [col[0] for col in cursor.description]
return [
dict(zip(columns, row))
for row in cursor.fetchall()
]
class Command(BaseCommand):
help = "Resets sequencing errors in Postgres which normally occur due to importing/restoring a DB"
def handle(self, *args, **options):
# loop over all databases in system to figure out the tables that need to be reset
for name_to_use_for_connection, connection_settings in settings.DATABASES.items():
db_name = connection_settings['NAME']
host = connection_settings['HOST']
user = connection_settings['USER']
port = connection_settings['PORT']
password = connection_settings['PASSWORD']
# connect to this specific DB
conn_str = f"host={host} port={port} user={user} password={password}"
conn = psycopg2.connect(conn_str)
conn.autocommit = True
select_all_table_statement = f"""SELECT *
FROM information_schema.tables
WHERE table_schema = 'public'
ORDER BY table_name;
"""
# just a visual representation of where we are
print('-' * 20, db_name)
try:
not_reset_tables = list()
# use the specific name for the DB
with connections[name_to_use_for_connection].cursor() as cursor:
# using the current db as the cursor connection
cursor.execute(select_all_table_statement)
rows = dictfetchall(cursor)
# will loop over table names in the connected DB
for row in rows:
find_pk_statement = f"""
SELECT k.COLUMN_NAME
FROM information_schema.table_constraints t
LEFT JOIN information_schema.key_column_usage k
USING(constraint_name,table_schema,table_name)
WHERE t.constraint_type='PRIMARY KEY'
AND t.table_name='{row['table_name']}';
"""
cursor.execute(find_pk_statement)
pk_column_names = dictfetchall(cursor)
for pk_dict in pk_column_names:
column_name = pk_dict['column_name']
# time to build the reset sequence command for each table
# taken from django: https://docs.djangoproject.com/en/3.0/ref/django-admin/#sqlsequencereset
# example: SELECT setval(pg_get_serial_sequence('"[TABLE]"','id'), coalesce(max("id"), 1), max("id") IS NOT null) FROM "[TABLE]";
try:
reset_statement = f"""SELECT setval(pg_get_serial_sequence('"{row['table_name']}"','{column_name}'),
coalesce(max("{column_name}"), 1), max("{column_name}") IS NOT null) FROM "{row['table_name']}" """
cursor.execute(reset_statement)
return_values = dictfetchall(cursor)
# will be 1 row
for value in return_values:
print(f"Sequence reset to {value['setval']} for {row['table_name']}")
except Exception as ex:
# will only fail if PK is not an integer...
# currently in my system this is from django.contrib.sessions
not_reset_tables.append(f"{row['table_name']} not reset")
except psycopg2.Error as ex:
raise SystemExit(f'Error: {ex}')
conn.close()
print('-' * 5, ' ALL ERRORS ', '-' * 5)
for item_statement in not_reset_tables:
# shows which tables produced errors, so far I have only
# seen this with PK's that are not integers because of the MAX() method
print(item_statement)
# just a visual representation of where we are
print('-' * 20, db_name)
You need to truncate the table.
See http://www.postgresql.org/docs/8.1/static/sql-truncate.html