Search code examples
python-3.xpandassqliteinner-joinuser-input

Error while getting user input and using Pandas DataFrame to extract data from LEFT JOIN


I am trying to create Sqlite3 statement in Python 3 to collect data from two tables called FreightCargo & Train where a train ID is the input value. I want to use Pandas since its easy to read the tables.

I have created the code below which is working perfectly fine, but its static and looks for only one given line in the statement.

import pandas as pd
SQL = '''SELECT F.Cargo_ID, F.Name, F.Weight, T.Train_ID, T.Assembly_date 
                         FROM FreightCargo F LEFT JOIN [Train] T
                         ON F.Cargo_ID = T.Cargo_ID
                         WHERE Train_ID = 2;'''
cursor = conn.cursor()
cursor.execute( SQL )
names = [x[0] for x in cursor.description]
rows = cursor.fetchall()
Temp = pd.DataFrame( rows, columns=names)
Temp'''

I want to be able to create a variable with an input. The outcome of this action will then be determined with what has been given from the user. For example the user is asked for a train_id which is a primary key in a table and the relations with the train will be listed.

I expanded the code, but I am getting an error: ValueError: operation parameter must be str

Train_ID = input('Train ID')
SQL = '''SELECT F.Cargo_ID, F.Name, F.Weight, T.Train_ID, T.Assembly_date 
                         FROM FreightCargo F LEFT JOIN [Train] T
                         ON F.Cargo_ID = T.Cargo_ID
                         WHERE Train_ID = ?;''', (Train_ID)
cursor = conn.cursor()
cursor.execute( SQL )
names = [x[0] for x in cursor.description]
rows = cursor.fetchall()
Temp = pd.DataFrame( rows, columns=names)
Temp

Solution

  • The problem lays in your definition of the SQL variable.

    You are creating a tuple/collection of two elements. If you print type(SQL) you will see something like this: ('''SELECT...?;''', ('your_user's_input')).

    When you pass this to cursor.execute(sql[, parameters]), it is expecting a string as the first argument, with the "optional" parameters. Your parameters are not really optional, since they are defined by your SQL-query's [Train]. Parameters must be a collection, for example a tuple.

    You can unwrap your SQL statement with cursor.execute(*SQL), which will pass each element of your SQL list as a different argument, or you can move the parameters to the execute function.

    Train_ID = input('Train ID')
    SQL = '''SELECT F.Cargo_ID, F.Name, F.Weight, T.Train_ID, T.Assembly_date 
                             FROM FreightCargo F LEFT JOIN [Train] T
                             ON F.Cargo_ID = T.Cargo_ID
                             WHERE Train_ID = ?;'''
    cursor = conn.cursor()
    cursor.execute( SQL, (Train_ID,) )
    names = [x[0] for x in cursor.description]
    rows = cursor.fetchall()
    Temp = pd.DataFrame( rows, columns=names)
    Temp