SQLite3: Python Input to Table - Trouble with Auto Increment - python

I am currently having an issue with importing data to a sqlite3 table.
In my TEST program, users input their fake information when asked for an input.
I then take that input and put it in my Table, however, I am having an issue with the AutoIncrementing "User ID". Each user gets their own ID, and so far there are 5 users. When a new User inputs their data, how do I make it so it automatically sets "UserID" to the next number, in this case 6.
Everything works if I manually put "6" in the first Value (in the following code), but how do I make that automatic?
conn = sqlite3.connect('xxxxxxx.db')
c=conn.cursor()
NameCreate = input("Please enter your First and Last name: ")
UserNameCreate = input("Please enter your desired User Name: ")
PasswordCreate = input("Please enter your desired Password: ")
DOBCreate = input("Please enter your date of birth [DD.MM.YYYY]: ")
FavouriteArtistCreate = input("Please enter your favourite Arist: ")
FavouriteGenreCreate = input("Please enter your favourite Genre: ")
c.execute("INSERT INTO Users VALUES (AUTOINCREMENT, '{0}', '{1}', '{2}', '{3}', '{4}', '{5}')".format(NameCreate, DOBCreate, UserNameCreate, PasswordCreate, FavouriteArtistCreate, FavouriteGenreCreate))
conn.commit()

It's not enough to show your operations on the database. You need to show your database schema.
We start with two pieces of warning from sqlite doc:
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and disk I/O overhead and should be avoided if not strictly needed. It is usually not needed.
In SQLite, a column with type INTEGER PRIMARY KEY is an alias for the ROWID (except in WITHOUT ROWID tables) which is always a 64-bit signed integer.
With that out of the way, the problem with your code is that autoincrement is specified at table creation time, not insertion time.
See a minimal example:
import sqlite3
conn = sqlite3.connect(':memory:')
c = conn.cursor()
c.execute("CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)")
NameCreate = 'a'
c.execute("INSERT INTO users ('name') VALUES (?)", (NameCreate, ))
conn.commit()
print(c.execute('select * from users').fetchall())
NameCreate = 'b'
c.execute("INSERT INTO users ('name') VALUES (?)", (NameCreate, ))
conn.commit()
print(c.execute('select * from users').fetchall())
note the CREATE TABLE line with AUTOINCREMENT, although it's not necessary as sqlite3 will do AUTOINCREMENT on any INTEGER PRIMARY KEY.
So you will need to migrate your database to a new schema with that in your table.
A bad manual solution without migration can go as follows (only for stopgap!), in the above example:
c.execute("INSERT INTO users ('id', 'name') VALUES ((SELECT MAX(id) + 1 FROM users), ?)", (NameCreate, ))

Related

Update multiple columns: the Username disappears

I am trying to update my user detail with Python and SQLite.
The aim is to upgrade all the columns of my user in one go.
My code is:
def update():
new_username = input("Input your NEW username:\n")
new_firstname = input("Input your NEW firstname:\n")
new_lastname = input("Input your NEW lastname:\n")
new_email = input("Input your NEW email:\n")
new_password = input("Input your NEW password:\n")
update_customer =("""UPDATE customer SET username = ? AND firstname = ? AND lastname = ? AND email = ? AND password = ?""")
cursor.execute(update_customer, [(new_username), (new_firstname), (new_lastname), (new_email), (new_password)])
I inspected the database before and after running my python function. However, the changes are not saved into the database. Nothing changes but the username that disappears.
You don't use AND for additional columns to be SET. Instead you separate the columns to be SET with a comma.
So you want
update_customer =("""UPDATE customer SET username = ?, firstname = ?, lastname = ?, email = ?, password = ?""")
and then a WHERE clause if not setting all rows to the same values.
As per :-
SQL As Understood By SQLite - UPDATE
You need to save changes after you completed the transaction.
cursor = conn.cursor() # Get cursor
cursor.execute(...) # Execute some SQL queries
# This is the line you've missed.
# You need to call this function every time you update the data in database.
cursor.commit()
Also, your SQL syntax for the "UPDATE" command is not correct. Use commas instead of "AND" when specifying multiple columns to be changed. Like this:
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;

Iterate Over a list, deleting every value that matches a database

I have been working on this function in python. I intend for it to iterate over a list of phone numbers, checking with a database to see whether the number has been used yet or not. If it has been used, it should remove the phone number from the list and choose another and check the new one until an unused one has been found and return the unused one. If it has not been used, it should simply just return the number. However, after one run, it picks a number, checks it, runs, and then enters it into the database. The next run deletes the previously used number, and picks another that hasn't been used. It continues to run and enters this number into the database. The third run does not delete the previously used number from the list, but it still picks a new one regardless. Although this still works, when the numbers run out, since there are no others to pick, it continues using the last number in the list for every following run of the script. Sorry if the code is a bit sloppy right now, I am in a bit of a rush and this is only a script I have been messing around with. I hope this is clear, and not too confusing. If I need to clear any confusion, I will be glad too.
Edit: Sorry, I forgot to mention that these phone numbers are constantly grabbed from a website by another script. These set of numbers listed below is just a dummy set for testing. So in the end, I am needing to see if these recently grabbed numbers have been used by checking with the database tables.
import random
import names
##############################Information Variables##################################
emailAddress = "Fakeemail#mail.com"
titleValues = [0,1] #0 is 'Mr.', 1 is 'Mrs.'
country = 'Schwifty'
title = random.choice(titleValues)
#Generate a random name based on gender
if title == 1:
firstName = names.get_first_name(gender= 'female')
else:
firstName = names.get_first_name(gender= 'male')
lastName = names.get_last_name()
fullName = firstName + ' ' + lastName
print(fullName)
phoneNumber = '111-222-3333'
#########################################################
import sqlite3
import time
import datetime
conn = sqlite3.connect('accounts.db')
c = conn.cursor()
def createTable():
c.execute('CREATE TABLE IF NOT EXISTS accounts(Email TEXT, Name TEXT, Title TEXT, PhoneNumber TEXT, Country TEXT, DateStamp TEXT)')
def dynamic_data_entry(email, name, title, phone, country):
unix = time.time()
date = str(datetime.datetime.fromtimestamp (unix).strftime('%Y-%m-%d %H:%M:%S'))
c.execute('INSERT INTO accounts (Email, Name, Title, PhoneNumber, Country, DateStamp) VALUES (?, ?, ?, ?, ?, ?)', (email, name, title, phone, country, date))
conn.commit()
createTable()
#################################TEST NUMBER CHECK###########################
phoneNumbers = ['111-222-3333', '444-555-6666', '777-888-9999', '123-456-7890', '321-321-321']
def checkNumber(a):
c.execute("SELECT * FROM accounts WHERE PhoneNumber = ?", (a,))
row = c.fetchall()
if row:
print("Phone number has already been used, choosing another and deleting current from list.")
phoneNumbers.remove(a)
a = random.choice(phoneNumbers)
checkNumber(a)
elif row == False:
print("Number is fresh and new, using " + a)
return a
elif row == None:
print('No new phone numbers to use, exiting... ')
exit()
# for num in phoneNumbers:
# checkNumber(num)
# print(num)
checkNumber(phoneNumber)
print(phoneNumbers)
print('working')
##########################################
# INSERT DATA TO DB #
##########################################
#Insert information to database in this order: email, name, title, phone, country
dynamic_data_entry(emailAddress, fullName, title, phoneNumber, country)
conn.commit()
c.close()
conn.close()
Don’t do this. Populate a table with your phone numbers and update each phone number record with a field like ‘used’ once used.
Always keep state and data modeling in the database where possible. It is made for it.
Update in response to OP:
Create a separate table for phone numbers and replace your number field in the accounts table with a foreign key id to the primary key of the phone number table. This is called maintaining an object model or data model, so that if you want to query accounts, you have the data you need via foreign key, and if you just want phone numbers you can query the phone numbers table directly.
This way your phone number ‘objects’ can have their own attributes like ‘already called’ or ‘on do not call list’ without muddying up your accounts ‘object’.
If you want to insert a new account, you should first insert your new phone number 'object' into the phone number table and return the id, and then use that in your account insert.

How can I "get" the data from a sqlite3 database and store them as variables?

I am trying to query whether the staff ID and password are correct. The query works, however I want to get the fname and lname data from the database and print certain fields. It seems as though the row[fname] and row[lname] doesn't work... is there another way to do this? I keeps saying fname is not defined.
import sqlite3
connection = sqlite3.connect('shop.db')
cursor = connection.cursor()
create_table = '''
CREATE TABLE IF NOT EXISTS employee (
staff_ID INTEGER PRIMARY KEY,
password CHAR(4),
fname VARCHAR(20),
lname VARCHAR(30));'''
cursor.execute(create_table)
staffid = input('staff id: ')
password = input('password: ')
cursor.execute('SELECT * FROM employee WHERE staff_ID=? AND password=?', [staffid, password])
row = cursor.fetchone()
if row != None:
print(row[fname]+' '+row[lname])
You may insert any values into this table, I just didn't want the code to look too bulky... Thanks!

Sqlite 3 multiple foreign keys

I'm working on my A2 coursework and I've run into a problem with multiple foreign keys. Here is all code I think is relevant, if you need more please reply saying so.
In TeacherInfo:
def TMenu():
print()
MenuPupil = menuClass.Menu("Teacher")
MenuPupil.printMenu()
Choice = int(input("Enter your choice: "))
if Choice == 1:
db_name = "PupilPremiumTableNew.db"
sql= """Create table TeacherInfo
(TeacherID int,
TeacherInitials text,
TeacherYearTeaching int,
primary key(TeacherID))"""
CreateTeachersTable(db_name, "TeacherInfo",sql)
In PupilPremiumTableNew:
db_name = "PupilPremiumTableNew.db"
sql= """Create table PupilPremiumTableNew
(PupilID int,
WritingGrade text,
ReadingGrade text,
MathsGrade text,
Term text,
RecordID int,
InterventionsReading text,
InterventionsWriting text,
InterventionsMaths text,
primary key(RecordID),
foreign key(PupilID)
references PupilInfo(PupilID)
foreign key(TeacherID)
references TeacherInfo (TeacherID)
on update cascade on delete cascade)"""
CreatePupilPremiumTable(db_name, "PupilPremiumTableNew",sql)
def CreateTeachersTable(db_name,table_name,sql):
with sqlite3.connect(db_name) as db:
cursor = db.cursor()
cursor.execute("select name from sqlite_master where name =?",(table_name,))
result = cursor.fetchall()
keep_table = True
if len(result) == 1:
response = input("The table {0} already exists, do you wish to recreate it?(y/n): ".format(table_name))
if response == 'y':
keep_table = False
print("The table {0} has been recreated, all existing data has been deleted. ".format(table_name))
cursor.execute("drop table if exists {0}".format(table_name))
db.commit()
else:
print("Existing table was kept. ")
else:
keep_table = False
if not keep_table:
cursor.execute(sql)
db.commit()
The error I get says: sqlite3.OperationalError: unknown column "TeacherID" in foreign key definition
As you may notice a foreign key from another file, PupilTable is in there. At the moment that one works, if I remove TeacherID as a foreign key it all works
Thanks
Devilb77
I forgot to tell it what TeacherID was, so to fix the issue I added TeacherID int, into the variable sql
Here is what it now looks like:
db_name = "PupilPremiumTableNew.db"
sql= """Create table PupilPremiumTableNew
(PupilID int,
WritingGrade text,
ReadingGrade text,
MathsGrade text,
Term text,
RecordID int,
InterventionsReading text,
InterventionsWriting text,
InterventionsMaths text,
TeacherID int,
primary key(RecordID),
foreign key(PupilID)
references PupilInfo(PupilID)
foreign key(TeacherID)
references TeacherInfo (TeacherID)
on update cascade on delete cascade)"""
CreatePupilPremiumTable(db_name, "PupilPremiumTableNew",sql)

insert or replace statement not working with sqlite3 and python

Everytime I run this through the python interpreter it writes new values. for example:
name = ben
age = 10
phone = 42045042
If I run it 10 times. I get 10 duplicates in my database. I know it has to be an easy fix, but I've been working on this for hours and can't figure it out.
conn = sqlite3.connect('addressbook.db')
cur=conn.cursor()
conn.execute('''
CREATE TABLE IF NOT EXISTS people(name TEXT,
age TEXT, phone TEXT, fblink TEXT)''')
conn.execute("INSERT OR REPLACE INTO people values (?, ?, ?, ?)", ben.displayPerson())
cursor = conn.execute("SELECT name, age, phone, fblink from people")
for row in cursor:
print "NAME = ", row[0]
print "AGE = ", row[1]
print "PHONE = ", row[2]
print "FACEBOOK LINK = ", row[3], "\n"
cur.close()
conn.commit()
conn.close()
There's no primary key field.
Make a primary key field.
For example:
conn.execute('''
CREATE TABLE IF NOT EXISTS people(name TEXT primary key,
age TEXT, phone TEXT, fblink TEXT)''')
REPLACE is executed when UNIQUE constraint violation occurs. Without primary key (or unique ..), it does not happen.
Your table has no primary key, and hence SQLite doesn't know what it should "OR REPLACE" since it has nothing to base replacing on. Add a primary key.

Categories

Resources