I'm busy writting a python script that is querying two db tables to build a single row of data per row it finds. Here is my script at the moment
#========================================================================
# DB CONNECT FUNCTION
#========================================================================
def f_connect(status):
global gv_conn
global gv_curs
if status == 1:
gv_conn = sqlite3.connect("./data.db")
gv_curs = gv_conn.cursor()
else
gv_conn.close()
#========================================================================
# PREPARE SQL STATEMENTS
#========================================================================
def f_statements():
global users_stmt
users_stmt = ("select * from users")
global users_curs
users_curs = gv_conn.cursor()
global uinfo_stmt
uinfo_stmt = ("select * from uinfo" +
"where ui_u_id = ?")
global uinfo_curs
uinfo_curs = gv_conn.cursor()
#========================================================================
#
# MAIN SCRIPT START
#
#========================================================================
f_connect(1)
f_statements()
la_users = []
for u_row in users_curs.execute(users_stmt):
# THIS LINE GETS USERS FROM THE ABOVE STATEMENT
# AND ADDS THEM TO THE DICTIONARY
la_users.append({"u_id": u_row[0], "u_name": u_row[1]})
# THIS LINE EXECUTES ANOTHER QUERY TO RETRIEVE
# A SINGLE ROW OF DATA FROM ANOTHER TABLE
la_uinfo = uinfo_curs.execute(uinfo_stmt, "1")
f_connect(0)
My problem is that when I execute the first sql statement I can get get the data by looping using a for loop which is storing the data so i can access it using u_row[int].
When I execute the second query it is storing it inside la_uinfo although when I try to get the data from la_uinfo[int] it doesn't work? How can I retrieve the data from my second query without using another for loop? (I shouldn't have to considering it only returns one row)
Cursors are not indexable, so cursor[0] will not work. To retrieve the first row of a cursor, you should use cursor.fetchone().
Related
My objective is to show a kanban table by day, so the user could save their pending, in process or completed tasks for each day in the calendar. My program look as follows:
Every list is a QListWidget, where the user can add a new pending task by right clicking over them or move the tasks from the "Pendientes" list to the "En proceso" list or the "Completadas" list.
Now, for saving the task for every date of the QCalendarWidget, I'm trying to use a sqlite database that looks like this:
where the "tareas" column shows the tasks, "lista" shows a number corresponding to each of my three QListWidgets (0 = "Pendientes"; 1 = "En proceso" and 2 = "Completadas") and "fecha" shows the date. I'm able to show every task in the corresponding list by date just fine with this function, but only the tasks that I added directly in the Sqlite Browser:
def updateTaskList(self, date):
self.lista_pendientes.clear()
self.lista_enprogreso.clear()
self.lista_completadas.clear()
db = sqlite3.connect("todo.db")
cursor = db.cursor()
query = "SELECT tarea, lista FROM tareas WHERE fecha = ?"
row = (date,)
results = cursor.execute(query, row).fetchall()
for tarea, list in results:
item = QListWidgetItem(tarea)
if list == 0:
self.lista_pendientes.addItem(item)
elif list == 1:
self.lista_enprogreso.addItem(item)
elif list == 2:
self.lista_completadas.addItem(item)
But when I try to save the tasks that I added from my program it doesn't save the changes:
def saveChanges (self):
db = sqlite3.connect("todo.db")
cursor = db.cursor()
date = self.calendarWidget.selectedDate().toPython()
for i in range(self.lista_pendientes.count()):
item = self.lista_pendientes.item(i)
task = item.text()
query = "UPDATE tareas SET lista = '0' WHERE tarea = ? AND fecha = ? "
row = (task, date,)
cursor.execute(query,row)
db.commit()
In this function I'm trying to save only the tasks that are in the "pendientes" list, by assigning the index 0 to those tasks, but to no avail. What could I do to save the tasks from the three QListWidgets in my database?
EDIT-SOLVED
After experimenting a bit I founded an easier solution: to use three different tables in my sqlite database for each type of task. That way I can save each task individually without worrying about the list column.
I am trying to create a search function in tkinter from a sql table.
for konto in sql_konto_search(db_file, "kontoplan", keywords):
tv.insert('', tk.END, values=((konto[konto_q][0], konto[konto_q][1]), konto[konto_q][2]), tags=('fg', 'fs', 'bg', 'anch'))
konto_q += 1
if not keywords:
tv.delete(*tv.get_children())
tv_index()
Here is my SQL code (function). I am trying to create a query that is searching for multiple keywords - but it is not working that well.
def sql_konto_search(db_file, table, keywords):
keywords_split = keywords.split()
keywords_list = []
for keyword in keywords_split:
keywords_list.append(keyword)
ant_que = len(keywords_list)
keywords_list = tuple(keywords_list)
try:
rows = []
conn = sqlite3.connect(db_file)
cur = conn.cursor()
xq = 0
for ant_q in range(ant_que):
cur.execute(f"SELECT konto, konto_t, beskrivelse FROM {table} WHERE konto_t LIKE ('%{keywords_list[xq]}%') OR beskrivelse LIKE ('%{keywords[xq]}%')")
xq += 1
rows.append(cur.fetchall())
return rows
except Error as e:
print(e)
As you can see "keywords" are user input keywords - and I want to search for every single word.
Any suggestions?
You'll want something like this to properly compose a single SQL query from your keyword search string.
This also properly uses parameter substitution, so your program is no longer vulnerable to SQL injection issues. (I recommend reading the sqlite3 module documentation; search for "Never do this".)
import sqlite3
def sql_konto_search(db_file, table, keywords):
# Get an unique set of keywords from the string
keywords_set = set(keyword.strip() for keyword in keywords.split())
# Initialize a list for the where clauses we'll OR together
where_clauses = []
# Initialize a list for the `?` parameter placeholders.
parameters = []
for keyword in keywords_set:
# If the keyword is empty, skip it.
if not keyword:
continue
# Add a parenthesized fragment for the search with two parameter placeholders...
where_clauses.append("(konto_t LIKE ? OR beskrivelse LIKE ?)")
# ... so add two parameters.
keyword_wildcard = f"%{keyword}%"
parameters.append(keyword_wildcard)
parameters.append(keyword_wildcard)
# Compose the final query. Start with the select...
query_fragments = [f"SELECT konto, konto_t, beskrivelse FROM {table}"]
if where_clauses:
# and if there are where clauses, add the WHERE
# and join the clauses with ORs (they're already parenthesized above)
query_fragments.append(" WHERE ")
query_fragments.append(" OR ".join(where_clauses))
# Join the fragments into a single SQL statement...
sql = "".join(query_fragments)
print(sql, parameters) # Just so you can see what happens.
# ... and execute it.
with sqlite3.connect(db_file) as db:
cur = db.cursor()
cur.execute(sql, parameters)
return cur.fetchall()
I am writing a python script to perform some specific task if an element ID pre-exists. I have created a database where I am saving the data elements.
I want to find out if the element link_ID exists in the database or not. How will I do that?
I have written a small script which is not perfect. The output I am getting is No such element exists.
link_ID = link_1234
sql = ''' SELECT link_ID from link_table where link_ID=? '''
var = (link_ID)
conn.execute(sql, [var])
conn.commit()
if conn.execute(sql, [var]) == True:
print("Search Successful")
flag = 1
else:
print("No such element exists")
flag = 0
You have a number of problems here. First, you should create a cursor object from your connection and use that to execute your query:
c = conn.cursor()
c.execute(sql,var)
Secondly, execute wants a tuple of values to interpolate, not a list, so do this:
var = (link_ID,)
c.execute(sql,var)
Or:
c.execute(sql,(link_ID,))
Lastly, c.execute returns the cursor object rather than the success of the query. You should fetch the result of the query using fetchone(), if your query didn't return a row then the return value of fetchone() will be None:
result = c.fetchone()
if result is not None:
print('Success:',result)
else:
print('No row found for', link_ID)
I am trying to pass a variable to search for the row from SQLite DB and print out the results. Here is the code below thats causing the problem:
find_domain = 'domain.com'
def searchdomain(locate):
row = sql.execute("SELECT * FROM blocked_domains WHERE name = ?;",(locate,))
print(row)
searchdomain(find_domain)
No error comes up, it just come back blank.
Ensure that you have created a cursor object for data retrieval:
import sqlite3
conn = sqlite3.connect('tablename.db')
data = list(conn.cursor().execute("SELECT * FROM blocked_domains WHERE name = ?;", (locate,)))
I am trying to make a random code generator in python that writes to a database. I have the codes generating and writing to the database, but instead of adding full codes to the database it loops through letters. Here is my code for the code generator:
import string
import random
import sqlite3
def id_generator():
db = sqlite3.connect('codes.db')
c = db.cursor()
number_of_codes = 10
stringLength = 9
id_code = input("what letter should this begin with: \n")
id_code = id_code.upper()
dict_ofcodes = []
for x in range(0, number_of_codes):
codez = (''.join(random.choice(string.ascii_uppercase) for i in range(stringLength)))
final_codez = (id_code + codez)
dict_ofcodes.insert(x, final_codez)
print (dict_ofcodes)
dict_ofcodes_tuple = tuple(dict_ofcodes)
print(dict_ofcodes_tuple)
for x in range(0, number_of_codes):
c.executemany(''' INSERT INTO codes(codes) VALUES(?)''', dict_ofcodes_tuple[x])
db.commit()
db.close()
id_generator()
Here is what it prints
['AALRRIULNC', 'AZTKZBKTLK', 'ATWMWYWICO', 'AWQJIJYEJH', 'AQFIONPUNJ', 'AMJRXUIJXM', 'AUDRLSBLSG', 'ABXYXDUMPD', 'AUAXRQURBH', 'ADQEVIRDFU']
('AALRRIULNC', 'AZTKZBKTLK', 'ATWMWYWICO', 'AWQJIJYEJH', 'AQFIONPUNJ', 'AMJRXUIJXM', 'AUDRLSBLSG', 'ABXYXDUMPD', 'AUAXRQURBH', 'ADQEVIRDFU')
It writes to the database single letters of the codes:
A
F
Y
and so on
The code I used to create the schema is contained in the a python file
import sqlite3
def writeDB():
db = sqlite3.connect('codes.db')
c = db.cursor()
# Create table
c.execute('''CREATE TABLE codes (codes TEXT)''')
# Save (commit) the changes
db.commit()
#can also close the connection if done with it.
# be sure any changes have been committed or they will be lost.
db.close()
writeDB()
I created the file with the mac terminal.
How could I write the full codes to the database?
The problem is with this line:
c.executemany(''' INSERT INTO codes(codes) VALUES(?)''', dict_ofcodes_tuple[x])
executemany is used to iterate over a list of parameters and call the sql statement for each parameter. So your dict_ofcodes_tupel[x] is treated as a character array and the INSERT is called for each character.
If you want to insert the entire string as one, use execute() instead.
c.execute(''' INSERT INTO codes(codes) VALUES(?)''', (dict_ofcodes_tuple[x],))
or
c.execute(''' INSERT INTO codes(codes) VALUES(?)''', [dict_ofcodes_tuple[x]])