Is commit used on the connect or cursor? - python

The book named "Practical Programming: 2nd Edition" has conflicting code. This is the start of my code:
import sqlite3
con = sqlite3.connect('stackoverflow.db')
cur = conn.cursor()
To commit, would I use con.commit(), cur.commit() or are there different times to use each? From the book:
con.commit() :
cur.commit() :
Documentation shows con.commit() :

I took unutbu's advice and tried it myself.
Sample code:
import sqlite3
con = sqlite3.connect('db.db')
cur = con.cursor()
data = [('data', 3), ('data2', 69)]
cur.execute('CREATE TABLE Density(Name TEXT, Number INTEGER)')
for i in data:
cur.execute('INSERT INTO Density VALUES (?, ?)', (i[0], i[1]))
cur.commit()
PyCharm Run:
Traceback (most recent call last):
File "/Users/User/Library/Preferences/PyCharmCE2018.1/scratches/scratch_2.py", line 13, in <module>
cur.commit()
AttributeError: 'sqlite3.Cursor' object has no attribute 'commit'
Error in textbook. cur.commit() does not exist.
Thanks unutbu and s3n0

con.commit() and conn.commit() are the same ... they are created object types ... in both cases they are otherwise named ... important is mainly .commit() and not the naming that the programmer has specified
There are object types that use a different name (con and cur - as you asked) to calling the method. You can also use a different name in your code, for example:
db = sqlite3.connect('/tmp/filename.db')
cursor = db.cursor()
cursor.execute("CREATE TABLE ....
.... some DB-API 2.0 commands ....
")
db.commit()
Please check again the webpage https://docs.python.org/3/library/sqlite3.html .
You forgot to copy these two lines from the webpage:
import sqlite3
conn = sqlite3.connect('example.db')
And then continuing the code (just copied it):
c = conn.cursor()
# Create table
c.execute('''CREATE TABLE stocks
(date text, trans text, symbol text, qty real, price real)''')
# Insert a row of data
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
# Save (commit) the changes
conn.commit()
# We can also close the connection if we are done with it.
# Just be sure any changes have been committed or they will be lost.
conn.close()

I think if you're using a specified cursor to commit changes, in your case, it should be cur.connection.commit().
You can always use connect to commit in the end of your code, whether it's named db, or con or conn.
But when your code gets complicated, you'll have different function to do certain operation to the database, if you only use connection commit, when there is a bug, you gonna have a hard time to find which function failed. So you create specific cursor for specific operation, when that failed, the traceback message will show you which specific cursor when wrong.

To #s3n0 & #DanielYu's point they can be handled two different ways. I had to list these out to better understand the overlap:
Connection Objects
backup
close
commit
create_aggregate
create_collation
create_function
cursor
enable_load_extension
execute
executemany
executescript
in_transaction
interrupt
isolation_level
iterdump
load_extension
rollback
row_factory
set_authorizer
set_progress_handler
set_trace_callback
text_factory
total_changes
Cursor objects
arraysize
close
connection
description
execute
executemany
executescript
fetchall
fetchmany
fetchone
lastrowid
rowcount
setinputsizes
setoutputsize

Related

Cannot operate on a closed cursor in sqlite3 python

I've been following this 5 part tutorial from this YouTube playlist: https://www.youtube.com/playlist?list=PLQVvvaa0QuDezJh0sC5CqXLKZTSKU1YNo
I'm using Jupyter notebook with Python with the following code:
import sqlite3
import time
import datetime
import random
conn = sqlite3.connect("tutorial2.db")
c = conn.cursor()
Then I create several functions.
def create_table():
c.execute('CREATE TABLE IF NOT EXISTS stuffToPlot (unix REAL, datestamp TEXT,
keyword TEXT, value REAL)')
def data_entry():
c.execute("INSERT INTO stuffToPlot VALUES (145123542, '2016-01-03',
'Python', 7)")
conn.commit()
c.close()
conn.close()
create_table()
data_entry()
It works fine the first time, and generates a db file in C:\Users\Michael
However, when I try to run only the create_table() function again, I get the following error:
ProgrammingError: Cannot operate on a closed cursor.
Anyone able to help resolving this issue would be greatly appreciated!
The error is pretty explicit: You cannot run queries on closed cursors. Here it's even worse since you have also closed the connection at the first call of the data_entry() function.
I would advise on opening a cursor for each query, and then closing it after completing the query, and only closing the connection at the end of your script:
import sqlite3
import time
import datetime
import random
conn = sqlite3.connect("tutorial2.db")
def create_table():
c = conn.cursor()
c.execute('CREATE TABLE IF NOT EXISTS stuffToPlot (unix REAL, datestamp TEXT, keyword TEXT, value REAL)')
c.close()
def data_entry():
c = conn.cursor()
c.execute("INSERT INTO stuffToPlot VALUES (145123542, '2016-01-03', 'Python', 7)")
conn.commit()
c.close()
create_table()
data_entry()
By moving the conn.close() statement after you have completed all of your queries, and opening the cursors only when you need them, the error won't occur anymore.
EDIT : What is happening in your video is the following:
He first executes the whole script once.
He comments the line that creates the table.
He executes the whole script a second time.
I think you are probably entering the commands in a python interactive session, which is not equivalent to what he is doing in the video, because when he re-executes the script, a new connection and cursor are created, whereas if you're only trying to call the function again, the cursor and connection are already closed, which causes the error.

Python and PostgreSQL - GeomFromText

I'm a Python learner,
I'm trying to insert geometry records into PostgreSQL.
If I tried the query without the geometry column, it works fine and all data inserted successfully.
cur.execute("INSERT INTO taxi (userid,carNum) SELECT '"+str(msg['UserID'])+"',"+str(msg['CarNumber']))
Once I try to add the geometry records, nothing happens! execution ends without errors but nothing being inserted into DB.
cur.execute("INSERT INTO taxi (position,userid,carNum) SELECT GeomFromText('POINT("+str(float(msg['longitude']))+" "+str(float(msg['latitude']))+")',4326),'"+str(msg['UserID'])+"',"+str(msg['CarNumber']))
Couldn't figure out what I'm missing here
You need to commit the data to the database.
Check the documentation of psycopg2 http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries
Follow those steps
>>> import psycopg2
# Connect to an existing database
>>> conn = psycopg2.connect("dbname=test user=postgres")
# Open a cursor to perform database operations
>>> cur = conn.cursor()
# Execute a command: this creates a new table
>>> cur.execute("CREATE TABLE test (id serial PRIMARY KEY, num integer, data varchar);")
# Pass data to fill a query placeholders and let Psycopg perform
# the correct conversion (no more SQL injections!)
>>> cur.execute("INSERT INTO test (num, data) VALUES (%s, %s)",
... (100, "abc'def"))
# Query the database and obtain data as Python objects
>>> cur.execute("SELECT * FROM test;")
>>> cur.fetchone()
(1, 100, "abc'def")
# Make the changes to the database persistent
>>> conn.commit()
# Close communication with the database
>>> cur.close()
>>> conn.close()

Python, Sqlite not saving results on the file

I have this code in Python:
conn = sqlite3.connect("people.db")
cursor = conn.cursor()
sql = 'create table if not exists people (id integer, name VARCHAR(255))'
cursor.execute(sql)
conn.commit()
sql = 'insert into people VALUES (3, "test")'
cursor.execute(sql)
conn.commit()
sql = 'insert into people VALUES (5, "test")'
cursor.execute(sql)
conn.commit()
print 'Printing all inserted'
cursor.execute("select * from people")
for row in cursor.fetchall():
print row
cursor.close()
conn.close()
But seems is never saving to the database, there is always the same elements on the db as if it was not saving anything.
On the other side If I try to access the db file via sqlite it I got this error:
Unable to open database "people.db": file is encrypted or is not a database
I found on some other answers to use conn.commit instead of conn.commit() but is not changing the results.
Any idea?
BINGO ! people! I Had the same problem. One of thr reasons where very simple. I`am using debian linux, error was
Unable to open database "people.db": file is encrypted or is not a database
database file was in the same dir than my python script
connect line was
conn = sqlite3.connect('./testcases.db')
I changed this
conn = sqlite3.connect('testcases.db')
! No dot and slash.
Error Fixed. All works
If someone think it is usefull, you`re welcome
This seems to work alright for me ("In database" increases on each run):
import random, sqlite3
conn = sqlite3.connect("people.db")
cursor = conn.cursor()
sql = 'create table if not exists people (id integer, name VARCHAR(255))'
cursor.execute(sql)
for x in xrange(5):
cursor.execute('insert into people VALUES (?, "test")', (random.randint(1, 10000),))
conn.commit()
cursor.execute("select count(*) from people")
print "In database:", cursor.fetchone()[0]
You should commit after making changes i.e:
myDatabase.commit()
can you open the db with a tool like sqlite administrator ? this would proove thedb-format is ok.
if i search for that error the solutions point to version issues between sqlite and the db-driver used. maybe you can chrck your versions or AKX could post the working combination.
regards,khz

Mysqldb Update error with set %s

I have created a database with MySQLdb.
In database I have a table with name student with columns:
id(is int),
id_user(is int),
f_name(is str),
l_name(is str)
I want to update a row.
My code is below:
db=mdb.connect(host="localhost", use_unicode="True", charset="utf8",
user="", passwd="", db="test")
# prepare a cursor object using cursor() method
cursor = db.cursor()
sql="""SELECT id_user FROM student"""
try:
# Execute the SQL command
cursor.execute(sql)
# Commit your changes in the database
db.commit()
except:
# Rollback in case there is any error
db.rollback()
rows = cursor.fetchall()
the=int(7)
se=str('ok')
for row in rows:
r=int(row[0])
if r==the:
sql2 = """UPDATE student
SET f_name=%s
WHERE id_user = %s"""% (se,the)
# Execute the SQL command
cursor.execute(sql2)
# Commit your changes in the database
db.commit()
db.rollback()
# disconnect from server
db.close()
When I run it I take the error there is column with name ok why?
Can anyone help me find what I am doing wrong please?
str doesn't wrap its argument in quotation marks, so your statement is this:
UPDATE student SET f_name=ok WHERE id_user = 7
when it needs to be this:
UPDATE student SET f_name='ok' WHERE id_user = 7
So, either change this line:
SET f_name=%s
to this:
SET f_name='%s'
or else change this line:
se=str('ok')
to this:
se="'" + str('ok') + "'"
Though I recommend reading about SQL injection, which will become a concern as soon as you start using user-supplied data instead of hard-coded values.
You should run the query like this:
sql2 = """UPDATE student
SET f_name = %s
WHERE id_user = %s"""
cursor.execute(sql2, (se, the))
Don't use string interpolation, let the database driver handle passing the parameters for you. Otherwise you have to deal with syntax errors like this, or worse, SQL injection.
More details here.
You should always enclose your data with quotes.
Instead of %s solely use '%s' the only types you dont need it are numeric ones, but even there i would enclose %d with '%d' cos it is more save.
And you should use at least db.escape_string(your_data) before inserting or updating same values into your database.
Or have a look at the pdo-using style of mysqldb:
http://mysql-python.sourceforge.net/MySQLdb.html#some-examples
c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < %s""", (max_price,))

pymysql callproc() appears to affect subsequent selects

I'm attempting to transition a code base from using MySQLdb to pymysql. I'm encountering the following problem and wonder if anyone has seen something similar.
In a nutshell, if I call a stored procedure through the pymysql cursor callproc() method a subsequent 'select' call through the execute() method using the same or a different cursor returns incorrect results. I see the same results for Python 2.7.2 and Python 3.2.2
Is the callproc() method locking up the server somehow? Code is shown below:
conn = pymysql.connect(host='localhost', user='me', passwd='pwd',db='mydb')
curr = conn.cursor()
rargs = curr.callproc("getInputVar", (args,))
resultSet = curr.fetchone()
print("Result set : {0}".format(resultSet))
# curr.close()
#
# curr = conn.cursor()
curr.execute('select * from my_table')
resultSet = curr.fetchall()
print("Result set len : {0}".format(len(resultSet)))
curr.close()
conn.close()
I can uncomment the close() and cursor creation calls above but this doesn't change the result. If I comment out the callproc() invocation the select statement works just fine.
I have a similar problem with (committed) INSERT statements not appearing in the database. PyMySQL 0.5 für Python 3.2 and MySQL Community Server 5.5.19.
I found the solution for me: instead of using the execute() method, I used the executemany method, explained in the module reference on
http://code.google.com/p/pymssql/wiki/PymssqlModuleReference
There is also a link to examples.
Update
A little later, today, I found out that this is not yet the full solution.
A too fast exit() at the end of the python script makes the data getting lost in the database.
So, I added a time.sleep() before closing the connection and before exit()ing the script, and finally all the data appeared!
(I also switched to using a myisam table)
import pymysql
conn = pymysql.connect(host='localhost', user='root', passwd='', db='mydb', charset='utf8')
conn.autocommit(True)
cur = conn.cursor()
# CREATE tables (SQL statements generated by MySQL workbench, and exported with Menu -> Database -> Forward Engineer)
cur.execute("""
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL';
DROP SCHEMA IF EXISTS `mydb` ;
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `mydb` ;
# […]
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
""")
# Fill lookup tables:
cur.executemany("insert into mydb.number(tagname,name,shortform) values (%s, %s, %s)", [('ЕД','singular','sg'), ('МН','plural','p')] )
cur.executemany("insert into mydb.person(tagname,name,shortform) values (%s, %s, %s)", [('1-Л','first','1st'), ('2-Л','second','2nd'), ('3-Л','third','3rd')] )
cur.executemany("insert into mydb.pos(tagname,name,shortform) values (%s, %s, %s)", [('S','noun','s'), ('A','adjective','a'), ('ADV','adverb','adv'), ('NUM','numeral','num'), ('PR','preposition','pr'), ('COM','composite','com'), ('CONJ','conjunction','conj'), ('PART','particle','part'), ('P','word-clause','p'), ('INTJ','interjection','intj'), ('NID','foreign-named-entity','nid'), ('V','verb','v')] )
#[…]
import time
time.sleep(3)
cur.close()
conn.close()
time.sleep(3)
exit()
I suggest the forum/group https://groups.google.com/forum/#!forum/pymysql-users for further discussion with the developer.

Categories

Resources