Creating an sql table based off of a variable - python

I am creating a database that includes 3 primary tables:
Users, Assignments, Groups
With other potential tables that relate to the table 'Groups'. These potential tables are meant to be tables which are named based on the key variable in the "Groups" table. eg if the Groups table has an entry with groupName = "Group_One", I want to create a table called "Group_One" and then store the usernames of other users into that table. As don't see a practical way to store multiple usernames in one row of the 'Groups' table.
Here is the code I am testing to try and implement this:
import sqlite3
def Database_Setup():
Cur.executescript(
"""
CREATE TABLE IF NOT EXISTS USERS
(
username text,
password text,
clearance int,
classes int
);
CREATE TABLE IF NOT EXISTS GROUPS
(
groupName text
teacher text,
teachingAssistant text
users
);
CREATE TABLE IF NOT EXISTS ASSIGNMENTS
(
assignmentID int,
assignmentName text,
assignmentInfo text,
dueDate date,
setDate date,
completedAmount int
)
"""
)
def Potential_Solution():
Group_Name = "Group1"
List_Of_Users = ["User1","User2","User3"]
Cur.execute("""
CREATE TABLE IF NOT EXISTS {}
(
username text,
randomVar text
)
""".format(Group_Name))
# This part works fine ^^
for User in List_Of_Users:
Cur.execute("INSERT INTO TABLE ? values (?,'Some_Var')",(Group_Name,User))
def Main():
Database_Setup()
Potential_Solution()
Cur.execute("SELECT * FROM Group1")
print(Cur.fetchall())
if __name__ == "__main__":
Conn = sqlite3.connect("FOO_DB.db")
Cur = Conn.cursor()
Main()
However when I execute this, I run into this error:
Traceback (most recent call last):
File "E:/Python/Py_Proj/DB LIST vs new db example.py", line 53, in <module>
Main()
File "E:/Python/Py_Proj/DB LIST vs new db example.py", line 46, in Main
Potential_Solution()
File "E:/Python/Py_Proj/DB LIST vs new db example.py", line 42, in Potential_Solution
Cur.execute("INSERT INTO TABLE ? values (?,Some_Var)",(Group_Name,User))
sqlite3.OperationalError: near "TABLE": syntax error
is there a practical way to do what I am trying to achieve? Or should I resort to another method?

I tried the following ,
you have to remove TABLE keyword use positional formatting
Cur.execute("INSERT INTO {0} VALUES('{1}', 'SomeVar')".format(Group_Name,User )
)
import sqlite3
def Database_Setup():
Cur.executescript(
"""
CREATE TABLE IF NOT EXISTS USERS
(
username text,
password text,
clearance int,
classes int
);
CREATE TABLE IF NOT EXISTS GROUPS
(
groupName text
teacher text,
teachingAssistant text
users
);
CREATE TABLE IF NOT EXISTS ASSIGNMENTS
(
assignmentID int,
assignmentName text,
assignmentInfo text,
dueDate date,
setDate date,
completedAmount int
)
"""
)
def Potential_Solution():
Group_Name = "Group1"
List_Of_Users = ["User1","User2","User3"]
Cur.execute("""
CREATE TABLE IF NOT EXISTS {}
(
username text,
randomVar text
)
""".format(Group_Name))
for User in List_Of_Users:
Cur.execute("INSERT INTO {0} VALUES('{1}', 'SomeVar')".format(Group_Name,User )
)
def Main():
Database_Setup()
Potential_Solution()
Cur.execute("SELECT * FROM Group1")
print(Cur.fetchall())
if __name__ == "__main__":
Conn = sqlite3.connect("FOO_DB.db")
Cur = Conn.cursor()
Main()

Related

Create SQLite Table With Variable

I want to create three tables fremdgehen.com, molligundwillig.de and reifer6.de.
But I am not able to transfer each element to CREATE TABLE. Why?
import sqlite3
con = sqlite3.connect('emails.db')
cur = con.cursor()
pages = ['fremdgehen.com', 'molligundwillig.de', 'reifer6.de']
for i in pages:
try:
sql_command = f'''
CREATE TABLE {i} (
email INTEGER,
password VARCHAR,
PRIMARY KEY (id));
cur.executescript(sql_command)
con.commit()
'''
except:
pass
con.close()
Since the table names contain a . character, you have to escape the names.
sql_command = f'''
CREATE TABLE `{i}` (
email INTEGER,
password VARCHAR,
PRIMARY KEY (id));
cur.executescript(sql_command)
con.commit()
'''
Note that having . in table and column names is inconvenient, because . is the separator between database, table, and column names. So you'll have to escape the table name in all your queries. Consider removing the . before using it as a table name to simplify this.

How to let user input TABLE name in sqlite3, python3?

I need to prompt a user to create a student table, check if a table with such a name exists in the database, and if not create it.
import sqlite3
conn = sqlite3.connect('School')
print ("Database has been created")
def create_table():
TableName = input("Enter table name: ")
tb_create ="""CREATE TABLE , (TableName,) (ID INT PRIMARY KEY,title VARCHAR(10), forename VARCHAR(20),
surname VARCHAR(20))"""
tb_exists ="SELECT name FROM sqlite_master WHERE type='table' AND name= ?", (TableName,)
if not conn.execute(tb_exists).fetchone():
conn.execute(tb_create)
print ("Table created successfully")
else:
print ("Table Exists!")
I know its possible to inser user inputed value into a table, but how do I create a table with inputed name? What should go after CREATE TABLE? If I use , (TableName,) the code wont compile.
Also, once the new table has been added to database, how do I indicate its name in INSER INTO query?
def insert_data():
conn.execute("INSERT INTO TableName (ID,title,forename,surname)VALUES \
(234,'Mr','XXX','XXX'")
conn.commit()
The correct syntax for a CREATE TABLE statement is:
CREATE TABLE tablename(column1 datatype1, column2 datatype2, ....)
Since you want the user to provide the name of the table, you can do it with string interpolation, because you can't pass it with a ? placeholder in the sql query as aparameter:
tb_create = f"CREATE TABLE [{TableName}](ID INTEGER PRIMARY KEY, title TEXT, forename TEXT, surname TEXT)"
The table's name must be enclosed inside square brackets, just in case the user provided a name that is not valid (for example it starts with digit or contains spaces).
Also, if you want the column ID to be autoincrement, you must use INTEGER instead of INT for its data type.
Also, there is no VARCHAR data type in SQLite. Use TEXT.
You can define the variable TableName as global so that you can use it in all the functions, like insert_data().
Use string interpolation for the INSERT statement also.
import sqlite3
conn = sqlite3.connect("School")
print ("Database has been created")
TableName = ""
def create_table():
global TableName
TableName = input("Enter table name: ").strip()
tb_exists ="SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?"
if not conn.execute(tb_exists, (TableName,)).fetchone():
tb_create = f"CREATE TABLE [{TableName}](ID INTEGER PRIMARY KEY, title TEXT, forename TEXT, surname TEXT)"
conn.execute(tb_create)
print("Table created successfully")
else:
print("Table Exists!")
def insert_data():
if len(TableName) > 0:
conn.execute(f"INSERT INTO [{TableName}] (ID,title,forename,surname) VALUES (234,'Mr','XXX','XXX')")
conn.commit()
create_table()
insert_data()
The name of the table, or of the columns cannot be parameterized, so you must build the query string. It means that you should control that the entered name is sane because building query from strings is know to be a vector for SQL injection.
But most (if not all) SQL database allow to create a table if it does not already exists. The syntax is just:
CREATE TABLE table_name IF NOT EXISTS (
column_name type,
...)
So here, you could just do:
import re
...
def create_table():
TableName = input("Enter table name: ")
# control name:
if not re.match(r'\w*$', TableName):
raise IllegalValue("Invalid table name")
tb_create =f"""CREATE TABLE {TableName} IF NOT EXISTS (ID INT PRIMARY KEY,title VARCHAR(10),
forename VARCHAR(20), surname VARCHAR(20))"""
conn.execute(tb_create)

I can't create table by getting column names from a list?(postgresql/psycopg2)

I have prepared two sample lists below. My goal is to create a table with these two lists in postgresql.id will be bigserial primary key.but I keep getting errors. how do you think i can do that?
My example list and code:
my_column_name = ['id','first name','surname','age']
data= [{'Jimmy', 'wallece', 17}]
connection = psycopg2.connect(user = "postgres",
password = "Sabcanuy.1264",
host="127.0.0.1",
port="5432",
database="postgres")
cursor = connection.cursor()
create_table_query = '''CREATE TABLE unit_category_report (ID BIGSERIAL PRIMARY KEY ,
my_columne_name); '''
Strings cannot access variables and their values.
I’m not 100% sure this will work but you can try:
my_column_name =['id','first_name','surname','age']
create_table_query = '''CREATE TABLE unit_category_report (ID BIGSERIAL PRIMARY KEY , %s); ''' % (my_column_name)
Or...
create_table_query = '''CREATE TABLE unit_category_report (ID BIGSERIAL PRIMARY KEY , {0}); '''.format(my_column_name)
You may have to switch to double quotes from the triple single quote.

creating mysql tables id best pratice

I am coding a new python (version 3.8.2) project with a mysql(8.0.19) db.
This is the table creation code:
import mysql.connector
mydb = mysql.connector.connect(
host = "localhost",
user = "root",
password = "mypassword",
database = "acme_db"
)
mycursor = mydb.cursor()
sql_formula = ("CREATE TABLE employee (employee_id INT AUTO_INCREMENT PRIMARY KEY,"
"first_name VARCHAR(255),"
"last_name VARCHAR(255),"
"email VARCHAR(255),"
"phone_nr VARCHAR(255),"
"hire_date DATE,"
"job_id INTEGER,"
"salary NUMERIC(8,2),"
"commission_pct NUMERIC(8,2),"
"manager_id INTEGER,"
"department_id INTEGER)")
mycursor.execute(sql_formula)
mycursor.execute("CREATE TABLE jobs (job_id INT, job VARCHAR(255))")
mycursor.execute("CREATE TABLE managers (manager_id INT, employee_id INTEGER)")
mycursor.execute("CREATE TABLE departments (department_id INT, department_name VARCHAR(255))")
The question is, what is the best practice about id?
What I mean is this, employee_id is unique auto increment pk, that I understand, what about the other id's? for tables jobs, managers and departments.
Shouldn't they be also the same as employee_id definition or just INT and I need to take care of the number, that it doesn't repeat itself, and so on?
I did make all id's the same definition but I coudn't insert data to the tables:
dptFormula = "INSERT INTO depatments (department_name) VALUES (%s)"
acme_departments = [("Accounting"),("R&D"),("Support")]
mycursor.executemany(dptFormula, acme_departments)
I got:
Traceback (most recent call last):
File "c:/Users/Daniel/EmployeeProject/employee_mgt/insert_into.py", line 20, in <module>
mycursor.executemany(dptFormula, acme_departments)
File "C:\Program Files\Python38\lib\site-packages\mysql\connector\cursor.py", line 668, in executemany
stmt = self._batch_insert(operation, seq_params)
File "C:\Program Files\Python38\lib\site-packages\mysql\connector\cursor.py", line 613, in _batch_insert
raise errors.ProgrammingError(
mysql.connector.errors.ProgrammingError: Not all parameters were used in the SQL statement
You're already using one best practice. Each table has an autoincrementing integer for a primary key, and you named those keys after the tables (employee_id, 'job_id, not justid`)
Each table has its own sequence of autoincrementing id values. If you try to look up something in your employees table using a job_id, you'll get nonsense. But you can do things like this
SELECT e.first_name, e.last_name, j.job
FROM employee e
JOIN job h ON e.job_id = j.job_id
to exploit the relationship between employee and job. The relationships between rows of tables expressed by JOIN job h ON e.job_id = j.job_id are the reason for the term relational database management system.
In a comment, #Akina pointed out you should use this sort of definition for your primary key columns.
something_id UNSIGNED INT NOT NULL AUTO_INCREMENT PRIMARY KEY
That's good advice.

Working with databases with Python: Course registration data in JSON

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.

Categories