How do I create a foreign key in sqlite3 python - python

I can't get my program to use a foreign key for some unbeknown reason. I have read other questions related to this but cant find an answer that works. I tried the PRAGMA foreign_keys = ON, but instead i get a syntax error for "foreign_keys". I also tried removing this and running the program again and instead got an error saying the column I'm trying to create doesn't exist
import sqlite3
import os
import random
from tkinter import *
import uuid
PRAGMA foreign_keys = ON
conn = sqlite3.connect('MyComputerScience.db')
c = conn.cursor()
c.execute("""CREATE TABLE IF NOT EXISTS users (
UserID text PRIMARY KEY,
FName text,
SName text,
username text,
password varchar,
userType text)""")
c.execute("""CREATE TABLE IF NOT EXISTS classes (
ClassID PRIMARY KEY,
FOREIGN KEY (User) REFERENCES users(UserID)))""")
FOREIGN KEY (User) REFERENCES users(UserID)))""")
sqlite3.OperationalError: unknown column "User" in foreign key definition

You need to create the fields in the table before using them as a foreign key.
As you did not add a field User to your table, you got the error:
unknown column "User" in foreign key definition
To fix the error, add User to your table definition
c.execute("""CREATE TABLE IF NOT EXISTS classes (
ClassID PRIMARY KEY,
User text,
FOREIGN KEY (User) REFERENCES users(UserID)))""")
However, I would question the design. The table classes would only be able to relate one user per class. Is that what you want to do?

c.execute("""CREATE TABLE IF NOT EXISTS classes (
ClassID PRIMARY KEY,
FOREIGN KEY (ClassID) REFERENCES users(UserID)))""")
That's the correct syntax but this way you set as foreign key your primary key. Maybe you wanted to use another field.

Related

How to One to One relation sqlite3 python

This is the relation I want to create for my quiz app and im using python
Module:
c.execute("""CREATE TABLE Questions (
mod_id INTEGER PRIMARY KEY,
mod_name TEXT NOT NULL
)""")
Question:
c.execute("""CREATE TABLE Questions (
quest_id INTEGER PRIMARY KEY,
quest_name TEXT NOT NULL,
mod_id INTEGER NOT NULL,
FOREIGN KEY (mod_id)
REFERENCES Modules (mod_id)
)""")
Now Since the each feedback correspont to 1 question, how do i sort of create one to one relationship? should I do the same as I did for the question table? would this be handle automatically by sqlite3??
Appreciate all sort of help Thanks!!!
EDIT: Does my feedback table need to have a primary key?? I think no because when accesing the feeback table to delete or add data we just pass the question ID as the parameter to look that row up.

Syntax errors while trying to make a foreign key sqlit3 p

I am trying to create a foreign key to show which homework a student has been set. I have done what I believed to be the right syntax, however I keep getting syntax errors for other parts of the database. I'm not sure if this is because of the foreign key as it hasn't occured otherwise.
c.execute("""CREATE TABLE IF NOT EXISTS HomeworkInfo (
HWID INTEGER PRIMARY KEY AUTOINCREMENT,
HomeworkName text);""")
c.execute("""CREATE TABLE IF NOT EXISTS HomeworkSet (
HWID text,
FOREIGN KEY (HWID) REFERENCES HomeworkInfo(HWID),
FName text,
SName text,
Results text);""")
line 36, in <module>
Results text);""")
OperationalError: near "FName": syntax error
Move the definition of the foreign key at the end of the statement:
CREATE TABLE IF NOT EXISTS HomeworkSet (
HWID text,
FName text,
SName text,
Results text,
FOREIGN KEY (HWID) REFERENCES HomeworkInfo(HWID)
);
or define it like this:
CREATE TABLE IF NOT EXISTS HomeworkSet (
HWID text REFERENCES HomeworkInfo(HWID),
FName text,
SName text,
Results text
);
You can find more about the definition of the foreign keys here: SQLite Foreign Key Support
Just a guess but in your example it looks like HomeworkInfo.HWID is an integer but HomeworkSet.HWID is text. Shouldn't they be the same type?

Error: Duplicate foreign key constraint name

I exported a schema from workbench and now trying to use that script to create table in my server, But getting error
I tried to change the table and also tried to find duplicate foriegn key.
ERROR 1826: Duplicate foreign key constraint name 'bank_id'
SQL Statement:
-- Table aditya.users_has_bank
CREATE TABLE IF NOT EXISTS `aditya`.`users_has_bank` (
`users_user_id` INT NOT NULL AUTO_INCREMENT,
`bank_id` INT NOT NULL,
`user_id` INT NOT NULL,
PRIMARY KEY (`users_user_id`),
INDEX `bank_id_idx` (`bank_id` ASC) VISIBLE,
INDEX `user_id_idx` (`user_id` ASC) VISIBLE,
CONSTRAINT `bank_id`
FOREIGN KEY (`bank_id`)
REFERENCES `aditya`.`bank` (`bank_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `user_id`
FOREIGN KEY (`user_id`)
REFERENCES `aditya`.`users` (`user_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
High possibility that FK name is used in other tables within your schema. Please do practice good FK naming convention
Source: Foreign Key naming scheme

SQL for creating tables in a database using Python sqlite3

I am trying to create a number of tables with different names (of course) but sharing the same schema. For this purpose, I am using executemany on a Cursor object as follows:
tables = ['Meanings', 'Synonyms', 'Antonyms', 'Examples', 'Phrases',
'Pronunciations', 'Hyphenations']
create_table_query = '''CREATE TABLE (?) (
id INTEGER NOT NULL,
text TEXT,
word_id INTEGER NOT NULL,
PRIMARY KEY id,
FOREIGN KEY(word_id) REFERENCES Word(id)
)'''
cursor.executemany(create_table_query, tables)
When I execute this snippet, I get the following error message:
OperationalError: near "(": syntax error
I am having trouble fixing the bug here with my SQL since I find the error message to be not descriptive enough. I have tried the following queries but I am unable to develop the understanding of their success and my query's failure:
create_table_query_1 = '''CREATE TABLE {} (
id INTEGER NOT NULL,
text TEXT,
word_id INTEGER NOT NULL,
PRIMARY KEY id,
FOREIGN KEY(word_id) REFERENCES Word(id)
)''' # Syntax error near "id"
create_table_query_2 = '''CREATE TABLE (?) (
id INTEGER PRIMARY KEY,
text TEXT,
word_id INTEGER NOT NULL,
FOREIGN KEY(word_id) REFERENCES Word(id)
)''' # Syntax error near "("
create_table_query_1 = '''CREATE TABLE {} (
id INTEGER PRIMARY KEY,
text TEXT,
word_id INTEGER NOT NULL,
FOREIGN KEY(word_id) REFERENCES Word(id)
)''' # works with string formatting
Also, what are other efficient(in terms of time) ways to achieve the same?
To put my comment into an answer and expand on it: you cannot parametrize table nor column names. I was unable to find any documentation on this...
In a couple of the other examples you have extra parens/brackets that SQLite doesn't need.
So the solution, as you've found, is to use string substitution for the table names as in your final example.
Here's an example with a loop over all of your tables:
for table in tables:
cursor.execute('''CREATE TABLE {} (
id INTEGER PRIMARY KEY,
text TEXT,
word_id INTEGER NOT NULL,
FOREIGN KEY(word_id) REFERENCES Word(id)
)'''.format(table))
I am not completely clear on why you want different tables for the different types of words, though, as this would seem to go against the principles of database design.

Adding primary key to existing MySQL table in alembic

I am trying to add an 'id' primary key column to an already existing MySQL table using alembic. I tried the following...
op.add_column('mytable', sa.Column('id', sa.Integer(), nullable=False))
op.alter_column('mytable', 'id', autoincrement=True, existing_type=sa.Integer(), existing_server_default=False, existing_nullable=False)
but got the following error
sqlalchemy.exc.OperationalError: (OperationalError) (1075, 'Incorrect table definition; there can be only one auto column and it must be defined as a key') 'ALTER TABLE mytable CHANGE id id INTEGER NOT NULL AUTO_INCREMENT' ()
looks like the sql statement generated by alembic did not add PRIMARY KEY at the end of the alter statement. Could I have missed some settings?
Thanks in advance!
I spent some time digging through the alembic source code, and this doesn't seem to be supported. You can specify primary keys when creating a table, but not when adding columns. In fact, it specifically checks and won't let you (link to source):
# from alembic.operations.toimpl.add_column, line 132
for constraint in t.constraints:
if not isinstance(constraint, sa_schema.PrimaryKeyConstraint):
operations.impl.add_constraint(constraint)
I looked around, and adding a primary key to an existing table may result in unspecified behavior - primary keys aren't supposed to be null, so your engine may or may not create primary keys for existing rows. See this SO discussion for more info: Insert auto increment primary key to existing table
I'd just run the alter query directly, and create primary keys if you need to.
op.execute("ALTER TABLE mytable ADD id INT PRIMARY KEY AUTO_INCREMENT;")
If you really need cross-engine compatibility, the big hammer would be to (1) create a new table identical to the old one with a primary key, (2) migrate all your data, (3)delete the old table and (4) rename the new table.
Hope that helps.
You have to remove the primary key that is in the table and then create a new one that includes all columns that you want as the primary key.
eg. In psql use \d <table name> to define the schema, then check the primary key constraint.
Indexes:
"enrollments_pkey" PRIMARY KEY, btree (se_crs_id, se_std_id)
then use this information in alembic
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('enrollments', sa.Column(
'se_semester', sa.String(length=30), nullable=False))
op.drop_constraint('enrollments_pkey', 'enrollments', type_='primary')
op.create_primary_key('enrollments_pkey', 'enrollments', [
'se_std_id', 'se_crs_id', 'se_semester'])
The results after running \d enrollments should be updated to
Indexes:
"enrollments_pkey" PRIMARY KEY, btree (se_std_id, se_crs_id, se_semester)
This solution worked fine for me.

Categories

Resources