I have 3 MariaDB-SQL tables and I want to insert some data:
Restaurant
ID_Restaurant (Primary Key, Auto Increment)
RestaurantName
Location
Restaurant_has_Request
ID_Restaurant(Foreign Key)
ID_Request (Foreign Key)
Request
ID_Request (Primary Key, Auto Increment)
Date
Adults
One Restaurant has 0 or infinity Requests. One Request can have 1 or infinity Restaurants.
I am iterating through a request site for only one Request. That means I want to treat first one Request and then I save the related one or more Restaurants. After I have done this another Request will be treated and so on.
I have the following Python Code for inserting the data:
cursor.execute('insert into Restaurant(RestaurantName, Location) values(%s, %s)',(RestaurantName, Location))
# ID from last insert
ID_Restaurant_Cache = cursor.lastrowid
cursor.execute('insert into Request(Date, Adults) values(%s, %s)',(Date, Adults))
# ID from last insert
ID_Request_Cache = cursor.lastrowid
cursor.execute('insert into Restaurant_has_Request(ID_Restaurant, ID_Request) values(%s, %s)',(ID_Restaurant_Cache, ID_Request_Cache))
The problem is that I have still duplicates... How can I modify the Python code that I use the existing entry from a Restaurant, when it already exists (RestaurantName & Location is already in the database)?
I have also duplicates for the Request. I want to use the same Request ID for one iteration and then I want to use another Request ID.
Thank you :)
You need to check whether the restaurant already exists before inserting.
cursor.execute('select ID_Restaurant from Restaurant where RestaurantName = %s', (RestaurantName,))
row = cursor.fetchone()
if row:
ID_Restaurant_Cache = row[0]
else:
cursor.execute('insert into Restaurant(RestaurantName, Location) values(%s, %s)',(RestaurantName, Location))
ID_Restaurant_Cache = cursor.lastrowid
You should also add a unique index on the RestaurantName column, to prevent duplicates.
Please provide SHOW CREATE TABLE.
Shouldn't Restaurant_has_Request have
PRIMARY KEY(ID_restaurant, ID_request),
INDEX(ID_request, ID_restaurant)
Related
I am creating a program to practice MySQL where there is a table called inventory and the user adds to the table
item_code item_name price quantity
a000 a 100 100
I want to make it so that if the user inputs a000 then he gets a message of the item_code already being in the table
is there any way to do this
You can specify a UNIQUE index on the item_code field.
CREATE UNIQUE INDEX item_code_unique
ON inventory(item_code);
You can then use a try-catch block to catch any error from inserting duplicates.
try:
cursor.execute("INSERT INTO ....")
except MySQLdb.IntegrityError:
print("Duplicate entry")
See also: How to avoid duplicate entries in a MySQL database without throwing an error
Using MySQL UNIQUE Index To Prevent Duplicates
Try this:
import sqlite3
conn = sqlite3.connect("NameOfYourDatabase.db")
cur = conn.cursor()
cur.execute("""CREATE TABLE IF NOT EXISTS inventory (
item_code text UNIQUE,
item_name text,
price INT,
quantity INT
)"""
try:
#INSERT whatever you want into the db here
except sqlite3.IntegrityError:
print("Item code already exists")
You can also make your item_code a PRIMARY KEY as a PRIMARY KEY is automatically set as UNIQUE
REMEMBER: You can have only one PRIMARY KEY per table.
If your table is already created:
ALTER TABLE inventory
MODIFY item_code text NOT NULL UNIQUE;
With PRIMARY KEY:
ALTER TABLE inventory
ADD PRIMARY KEY (item_code);
Learn more in this website:
https://www.w3schools.com/sql/sql_unique.asp
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
I am using sqlite, and I have a Python code as follows:
...
cur.execute("insert or ignore into books (title, authors, ...) \
values (:title, :authors, ..."), locals())
...
bookId = cur.lastrowid
If the ignore part of the select statement applies
then the value of cur.lastrowid is 0.
But this is not what I want. I'd like to get books.id value from the database
in any case.
Should I use select statement or is there smarter way to achieve it?
My temporary solution:
if bookId == 0:
cur.execute("select id from books where \
title = :title and authors = :authors", locals())
bookId = cur.fetchone()[0]
There is no better way.
To read some existing value from the database, there's only SELECT.
Try using on duplicate key update id=LAST_INSERT_ID(id) for the PK. Seems like lastrowID will be correct from then on out.
link_title = []
comments = []
username = request.form['user']
user = requests.get('http://www.reddit.com/user/{username}/comments.json?'.format(username=username))
j = json.loads(user.content)
for i in j['data']['children']:
link_title.append(i['data']['link_title'])
for i in j['data']['children']:
comments.append(i['data']['body'])
g.db.execute("UPDATE comments SET (user,title,comments) VALUES (?,?,?)", (request.form['user'], link_title, comments))
basically there is a form on my app, you enter a user, it runs this code I just showed. This will grab the comments/title/body from a user. I want to add the comments into 1 column, as a whole list, so that each time someone uses the form the comments will be erased. When I run this code, it says error at ( syntax, and points to my g.d.execute line. Am I approaching this wrong? how do I add the list to 1 column 1 row
EDIT:
cur.execute('PRAGMA foreign_keys = ON')
cur.execute('CREATE TABLE user(user_id integer primary key, username text)')
cur.execute('CREATE TABLE comments(comment_id integer primary key, title text, comments text, user_id, \
FOREIGN KEY(user_id) REFERENCES user(user_id))')
when I insert into or delete anything in either user/comments table, I can see no constraints in place. I can add a user_id into the comments table even if no user exists. Is my code/logic incorrect?
I am using SQLAlchemy without the ORM, i.e. using hand-crafted SQL statements to directly interact with the backend database. I am using PG as my backend database (psycopg2 as DB driver) in this instance - I don't know if that affects the answer.
I have statements like this,for brevity, assume that conn is a valid connection to the database:
conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
Assume also that the user table consists of the columns (id [SERIAL PRIMARY KEY], name, country_id)
How may I obtain the id of the new user, ideally, without hitting the database again?
You might be able to use the RETURNING clause of the INSERT statement like this:
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
RETURNING *")
If you only want the resulting id:
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
RETURNING id")
[new_id] = result.fetchone()
User lastrowid
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
result.lastrowid
Current SQLAlchemy documentation suggests
result.inserted_primary_key should work!
Python + SQLAlchemy
after commit, you get the primary_key column id (autoincremeted) updated in your object.
db.session.add(new_usr)
db.session.commit() #will insert the new_usr data into database AND retrieve id
idd = new_usr.usrID # usrID is the autoincremented primary_key column.
return jsonify(idd),201 #usrID = 12, correct id from table User in Database.
this question has been asked many times on stackoverflow and no answer I have seen is comprehensive. Googling 'sqlalchemy insert get id of new row' brings up a lot of them.
There are three levels to SQLAlchemy.
Top: the ORM.
Middle: Database abstraction (DBA) with Table classes etc.
Bottom: SQL using the text function.
To an OO programmer the ORM level looks natural, but to a database programmer it looks ugly and the ORM gets in the way. The DBA layer is an OK compromise. The SQL layer looks natural to database programmers and would look alien to an OO-only programmer.
Each level has it own syntax, similar but different enough to be frustrating. On top of this there is almost too much documentation online, very hard to find the answer.
I will describe how to get the inserted id AT THE SQL LAYER for the RDBMS I use.
Table: User(user_id integer primary autoincrement key, user_name string)
conn: Is a Connection obtained within SQLAlchemy to the DBMS you are using.
SQLite
======
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm) ''' )
# Execute within a transaction (optional)
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.lastrowid
txn.commit()
MS SQL Server
=============
insstmt = text(
'''INSERT INTO user (user_name)
OUTPUT inserted.record_id
VALUES (:usernm) ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.fetchone()[0]
txn.commit()
MariaDB/MySQL
=============
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm) ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = conn.execute(text('SELECT LAST_INSERT_ID()')).fetchone()[0]
txn.commit()
Postgres
========
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm)
RETURNING user_id ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.fetchone()[0]
txn.commit()
result.inserted_primary_key
Worked for me. The only thing to note is that this returns a list that contains that last_insert_id.
Make sure you use fetchrow/fetch to receive the returning object
insert_stmt = user.insert().values(name="homer", country_id="123").returning(user.c.id)
row_id = await conn.fetchrow(insert_stmt)
For Postgress inserts from python code is simple to use "RETURNING" keyword with the "col_id" (name of the column which you want to get the last inserted row id) in insert statement at end
syntax -
from sqlalchemy import create_engine
conn_string = "postgresql://USERNAME:PSWD#HOSTNAME/DATABASE_NAME"
db = create_engine(conn_string)
conn = db.connect()
INSERT INTO emp_table (col_id, Name ,Age)
VALUES(3,'xyz',30) RETURNING col_id;
or
(if col_id column is auto increment)
insert_sql = (INSERT INTO emp_table (Name ,Age)
VALUES('xyz',30) RETURNING col_id;)
result = conn.execute(insert_sql)
[last_row_id] = result.fetchone()
print(last_row_id)
#output = 3
ex -