I have this code in python querying an existing database:
count = db.execute("SELECT COUNT (player_id) FROM players WHERE user_id
= :id", id = session["user_id"])
for player in range(count):
db.execute("INSERT INTO live_players (player_id) VALUES (:filler)",
filler = 0)
However, it doesn't run because 'count' isn't an int. I want SELECT COUNT to return 2, but instead it returns '[{'COUNT (player_id)': 2}]'. How could I remedy this?
You're getting back a result dictionary. Simply access it. To make this access easier, give it an alias:
SELECT COUNT(player_id) AS player_count ...
Then:
for player in range(count["player_count"]):
...
Related
I believe that I need to to expand the sql statement as the current one I have:
SELECT OrderID FROM Orders WHERE UserID = (?)
is likely to cause problems in the future when there are users with multiple orders. Is there a way that I can select and use the autoincrementing orderID in my orders table in combination?
For reference, my DB looks like this:
And the python I currently have is like this however I feel that it may have to be rewritten entirely.
results[0][0] is the ID of the current user from the Users table
elif userinput == "5":
basket = []
print(pd.read_sql_query('SELECT * FROM Products', conn))
shopping = True
while shopping:
itemToAdd = input("Please enter the ID of the item to add to the basket: ")
basket.append(itemToAdd)
print(basket)
continueShop = input("Continue shopping?(y/n): ")
if continueShop == "n":
conn.execute("INSERT INTO Orders (UserID) VALUES (?)", (results[0][0],))
conn.commit()
counter = 0
for items in basket:
createOrderItems = "INSERT INTO OrderItems (OrderID, ProductID) VALUES (?,?)"
currentOrder = ("SELECT OrderID FROM Orders WHERE UserID = (?) ", (results[0][0]))
conn.execute(createOrderItems, (currentOrder[0], basket[counter]))
counter = +1
conn.commit()
Because the database is built using the DB Browser application, I really have no clue how to access the parts of it that I need to ensure I am selecting the right record. Any help is appreciated, thanks.
Also, since the primary key of each table is autoincrementing I need a way to select only the record that was created just now using
conn.execute("INSERT INTO Orders (UserID) VALUES (?)",
However, I cannot think of a way to do so even though the record is unique in the orders table, as there is no way of knowing which order is the one that needs to be looked at as far as I can tell
You can use the lastrowid attribute of the cursor object to find the id of the inserted order. Then use a compound WHERE in the select statement (ie WHERE userid = something and orderid = something_else).
I've been working most of today on a function that creates a record in an sqlite table. I believe I am finally making some progress and it currently looks like this:
shopping = True
while shopping:
itemToAdd = input("Please enter the ID of the item to add to the basket: ")
basket.append(itemToAdd)
print(basket)
continueShop = input("Continue shopping?(y/n): ")
if continueShop == "n":
conn.execute("INSERT INTO Orders (UserID) VALUES (?)", (results[0][0],))
lastID = conn.execute("SELECT last_insert_rowid()")
conn.commit()
counter = 0
for items in basket:
createOrderItems = "INSERT INTO OrderItems (OrderID, ProductID) VALUES (?,?)"
conn.execute(createOrderItems, (lastID, basket[counter]))
counter = +1
conn.commit()
However, I am now encountering this error to do with lastID if I am reading the error correctly.
line 107, in
conn.execute(createOrderItems, (lastID, basket[counter])) sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type.
I have 2 tables that I am currently attempting to use:
Orders - contains only an orderID and userID
OrderItems- contains OrderItemsID, OrderID (which i need to be the same as the OrderID Just added) and ProductID(which needs to be taken from the list created and looped to make a record for each item in the "basket".
When you do
lastID = conn.execute("SELECT last_insert_rowid()")
lastID gets bound to an sqlite3.Cursor:
To retrieve data after executing a SELECT statement, you can either treat the cursor as an iterator, call the cursor’s fetchone() method to retrieve a single matching row, or call fetchall() to get a list of the matching rows.
The cursor cannot be converted automatically to the raw ID. You'll have to pull it out yourself, e.g. by doing something like
row = lastID.fetchone()
row_id = row[0]
Then use row_id in your query instead of lastID.
I'm trying to save a column value into a python variable; I query my DB for a int in a columns called id_mType and id_meter depending of a value that I get from a XML. To test it I do the next (I'm new using databases):
m = 'R1'
id_cont1 = 'LGZ0019800712'
xdb = cursor.execute("SELECT id_mType FROM mType WHERE m_symbol = %s", m)
xdb1 = cursor.execute("select id_meter from meter where nombre = %s",
id_cont1)
print (xdb)
print (xdb1)
I get every time the value "1" where the id_mType for 'R1' = 3 and id_meter= 7 for id_cont1 value. I need this to insert in another table (where there are both FK: id_meter and id_mType. Dont know if there is an easiest way)
You can store it in a list. Is that okay?
results=cursor.fetchall()
my_list=[]
for result in results:
my_list.append(result[0])
Now my_list should hold the SQL column you get returned with your query.
Use the fetchone() method to fetch a row from a cursor.
row = xdb.fetchone()
if row:
mtype = row[0]
row = xdb1.fetchone()
if row:
meter = row[0]
I've been learning Python recently and have learned how to connect to the database and retrieve data from a database using MYSQLdb. However, all the examples show how to get multiple rows of data. I want to know how to retrieve only one row of data.
This is my current method.
cur.execute("SELECT number, name FROM myTable WHERE id='" + id + "'")
results = cur.fetchall()
number = 0
name = ""
for result in results:
number = result['number']
name = result['name']
It seems redundant to do for result in results: since I know there is only going to be one result.
How can I just get one row of data without using the for loop?
.fetchone() to the rescue:
result = cur.fetchone()
use .pop()
if results:
result = results.pop()
number = result['number']
name = result['name']
My table bank has three columns: uid, nick, and balance.
I can insert new row perfectly fine, however it would be easy for duplicates of the nick to appear since the uid auto increments, making each row unique. However I don't want that, I only one want one row for each nick.
target = input.group(2)
cursor.execute ("INSERT INTO bank (nick, balance) VALUES('" + db.escape_string(target.lower()) + "', 5)")
db.commit()
bot.say('An account for ' + target + ' has been created.')
That is my code so far, however I am unsure in how I would create a SELECT query and then check if the nick already exists in the table before inserting a new row.
I would adopt a different approach. I would add a unique constraint at DB-level on the nick column:
ALTER TABLE bank ADD UNIQUE (nick);
Within your Python code, then put a try and except to handle the unique constraint violated exception appropriately.
It doesn't sound like it makes sense to have that incrementing ID.
Consider instead an unique identifier for the account, e.g. an account number.
The danger with adding a unique constraint on nick, as another answer suggests, is that as your population grows, you will likely have two or more people who wish to use the same nick.
Also, you should pass the values to insert as a second argument to execute() for at least two reasons*.
cursor.execute("""INSERT INTO bank (nick, balance)
VALUES (%s, %s);""", (target.lower(), 5))
*Two reasons for that are:
You avoid having to manually handle any quoting issues. Mysql-Python will take care of that for you.
You avoid a possibility of SQL-injection attacks.
Please note: the parameter placeholders are %s for all types of parameter, not just strings. So you don't need to do anything like %d to insert an integer.
I suppose you are using psycopg2
cursor.execute ("SELECT * FROM bank WHERE nick = %s",[nick])
nick = cursor.fetchall()
if nick ...
I'm using Python (3.6) and MySql and I wanted to check records before adding them.
Here is my code:
import mysql.connector
mydb = mysql.connector.connect(
host="localhost",
user="user",
passwd="password",
database='football'
)
mycursor = mydb.cursor()
def write_to_db(db_table, col_list, data_list, *supply_id):
"""
Takes a record, checks if it already exists and if not inserts it, returning its index or None
:param db_table: name of table to be checked / inserted into
:param col_list: column/field names in a list eg. ['meat', 'sides']
:param data_list: data to be found or inserted eg ['spam', 'eggs']
:param supply_id: Only if you supply calculated id as tuple ('table_id', table_id_val)
:return: If lists don't match =None Else =Index of found record or Index of inserted one
"""
if len(col_list) != len(data_list) or len(col_list) == 0: # List lengths must match
return None # Otherwise returned index is None
# Build search SQL - Select - table - Where - match conditions
find_existing_sql = 'SELECT * FROM {} '.format(db_table) # Which table
find_existing_sql += 'WHERE {} = {} '.format(col_list[0], data_list[0])
sql_end = ' LIMIT 1 ;'
if len(col_list) > 1: # Provided record has more than 1 column
and_sql = ' AND {} = {} ' # add extra match condition for each column
for indx in list(range(1, len(col_list))):
find_existing_sql += and_sql.format(col_list[indx], data_list[indx])
find_existing_sql += sql_end # Complete SQL to find given record
my_cursor.execute(find_existing_sql) # Query database with SQL
seek_response = my_cursor.fetchall() # Read the seek a record response
record_exists = len(seek_response) > 0 # Length = 0 not found, > 0 found
if record_exists:
return seek_response[0][0] # Return id = the first item from the first list of items
else:
# Build insert SQL - Insert into - table - column names - values
insert_sql = 'INSERT INTO {} ('.format(db_table) # Which table
if supply_id is not None: # If you supplied an index
id_col = supply_id[0][0] # first item in first arg = index name
id_val = supply_id[0][1] # second item in first arg = index value
col_list =[id_col] + col_list # Add index column name on the front of column list
data_list = [id_val] + data_list # Add index value on front of data_list
first_col = '{}'.format(col_list[0]) # Start listing columns
more_cols_vals = ', {}' # To add more coumns/values if needed
values_sql = ') VALUES ( {} '.format(data_list[0]) # Start listing values
end_sql = ' );'
insert_cols_sql = insert_sql + first_col
if len(col_list) > 1:
for indx in list(range(1, len(col_list))):
insert_cols_sql += more_cols_vals.format(col_list[indx])
values_sql += more_cols_vals.format(data_list[indx])
# Put Insert SQL together
insert_new_sql = insert_cols_sql + values_sql + end_sql
my_cursor.execute(insert_new_sql) # Insert the new record into db
mydb.commit()
if supply_id is not None: # If you supplied an index
return id_val # Return that
else: # if not
return my_cursor.lastrowid # Return auto-generated index
This function takes the name of the table, a list of column names, a list of values to insert and an optional tuple if you supply your own generated index thus
('table_id', table_id_value)
but if you don't supply this tuple, MySQL will use the auto-generated index for the insert.
The routine assumes that your table has the index as its first column.
It returns the index of the found record if it already exists, if the record doesn't exist it returns the index it uses when it inserts the record. The index is either the one MySQL generates or the one you supply.
It returns None if your column names list and value list lengths don't match.
I have used Python to build the SQL statements so you can have a variable number of columns.
You could pass values within SQL (though I've no idea how you do that for a variable number of columns and values) but I kept getting 'wrong number of parameters' errors and using Python's string.format() solved that.
The *supply_id (conventionally *args) parameter is a list even if you only supply one tuple so I needed two indices to access the first arg and then the 0 or 1 to access the column name and value in the tuple.
The .fetchall() itself was necessary to prevent 'unread record' errors as it clears the data from the cursor if a record is found.