Even though I pass a list as params I am getting the below error while executing the query
TypeError: ('Params must be in a list, tuple, or Row', 'HY000')
I am trying to pass multiple rows to sql table using executemany
Please find my code below and help, I am new to python.
query = """INSERT INTO TableTest (Summary) Values (%s)"""
val = [('SPHXNORF2ASW1'),('CHNSIRSDB1USAA'),('NKOLGTPRAVPNVM'),('STAMHO3WANCEG'),('SPHXNORWANCEG1'),('SPHXNORWANCE'),('STAMHO3WANCEG')]
cursor = conn.cursor()
cursor.executemany(query,val)
conn.commit() ```
In python, putting a value inside '()' does not make it tuple.
So, this code
val = [('SPHXNORF2ASW1'),('CHNSIRSDB1USAA'),('NKOLGTPRAVPNVM'),('STAMHO3WANCEG'),('SPHXNORWANCEG1'),('SPHXNORWANCE'),('STAMHO3WANCEG')]
will be converted to
['SPHXNORF2ASW1', 'CHNSIRSDB1USAA', 'NKOLGTPRAVPNVM', 'STAMHO3WANCEG', 'SPHXNORWANCEG1', 'SPHXNORWANCE', 'STAMHO3WANCEG']
If you want to specify it as a tuple, add a trailing comma like below or use '[]' instead of tuple.
Use:
val = [('SPHXNORF2ASW1',),('CHNSIRSDB1USAA',),('NKOLGTPRAVPNVM',),('STAMHO3WANCEG',),('SPHXNORWANCEG1',),('SPHXNORWANCE',),('STAMHO3WANCEG',)]
Or:
[ ['SPHXNORF2ASW1'], ['CHNSIRSDB1USAA'], ['NKOLGTPRAVPNVM'], ['STAMHO3WANCEG'], ['SPHXNORWANCEG1'], ['SPHXNORWANCE'], ['STAMHO3WANCEG']]
Related
Is there an elegant way of getting a single result from an SQLite SELECT query when using Python?
for example:
conn = sqlite3.connect('db_path.db')
cursor=conn.cursor()
cursor.execute("SELECT MAX(value) FROM table")
for row in cursor:
for elem in row:
maxVal = elem
is there a way to avoid those nested fors and get the value directly? I've tried
maxVal = cursor[0][0]
without any success.
I think you're looking for Cursor.fetchone() :
cursor.fetchone()[0]
Or you could write a wrapper function that, given SQL, returns a scalar result:
def get_scalar_result(conn, sql):
cursor=conn.cursor()
cursor.execute(sql)
return cursor.fetchone()[0]
I apologize for the possibly less than syntactically correct Python above, but I hope you get the idea.
Be careful, accepted answer might cause TypeError!
Due to fetchone() documentation:
Fetches the next row of a query result set, returning a single sequence, or None when no more data is available.
So with some SQL queries cursor.fetchone()[0] could turn into None[0] which leads to raising TypeError exception.
Better way to get first row or None is:
first_row = next(cursor, [None])[0]
If SQL query is empty, next will use default value [None] and get first element from that list without raising exceptions.
If you're not using pysqlite which has the built in cursor.fetchone
cursor.execute("select value from table order by value desc limit 1")
Sequence unpacking can be used to extract the scalar value from the result tuple.
By iterating over the cursor (or cursor.fetchall)if there are multiple rows:
for result, in cursor:
print(result)
Or using cursor.fetchone if there is a single row in the resultset:
result, = cur.fetchone()
print(result)
In both cases the trailing comma after result unpacks the element from the single-element tuple. This is the same as the more commonly seen
a, b = (1, 2)
except the tuples only have one element:
a, = (1,)
select count(*) from ... groupy by ... returns None instead of 0,
so fetchone()[0] would lead to an exception.
Therefore
def get_scalar_from_sql(sqlcur, sqlcmd):
# select count(*) from .... groupy by ... returns None instead of 0
sqlcur.execute(sqlcmd)
scalar = 0
tuple_or_None = sqlcur.fetchone()
if not tuple_or_None is None:
(scalar,) = tuple_or_None
return scalar
or you can try :
cursor.execute("SELECT * FROM table where name='martin'")
Is there an elegant way of getting a single result from an SQLite SELECT query when using Python?
for example:
conn = sqlite3.connect('db_path.db')
cursor=conn.cursor()
cursor.execute("SELECT MAX(value) FROM table")
for row in cursor:
for elem in row:
maxVal = elem
is there a way to avoid those nested fors and get the value directly? I've tried
maxVal = cursor[0][0]
without any success.
I think you're looking for Cursor.fetchone() :
cursor.fetchone()[0]
Or you could write a wrapper function that, given SQL, returns a scalar result:
def get_scalar_result(conn, sql):
cursor=conn.cursor()
cursor.execute(sql)
return cursor.fetchone()[0]
I apologize for the possibly less than syntactically correct Python above, but I hope you get the idea.
Be careful, accepted answer might cause TypeError!
Due to fetchone() documentation:
Fetches the next row of a query result set, returning a single sequence, or None when no more data is available.
So with some SQL queries cursor.fetchone()[0] could turn into None[0] which leads to raising TypeError exception.
Better way to get first row or None is:
first_row = next(cursor, [None])[0]
If SQL query is empty, next will use default value [None] and get first element from that list without raising exceptions.
If you're not using pysqlite which has the built in cursor.fetchone
cursor.execute("select value from table order by value desc limit 1")
Sequence unpacking can be used to extract the scalar value from the result tuple.
By iterating over the cursor (or cursor.fetchall)if there are multiple rows:
for result, in cursor:
print(result)
Or using cursor.fetchone if there is a single row in the resultset:
result, = cur.fetchone()
print(result)
In both cases the trailing comma after result unpacks the element from the single-element tuple. This is the same as the more commonly seen
a, b = (1, 2)
except the tuples only have one element:
a, = (1,)
select count(*) from ... groupy by ... returns None instead of 0,
so fetchone()[0] would lead to an exception.
Therefore
def get_scalar_from_sql(sqlcur, sqlcmd):
# select count(*) from .... groupy by ... returns None instead of 0
sqlcur.execute(sqlcmd)
scalar = 0
tuple_or_None = sqlcur.fetchone()
if not tuple_or_None is None:
(scalar,) = tuple_or_None
return scalar
or you can try :
cursor.execute("SELECT * FROM table where name='martin'")
I'm trying to populate a database with a single column with a list of strings (links). I scraped the list and I must modify every single link before sending it to the database. This is the code:
for event in events:
link_url = "https://www.website.com"+event+"#all"
c.execute("INSERT INTO table (links) VALUES(?)", link_url)
I can get it working if I modify the variables and send a tuple, like this:
for event in events:
link_url = "https://www.website.com"+event+"#all"
link = (link_url,)
c.execute("INSERT INTO seriea (links) VALUES(?)", link_url)
but I don't want to use this solution since I want to get a list of strings back out later:
c = connection.execute('select links from table')
list_of_urls = c.fetchall()
But this gives me a list of tuples.
This is the error I have: ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 80 supplied.
I think that's because the string characters are counted (actually more but I noticed that the number before "supplied" changes with the link fed)
I don't want to use this solution since I want to get a list of strings back out later:
c = connection.execute('select links from table')
list_of_urls = c.fetchall()
But this gives me a list of tuples.
The list of tuples you're getting when you do a select have nothing to do with the way you insert data. Remember, tables have two dimensions:
id
links
something
else
1
"foo"
"bar"
"baz"
2
"quux"
"herp"
"derp"
When you do a select you get a list that corresponds to the rows here. But each row has multiple fields: id, links, something, and else. Each tuple in the list contains the values for each of the fields in the table.
If you just want the URLs as a list of strings you can use a list comprehension or similar:
c = connection.execute('select links from table')
list_of_rows = c.fetchall()
list_of_strings = [row[0] for row in list_of_rows]
# ^ index of first element in
# ^^^ the tuple of values for each row
Note that you do have to provide a tuple or other sequence when you insert the data:
For the qmark style, parameters must be a sequence. For the named style, it can be either a sequence or dict instance. The length of the sequence must match the number of placeholders, or a ProgrammingError is raised. If a dict is given, it must contain keys for all named parameters.
You might be thinking of the tuple part of it the wrong way. You don't need to pass in a tuple of URLs, you need to pass in a tuple of parameters. You're not saying "the links column should contain this tuple" but rather "this tuple contains enough values to fill in the placeholders in this query".
I'd rewrite that like so:
for event in events:
link_url = "https://www.website.com"+event+"#all"
c.execute("INSERT INTO seriea (links) VALUES(?)", (link_url,))
This is so you can have multiple parameters, e.g.
c.execute(
"INSERT INTO seriea (links, some, other) VALUES(?, ?, ?)",
(link_url, foo, bar),
)
The current statement uses 1, and there are 80 supplied.
I think that's because the string characters are counted
Yes, that's most likely what's happening. c.execute() expects to receive a sequence, and strings are a sequence of characters.
I'm running SQL Query using python-Django RAW Query..!!
I'm using IN() function to pass my tuple in the query.
My code looks like this...
Here I am getting the list of dnc_domains and dnc_company from a json/function
dnc_domain_names = list(map(lambda x: get_domain_name(x), dnc_websites))
dnc_company_names = list(map(lambda l: l.lower(), list(filter(None, list(map(lambda x: x['company_name'], dnc_info))))))
QUERY:
select_query = """
select c.id
from (
select id, lower(company_name) as c_name,substring(website from '(?:.*://)?(?:www\.)?([^/]*)') as website_domain,
from contacts
where campaign_id = %s
) c
where
c.c_name IN %s
OR c.website_domain IN %s
"""
Executing Query:
with connection.cursor() as cursor:
cursor.execute(select_query, (campaign.id,tuple(dnc_company_names),tuple(dnc_domain_names))
matching_contact_ids = cursor.fetchall()
But, there is a case when any dnc_company_names or dnc_domain_name is empty [] then my Query throws an Error otherwise if there at least 1 element in any of them then it works fine.
SQL Error:
syntax error at or near ")"
LINE 5: WHERE id IN ()
^
So, help me to tackle this error. SQL should handle both empty or non empty tuples.
This is solved by providing NULL values in list
if not dnc_company_name:
dnc_company_name = [None]
finally, in my question, I am converting dnc_company_name into tuple.
and it solved my problem.
The right part of the IN must be a subquery returning exactly one column:
https://www.postgresql.org/docs/current/static/functions-subquery.html#FUNCTIONS-SUBQUERY-IN
I tried
SELECT *
FROM table_with_data
WHERE toto IN (SELECT * FROM empty);
which throws this error:
ERROR: subquery has too few columns
I guess you should provide something as IN (NULL) in the case your columns are strictly NOT NULL.
I want to add some data from variables into my database using sqlite library in python. I create a table and then run the sql statement. Here is my simple code:
import sqlite3
db = sqlite3.connect("dbse.sqlite")
cursor= db.cursor()
cursor.execute("CREATE TABLE Myt (Test TEXT)")
variable = ('aaa')
cursor.execute('INSERT INTO Myt VALUES (?)' , variable)
db.commit()
but after running the code, this error comes up:
cursor.execute('INSERT INTO Myt VALUES (?)' , variable)
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 3 supplied.
When I insert a variable that contains a one character value, it works well but when I use a variable with more than one character, it doesn't work.
I use python 3.2.3 .
Do you have an idea to solve it?
Your variable should be a tuple:
variable = ('aaa',) # Notice the comma
When creating a one-element tuple, you need to use comma at the end. As a side note, bear in mind that using the tuple() method won't give what you want:
>>> tuple('aaa')
('a', 'a', 'a')
>>> ('aaa',)
('aaa',)
cursor.execute() expects the second argument to be a sequence. Your variable is a string, which happens to be a sequence of length 3:
>>> len(variable)
3
>>> list(variable)
['a', 'a', 'a']
This is what causes your confusing error message; .execute sees a 3-element sequency and expected only 1. Pass it to .execute in a one-element tuple:
cursor.execute('INSERT INTO Myt VALUES (?)', (variable,))
Note the comma there.