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
Related
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)
Deleting from a table in SQLite with foreign keys enabled seems very slow. Is there anything that can be done to improve the performance (without disabling the foreign keys)?
import time
import sqlite3
def fk_check(state):
conn = sqlite3.connect(":memory:")
c = conn.cursor()
c.execute("CREATE TABLE parent (id integer primary key, name)")
c.execute("CREATE TABLE child (id integer primary key, parent_id references parent)")
c.execute("CREATE INDEX parentindex ON child(parent_id);")
c.execute(f"pragma foreign_keys={state};")
for i in range(10000):
c.execute("insert into parent (name) values (?);", ('name'+str(i),))
for i in range(5000, 10000):
c.execute("insert into child (parent_id) values (?);", (i,))
start = time.time()
c.execute("delete from parent where id < 5000")
took = time.time()-start
print(f'fk-{state}: {took}')
fk_check('on')
fk_check('off')
fk_check('on')
fk_check('off')
Has the following output:
fk-on: 0.8750052452087402
fk-off: 0.0007216930389404297
fk-on: 0.8769822120666504
fk-off: 0.0007178783416748047
From the docs:
each time an application deletes a row from the parent table, it performs the equivalent of the following SELECT statement to search for referencing rows in the child table:
SELECT rowid FROM <child-table> WHERE <child-key> = :parent_key_value
If this SELECT returns any rows at all, then SQLite concludes that deleting the row from the parent table would violate the foreign key constraint and returns an error. Similar queries may be run if the content of the parent key is modified or a new row is inserted into the parent table.
With FKs on, it's doing extra work on each delete. I don't think you can avoid this while still retaining the foreign key constraint.
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 able to get my Python code to run print the desired results, but my problem is with the SQLite table. I was asked to apply this SQL command to the tables:
SELECT hex(User.name || Course.title || Member.role ) AS X
FROM User JOIN Member JOIN Course
ON User.id = Member.user_id AND Member.course_id = Course.id
ORDER BY X
I was able to execute the command in SQLite, but according to the instructions for this project, X is supposed to start with 416 in row one of the results column produced. However, the X I got for row 1 in the results was:
43616C6962736933313030
Here is what I wrote in Python so far:
import sqlite3
import json
#Working with Java and Sqlite
conn = sqlite3.connect('rosterdb.sqlite')
cur = conn.cursor()
cur.executescript('''
DROP TABLE IF EXISTS User;
DROP TABLE IF EXISTS Member;
DROP TABLE IF EXISTS Course;
CREATE TABLE User(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT UNIQUE
);
CREATE TABLE Member(
user_id INTEGER UNIQUE,
course_id INTEGER UNIQUE,
role INTEGER,
PRIMARY KEY (user_id, course_id)
);
CREATE TABLE Course(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
title TEXT UNIQUE
);
''')
#primary key for junction table is composite of both user_id and course_id
fname = raw_input("Enter file name:")
if (len(fname) < 1): fname = 'roster_data.json'
#prompts for file name
str_data = open(fname).read()
json_data = json.loads(str_data)
#opens the file and reads it all
#loads the json data and now is a python list
for entry in json_data:
title = entry[1];
name = entry [0];
role = entry[2];
#["Charley, "sill0", 1] represents the name, course title, and role
print name, title, role
cur.execute('''INSERT or IGNORE INTO User (name)
VALUES (?)''', (name, ))
cur.execute('SELECT id FROM User WHERE name = ?',(name, ))
user_id = cur.fetchone()[0]
cur.execute('''INSERT or IGNORE INTO Course (title)
VALUES (?)''', (title, ))
cur.execute('SELECT id FROM Course WHERE title = ?', (title, ))
course_id = cur.fetchone()[0]
cur.execute('''INSERT or REPLACE INTO Member (user_id, course_id, role)
VALUES (?,?,?)''', (user_id, course_id, role))
#INSERT, SELECT AND FETCHONE STATEMENTS
conn.commit()
Here is the JSON data that I was working with. It is about course registration for students: roster_data.json Here is the link to it:
https://pr4e.dr-chuck.com/tsugi/mod/sql-intro/roster_data.php?PHPSESSID=9addd537cfe55c03585d2bfaa757f6b0
I am not sure if I implemented the "role" key correctly. Thank you for your inputs!
The problem is that you made Member.course_id unique. Thus you can have no more members than courses. Using REPLACE in INSERT or REPLACE into Member hides this error.
Just drop UNIQUE constraint on Member.course and you will get expected result.
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?