I have to loop over all rows in the database and have to update them at some location. I have written this code:
import sqlite3
con=sqlite3.connect("Models.db")
c=con.cursor()
c1=con.cursor()
c.execute("CREATE TABLE ABC(id INTEGER PRIMARY KEY, COLVAL text)")
///inserted a few rows........
for row in c.execute("SELECT * FROM ABC"):
if $(any condition):
with con:
c1.execute("UPDATE ABC SET COLUMN1=(:COLVAL) WHERE id=(:id)",{'COLVAL':'XYZ','id':row[0]})
but I get an error:
OperationalError: database is locked
in the second query, c1.execute("UPDATE ABC SET COLUMN1=(:COLVAL) WHERE id=(:id)",{'COLVAL':'XYZ','id':row[0]})
I do not want to fetch all rows at a time and apply for a loop, as there is a lot of data. Just one row at a time which in my case:
"for row in c.execute("SELECT * FROM ABC")"
line is doing.
Does anyone know the solution for it?
Basically you can loop within a list such as c.execute("SELECT * FROM abc").fetchall()
c.execute("CREATE TABLE IF NOT EXISTS abc(id INT PRIMARY KEY, column1 TEXT)")
///inserted a few rows........
for row in c.execute("SELECT * FROM abc").fetchall():
if $(any condition):
c.execute("UPDATE abc SET column1=(?) WHERE id=(?)",('XYZ',row[0],))
con.commit()
con.close()
Additionally;
add IF NOT EXISTS to the DDL Statement
replace parameter placeholders with question marks as being securer
no need to open more than one cursor
don't miss commiting the DML Statement at the end
extra tip : use executemany as
c.executemany("UPDATE abc SET column1=(?) WHERE id=(?)",[('XYZ',row[0],)])
instead of execute for the DML statement for the multiple data as being more performant. Indeed, you don't need for this current case as only concerns with only one row for each id value
Related
I'm trying to debug a SQL statement generated with sqlite3 python module...
c.execute("SELECT * FROM %s WHERE :column = :value" % Photo.DB_TABLE_NAME, {"column": column, "value": value})
It is returning no rows when I do a fetchall()
When I run this directly on the database
SELECT * FROM photos WHERE album_id = 10
I get the expected results.
Is there a way to see the constructed query to see what the issue is?
To actually answer your question, you can use the set_trace_callback of the connection object to attach the print function; this will make all queries get printed when they are executed. Here is an example in action:
# Import and connect to database
import sqlite3
conn = sqlite3.connect('example.db')
# This attaches the tracer
conn.set_trace_callback(print)
# Get the cursor, execute some statement as an example
c = conn.cursor()
c.execute("CREATE TABLE stocks (symbol text)")
t = ('RHAT',)
c.execute("INSERT INTO stocks VALUES (?)", t)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
print(c.fetchone())
This produces the output:
CREATE TABLE stocks (symbol text)
BEGIN
INSERT INTO stocks VALUES ('RHAT')
SELECT * FROM stocks WHERE symbol='RHAT'
('RHAT',)
the problem here is that the string values are automatically embraced with single quotes. You can not dynamically insert column names that way.
Concerning your question, I'm not sure about sqlite3, but in MySQLdb you can get the final query as something like (I am currently not at a computer to check):
statement % conn.literal(query_params)
You can only use substitution parameters for row values, not column or table names.
Thus, the :column in SELECT * FROM %s WHERE :column = :value is not allowed.
I have a sqlite3 program in which I have to connect to a database stored in 'employees.db'. I will enter the first name, last name and salary and then print it. For printing, I will use fetchall(). But when I print the output, what I get is this-->
[]
only 2 square brackets?
What is wrong?
I have started to learn python 2 weeks ago. But my course where I am learning is going too fast. I don't know what I am doing in this program is the correct approach or not?
HERE IS MY CODE--->>>
import sqlite3;
conn=sqlite3.connect('employees.db');
c=conn.cursor();
c.execute("""CREATE TABLE employees(first text,last text,pay integer)""");
c.execute("INSERT INTO employees VALUES('Tendo','Sinha',600000)");
c.execute("INSERT INTO employees VALUES('Krit','Kumar',40000)");
print(c.fetchall());
conn.commit();
conn.close
I don't get any error. The output only shows:-
[]
Only 2 square brackets.
You are inserting rows into the table but not retrieving them at all.
Try adding a SELECT statement:
import sqlite3
conn = sqlite3.connect("employees.db")
c = conn.cursor()
# Create table, insert things...
c.execute(
"""CREATE TABLE IF NOT EXISTS employees(first text,last text,pay integer)"""
)
c.execute("INSERT INTO employees VALUES('Kritin','Sinha',600000)")
c.execute("INSERT INTO employees VALUES('Krit','Kumar',40000)")
# Commit the changes.
conn.commit()
# Retrieve from the table.
c.execute("SELECT * FROM employees")
print(c.fetchall())
you have to run a query for fetching all rows.
add these lines to your code-
data = c.execute("Select * FROM employees").fetchall()
print(data);
I have a piece of code that I realized is probably quite inefficient, though I'm not sure how to improve it.
Basically, I have a database table like this:
Example DB table
Any or several of columns A-G might match my search query. If that is the case, I want to query VALUE from that row. I need VALUE not to equal NULL though, so if that's the case, it should keep looking. If my query were abc, I'd want to obtain correct.
Below is my current code, using a database named db with a table table.
cur=db.cursor()
data="123"
fields_to_check=["A","B","C","D","E","F","G"]
for field in fields_to_check:
"SELECT Value FROM table WHERE {}='{}'".format(field,data)
query=cur.fetchone()
if query and query !="NULL":
break
db.close()
I think that the fact that this performs 8 queries is likely very inefficient.
cur=db.cursor()
data="123"
fields_to_check=["A","B","C","D","E","F","G"]
sub_query = ""
for field in fields_to_check:
sub_query = sub_query + "or {}='{}' ".format(field,data)
if sub_query:
query = "SELECT Value FROM table WHERE ("+ str(sub_query[2:]) +") and value IS NOT NULL;"
if query:
cur.execute(query)
rows = cur.fetchall()
if rows:
for row in rows:
print(row)
This question already has answers here:
How can I get dict from sqlite query?
(16 answers)
Closed 4 years ago.
Issue:
Hi, right now I am making queries to sqlite and assigning the result to variables like this:
Table structure: rowid, name, something
cursor.execute("SELECT * FROM my_table WHERE my_condition = 'ExampleForSO'")
found_record = cursor.fetchone()
record_id = found_record[0]
record_name = found_record[1]
record_something = found_record[2]
print(record_name)
However, it's very possible that someday I have to add a new column to the table. Let's put the example of adding that column:
Table structure: rowid, age, name, something
In that scenario, if we run the same code, name and something will be assigned wrongly and the print will not get me the name but the age, so I have to edit the code manually to fit the current index. However, I am working now with tables of more than 100 fields for a complex UI and doing this is tiresome.
Desired output:
I am wondering if there is a better way to catch results by using dicts or something like this:
Note for lurkers: The next snipped is made up code that does not works, do not use it.
cursor.execute_to(my_dict,
'''SELECT rowid as my_dict["id"],
name as my_dict["name"],
something as my_dict["something"]
FROM my_table WHERE my_condition = "ExampleForSO"''')
print(my_dict['name'])
I am probably wrong with this approach, but that's close to what I want. That way if I don't access the results as an index, and if add a new column, no matter where it's, the output would be the same.
What is the correct way to achieve it? Is there any other alternatives?
You can use namedtuple and then specify connection.row_factory in sqlite. Example:
import sqlite3
from collections import namedtuple
# specify my row structure using namedtuple
MyRecord = namedtuple('MyRecord', 'record_id record_name record_something')
con = sqlite3.connect(":memory:")
con.isolation_level = None
con.row_factory = lambda cursor, row: MyRecord(*row)
cur = con.cursor()
cur.execute("CREATE TABLE my_table (record_id integer PRIMARY KEY, record_name text NOT NULL, record_something text NOT NULL)")
cur.execute("INSERT INTO my_table (record_name, record_something) VALUES (?, ?)", ('Andrej', 'This is something'))
cur.execute("INSERT INTO my_table (record_name, record_something) VALUES (?, ?)", ('Andrej', 'This is something too'))
cur.execute("INSERT INTO my_table (record_name, record_something) VALUES (?, ?)", ('Adrika', 'This is new!'))
for row in cur.execute("SELECT * FROM my_table WHERE record_name LIKE 'A%'"):
print(f'ID={row.record_id} NAME={row.record_name} SOMETHING={row.record_something}')
con.close()
Prints:
ID=1 NAME=Andrej SOMETHING=This is something
ID=2 NAME=Andrej SOMETHING=This is something too
ID=3 NAME=Adrika SOMETHING=This is new!
I'm trying to debug a SQL statement generated with sqlite3 python module...
c.execute("SELECT * FROM %s WHERE :column = :value" % Photo.DB_TABLE_NAME, {"column": column, "value": value})
It is returning no rows when I do a fetchall()
When I run this directly on the database
SELECT * FROM photos WHERE album_id = 10
I get the expected results.
Is there a way to see the constructed query to see what the issue is?
To actually answer your question, you can use the set_trace_callback of the connection object to attach the print function; this will make all queries get printed when they are executed. Here is an example in action:
# Import and connect to database
import sqlite3
conn = sqlite3.connect('example.db')
# This attaches the tracer
conn.set_trace_callback(print)
# Get the cursor, execute some statement as an example
c = conn.cursor()
c.execute("CREATE TABLE stocks (symbol text)")
t = ('RHAT',)
c.execute("INSERT INTO stocks VALUES (?)", t)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
print(c.fetchone())
This produces the output:
CREATE TABLE stocks (symbol text)
BEGIN
INSERT INTO stocks VALUES ('RHAT')
SELECT * FROM stocks WHERE symbol='RHAT'
('RHAT',)
the problem here is that the string values are automatically embraced with single quotes. You can not dynamically insert column names that way.
Concerning your question, I'm not sure about sqlite3, but in MySQLdb you can get the final query as something like (I am currently not at a computer to check):
statement % conn.literal(query_params)
You can only use substitution parameters for row values, not column or table names.
Thus, the :column in SELECT * FROM %s WHERE :column = :value is not allowed.