syntax of sql-statements in python - python

I got this code to save some values in a Sql-DB via python. But it doesn't work. Could you please help me to find the problem?
def saveValue(art, value, timestamp):
# Missing: Check if table setting exists or create it
# First check if row exists
cursor.execute('SELECT count(*) FROM setting WHERE parameter=%s', art)
existing = cursor.fetchone()
if existing[0]==0:
cursor.execute('INSERT INTO setting (parameter, wert) VALUES (%s, NULL)', art)
db.commit()
# Update row
cursor.execute('UPDATE setting set value=%s WHERE parameter=%s', value, art)
db.commit()
# Check if measure-table exisits or create ist
cursor.execute('SHOW TABLES LIKE measure_%s', art)
result = cursor.fetchone()
if not result:
cursor.execute('CREATE TABLE measure_%s (id INT NOT NULL AUTO_INCREMENT, time int(11), value float(6), PRIMARY KEY (id))', art)
db.commit()
# Insert measure value
sql = 'INSERT INTO measure_%s (time, value) VALUES (%s, %s)'
args= art, timestamp, value
cursor.execute(sql,args)
db.commit()
Maybe it is even possible to optimize/minimize the code?

Related

PostgreSQL INSERT ON CONFLICT and TKinter

I have problem with syntax within python/Tkinter when updating PostgreSQL table.
Syntax works for function code below without ON CONFLICT option:
def myclick_start():
# Create a database or connect to one
conn = psycopg2.connect(database="*",# hidden credentials here
host="*",
user="*",
password="*",
port="*")
# Create cursor
c = conn.cursor()
# Insert Into Database Table
thing1 = o_num.get()
thing2 = op_id.get()
thing3 = proc_name_cb.get()
# this works
c.execute('''INSERT INTO orders (order_id, op_id, status_id) VALUES (%s, %s, %s)''',
(thing1, thing2, thing3)
)
# Commit Changes
conn.commit()
# Close Connection
conn.close()
but not working when I want to UPDATE table ON CONFLICT of order_id value:
# but this is not working
c.execute('''INSERT INTO orders (order_id, op_id, status_id) VALUES (%s, %s, %s)''',
(thing1, thing2, thing3),
ON CONFLICT (order_id)
DO UPDATE SET op_id = EXCLUDED.op_id, status_id = EXCLUDED.status_id;
)
Resulted error:
File "E:\***.py", line 229
'''c.execute('''INSERT INTO orders (order_id, op_id, status_id) VALUES (%s, %s, %s)''',
^^^^^^
SyntaxError: invalid syntax
I've tried many syntax variants and kind of stuck with my error.
Appreciate your help.
If you take a closer look at the syntax highlight, you will notice that your ON CONFLICT ... isn't part of the SQL query (i.e. it's not part of the string that makes up the query).
Moving that part inside the string should solve the problem, like this
c.execute('''INSERT INTO orders (order_id, op_id, status_id) VALUES (%s, %s, %s)
ON CONFLICT (order_id)
DO UPDATE SET op_id = EXCLUDED.op_id, status_id = EXCLUDED.status_id;''',
(thing1, thing2, thing3)
)

Prevent to insert duplicates into table (python , sql)

I stepped over an problem while implementing a Database into my Python project.
I'm creating a new Table with the following Code:
mycursor = mydb.cursor()
sql = f"CREATE TABLE IF NOT EXISTS _{self.client_id} (tour_date DATE, tour_distance INT, tour_duration INT, tour_elevation_up INT, tour_elevation_down INT, tour_map_image TEXT, tour_name TEXT, tour_sport TEXT, tour_start_point TEXT, tour_type TEXT)"
mycursor.execute(sql)
mydb.commit()
I'm iterating over my Data and want to past it into the Table. But I won't want that if an entry already exists in the table it adds the same data again.
This is my code I currently have to Insert into my Table:
mycursor = mydb.cursor()
sql = f"INSERT INTO _{self.client_id} (tour_date, tour_distance, tour_duration, tour_elevation_up, tour_elevation_down, tour_map_image, tour_name, tour_sport, tour_start_point, tour_type) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) "
val = (TourDate, TourDistance, TourDuration, TourElevation_up, TourElevation_down, TourMap_image, TourName, TourSport, TourStart_point, TourType)
mycursor.execute(sql, val)
mydb.commit()
So my question is how can I check if a entry already exists in the Table and then avoiding creating a duplicate?
you can "select count() from your_table_name where client_id='current_id'
if count() return int that is greater than 0, you should not insert it into the databse.
First - avoid to use TEXT without it necessary
Second - create table with necessary indexes:
CREATE TABLE IF NOT EXISTS _{self.client_id} (
tour_date DATE,
tour_distance INT,
tour_duration INT,
tour_elevation_up INT,
tour_elevation_down INT,
tour_map_image TEXT,
tour_name VARCHAR(64) PRIMARY KEY,
tour_sport VARCHAR(64),
tour_start_point VARCHAR(64),
tour_type VARCHAR(64)
);
Third - use INSERT IGNORE ... statement for prevent duplicates

MySQL (python 3.6) - SELECT * FROM table - returns number of rows instead of table

I am working with MySQL but I have some unexpected behaviour.
I have past experience with SQLite but I guess I am missing something here.
Using the query SELECT * FROM tableName I would expect the content of the table to be the output.
Instead I get an int, being the count of rows in the table.
Here is the piece of code I am using.
import MySQLdb
conn=MySQLdb.connect(host="xxx",user="xxx",passwd="xxx")
cursor = conn.cursor()
cursor.execute("create database if not exists Test;")
cursor.execute("use Test;")
cursor.execute("create table if not exists City (id int not null primary key auto_increment, city varchar(50), unique(city));")
cursor.execute("insert into City (city) values ('Firenze');")
cursor.execute("insert into City (city) values ('Roma');")
conn.commit()
print(cursor.execute("select city from City;"))
I would expect to get:
Firenze
Roma
Instead I get:
2
If I run the same query from a SQL client I get the expected output. Any clever idea?
Thanks :)
You are missing the FetchAll() function in your code.
Fetch all is nothing but fetching the data of last executed statement.
import MySQLdb
conn=MySQLdb.connect(host="xxx",user="xxx",passwd="xxx")
cursor = conn.cursor()
cursor.execute("create database if not exists Test;")
cursor.execute("use Test;")
cursor.execute("create table if not exists City (id int not null primary key
auto_increment, city varchar(50), unique(city));")
cursor.execute("insert into City (city) values ('Firenze');")
cursor.execute("insert into City (city) values ('Roma');")
conn.commit()
print(cursor.execute("select city from City;"))
myresult = mycursor.fetchall()
for x in myresult:
print(x)
The thing is print(cursor.execute("select city from City;") returns you the number of rows or rows count.
For the complete records use something like this
myresult = cursor.fetchall()
for x in myresult:
print(x)

Access to a record just inserted [duplicate]

How to retrieve inserted id after inserting row in SQLite using Python? I have table like this:
id INT AUTOINCREMENT PRIMARY KEY,
username VARCHAR(50),
password VARCHAR(50)
I insert a new row with example data username="test" and password="test". How do I retrieve the generated id in a transaction safe way? This is for a website solution, where two people may be inserting data at the same time. I know I can get the last read row, but I don't think that is transaction safe. Can somebody give me some advice?
You could use cursor.lastrowid (see "Optional DB API Extensions"):
connection=sqlite3.connect(':memory:')
cursor=connection.cursor()
cursor.execute('''CREATE TABLE foo (id integer primary key autoincrement ,
username varchar(50),
password varchar(50))''')
cursor.execute('INSERT INTO foo (username,password) VALUES (?,?)',
('test','test'))
print(cursor.lastrowid)
# 1
If two people are inserting at the same time, as long as they are using different cursors, cursor.lastrowid will return the id for the last row that cursor inserted:
cursor.execute('INSERT INTO foo (username,password) VALUES (?,?)',
('blah','blah'))
cursor2=connection.cursor()
cursor2.execute('INSERT INTO foo (username,password) VALUES (?,?)',
('blah','blah'))
print(cursor2.lastrowid)
# 3
print(cursor.lastrowid)
# 2
cursor.execute('INSERT INTO foo (id,username,password) VALUES (?,?,?)',
(100,'blah','blah'))
print(cursor.lastrowid)
# 100
Note that lastrowid returns None when you insert more than one row at a time with executemany:
cursor.executemany('INSERT INTO foo (username,password) VALUES (?,?)',
(('baz','bar'),('bing','bop')))
print(cursor.lastrowid)
# None
All credits to #Martijn Pieters in the comments:
You can use the function last_insert_rowid():
The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. The last_insert_rowid() SQL function is a wrapper around the sqlite3_last_insert_rowid() C/C++ interface function.
SQLite 3.35's RETURNING clause:
CREATE TABLE users (
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT
);
INSERT INTO users (first_name, last_name)
VALUES ('Jane', 'Doe')
RETURNING id;
returns requested columns of the inserted row in INSERT, UPDATE and DELETE statements. Python usage:
cursor.execute('INSERT INTO users (first_name, last_name) VALUES (?,?)'
' RETURNING id',
('Jane', 'Doe'))
row = cursor.fetchone()
(inserted_id, ) = row if row else None

lastrowid returning None in sqlite3 in python 3

I'm having a bit of trouble trying to fix a problem I'm having in retrieving the last insert id from a query in SQLite3 using Python.
Here's a sample of my code:
import sqlite3
# Setup our SQLite Database
conn = sqlite3.connect('value_serve.db')
conn.execute("PRAGMA foreign_keys = 1") # Enable Foreign Keys
cursor = conn.cursor()
# Create table for Categories
conn.executescript('DROP TABLE IF EXISTS Category;')
conn.execute('''CREATE TABLE Category (
id INTEGER PRIMARY KEY AUTOINCREMENT,
category CHAR(132),
description TEXT,
parent_id INT,
FOREIGN KEY (parent_id) REFERENCES Category (id)
);''')
conn.execute("INSERT INTO Category (category, parent_id) VALUES ('Food', NULL)")
food_category = cursor.lastrowid
conn.execute("INSERT INTO Category (category, parent_id) VALUES ('Beverage', NULL)")
beverage_category = cursor.lastrowid
...
conn.commit() # Commit to Database
No matter what I do, when I try to get the value of 'food_category' I get a return value of 'None'.
Any help would be appreciated, thanks in advance.
The lastrowid value is set per cursor, and only visible to that cursor.
You need to execute your query on the cursor that executed the query to get the last row id. You are asking an arbitrary cursor, one that never actually is used to execute the query for a last row id, but that cursor can't know that value.
If you actually execute the query on the cursor object, it works:
cursor.execute("INSERT INTO Category (category, parent_id) VALUES ('Food', NULL)")
food_category = cursor.lastrowid
The connection.execute() function creates a new (local) cursor for that query and the last row id is only visible on that local cursor. That cursor is returned when you use connection.execute(), so you could get the same value from that return value:
cursor_used = conn.execute("INSERT INTO Category (category, parent_id) VALUES ('Food', NULL)")
food_category = cursor_used.lastrowid

Categories