MySQL in Python complaining about placeholders - python

I've been trying to use python's MySQLdb to execute SQL on a MySQL Database from SSH on my webhost. This program i wrote (on a mac) should print a table, but it doesn't.
Here's my code:
import feedparser
import time
import MySQLdb
topnews = []
politics = []
# tech = []
sports = []
world = []
mostread = []
business = []
feeds = [topnews, mostread, politics, world, sports, business]
d = feedparser.parse('http://feeds.reuters.com/reuters/topNews/.rss') #Just to keep other cells functioning.
def refresh():
global d
global topnews
global politics
# global tech
global sports
global world
global mostread
global business
topnews = feedparser.parse('http://feeds.reuters.com/reuters/topNews/.rss')
politics = feedparser.parse('http://feeds.reuters.com/reuters/PoliticsNews/.rss')
# tech = feedparser.parse('http://feeds.reuters.com/reuters/technologyNews/.rss')
sports = feedparser.parse('http://feeds.reuters.com/reuters/sportsNews/.rss')
world = feedparser.parse('http://feeds.reuters.com/reuters/worldNews/.rss')
mostread = feedparser.parse('http://feeds.reuters.com/reuters/mostRead/.rss')
business = feedparser.parse('http://feeds.reuters.com/reuters/businessNews/.rss')
global feeds
global d
feeds = [topnews, mostread, politics, world, sports, business]
d = feedparser.parse('http://feeds.reuters.com/reuters/topNews/.rss') #Just to keep other cells functioning.
refresh()
def summarize(feed, num): #Define a method called "summarize"
summary = feed['entries'][num]['summary_detail']['value'] #Make a variable equal to the summary
newsummary = "" #The summary we are trying to make, which is empty so far.
for char in summary: #Keep running the following code as many times as there are characters in summary.
if char == "<": #If the current character is a less than sign,
return newsummary #We can finally show our new summary! Mission Accomplished!!!!!!!
else: #Otherwise,
newsummary = newsummary + char #Add the current character to our new summary.
return newsummary.replace(firstword(summarize(topnews, 0)), "").replace("- ", "")
def identify(feed):
term = feed['entries'][0]['tags'][0]['term']
if term == mostread['entries'][0]['tags'][0]['term']:
return "Most Read"
elif term == topnews['entries'][0]['tags'][0]['term']:
return "Top News"
elif term == politics['entries'][0]['tags'][0]['term']:
return "Politics"
# elif term == tech['entries'][0]['tags'][0]['term']:
# return "Tech"
elif term == sports['entries'][0]['tags'][0]['term']:
return "Sports"
elif term == world['entries'][0]['tags'][0]['term']:
return "World"
elif term == business['entries'][0]['tags'][0]['term']:
return "Business"
def firstword(string):
word = ""
for char in string:
if char == "-":
return word
else:
word = word + char
def cat(feed, num):
spec = identify(feed)
if firstword(summarize(feed, num)) != "(Reuters)":
spec = spec + ", " + firstword(summarize(feed, num))
return spec#.replace("(Reuters)")
def link(feed, num):
return d['entries'][num]['link'] #Gives the link to the specified number article.
def date(feed):
return d['entries'][0]['published']
############################################################################################################################################# Coding Rocks!
# Open database connection
db = MySQLdb.connect("localhost","myusername","mypassword","databasename") # Of course, I included the actual values here.
# prepare a cursor object using cursor() method
cursor = db.cursor()
# Prepare SQL query to INSERT a record into the database.
cursor.execute('''
DROP TABLE IF EXISTS news;
''')
cursor.execute('''
CREATE TABLE news
(
id int unsigned NOT NULL auto_increment,
headline varchar(250) NOT NULL,
summary varchar(5000) NOT NULL,
date varchar(50) NOT NULL,
link varchar(2500) NOT NULL,
imagelink varchar(2500) NOT NULL,
category varchar(50) NOT NULL,
PRIMARY KEY (id)
);
''')
for numelem in range( 0, len(mostread['entries']) - 1):
sqlstring = '''
insert into news (headline, summary, date, link, imagelink, category)
values ("NULLFORNOW", %s, %s, %s, "NULLFORNOW", %s);
''' % ( summarize(mostread, numelem), date(mostread), link(mostread, numelem), cat(mostread, numelem) )
cursor.execute(sqlstring)
# cursor.execute('''
# SELECT * FROM news;
# ''')
# results = cursor.fetchall()
# disconnect from server
db.close()
print "Whoopdeedoo! Program done. :)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
This throws an error:
Traceback (most recent call last):
File "feedparser.py", line 132, in <module>
cursor.execute(sqlstring)
File "/usr/lib64/python2.6/site-packages/MySQLdb/cursors.py", line 173, in execute
self.errorhandler(self, exc, value)
File "/usr/lib64/python2.6/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Brazil (Reuters) - Brazilian presidential candidate Eduardo Campos was killed in' at line 2")
I am sincerely sorry for the poor quality of this question; I am just too sick of this error, and I really don't know where the error is.
Please tell me where the problem is, and, of course, how to fix it.
Thank you, CJ
EDIT:
I tried #metatoaster's suggestion, and now I am getting the error:
feedparser.py:137: Warning: Data truncated for column 'category' at row 1 cursor.execute(sqlstring, data)

If you refer to the documentation you will see that the execute method calls for a separate data argument, not format the entire SQL statement using % as that will introduce errors into the SQL statement. You can try this yourself by printing the sqlstring you generated and send it to MySQL and you will get that same error. Do this instead, as per the documentation.
data = (
summarize(mostread, numelem),
date(mostread),
link(mostread, numelem),
cat(mostread, numelem),
)
cursor.execute(sqlstring, data)
As for your second error, it means that the input data exceeded your length of the field (which you defined to a max of 50 characters). Again print out what you actually tried to input as category to see that it probably is too long of a string, or the wrong string even.

Related

pymysql error: 'str' object has no attribute 'nextset'

I am running into an issue building a random project for myself. I am trying to record entries into a mysql database that the user types in. I am storing them in a dictionary. The error message is
while self.nextset():
AttributeError: 'str' object has no attribute 'nextset'
I have googled and searched for this issue, but I only find issues kind of like it but not the same error.
My table headers in mysql db match the dictionary keys. I do realize I have issues with selection (2) but my error and what I am troubleshooting now is just when I select option (1).
import mysql
import pymysql
from datetime import date, datetime, timedelta
cursor = pymysql.cursors.Cursor
# Function for adding a new entry
def new_entry(name, date, task, time, notes):
# Build dictionary with new entry information
myDict = {
'Employee': name, # Name of employee
'Date': date, # Date of worked task
'Task': task, # Title of Task
'Time': time, # Time spent on task
'Notes': notes # Notes on the task
}
table = ('timesheet')
placeholders = ', '.join(['%s'] * len(myDict))
columns = ', '.join(myDict.keys())
sql = "INSERT INTO %s ( %s ) VALUES ( %s )" % (table, columns,
placeholders)
pymysql.cursors.Cursor.execute(sql, myDict)
#list all entries for a particular employee
def previous_entries(emp_name):
pymysql.cursors.Cursor.execute(
"SELECT * from user_data WHERE Name = %s", (emp_name,))
#list all entries that match a date or search term
#def search_entries():
# return null
#Print a report of this information to the screen, including the date, title
#of task, time spent, employee, and general notes.
if __name__ == '__main__':
#cnx = mysql.connect(user='root', database='me10_mig')
cnx = pymysql.connect(user='root', password='password',
database='me10_mig')
print("Please enter (1), (2), or (3)")
begin = input("Would you like to (1) enter a new entry or (2) display
all
previous entries or (3) display entries that match a date or search
term? ")
if begin == '1':
name = input("Your Name: ")
date = input("Date of Time Worked: ")
task = input("Title of Task: ")
time = input("Time Spent on Task: ")
notes = input("Notes on Time Worked: ")
new_entry(name, date, task, time, notes)
if begin == '2':
name = input("What is the employee name: ")
previous_entries(name)
#if begin == '3':
The error I get says:
Traceback (most recent call last):
File "C:/Users/a089673/Desktop/Python/TeamTreeHouse/Part 4/timesheet.py", line 61, in <module>
new_entry(name, date, task, time, notes)
File "C:/Users/a089673/Desktop/Python/TeamTreeHouse/Part 4/timesheet.py", line 27, in new_entry
pymysql.cursors.Cursor.execute(sql, myDict)
File "C:\Users\a089673\AppData\Roaming\Python\Python36\site packages\pymysql\cursors.py", line 165, in execute
while self.nextset():
AttributeError: 'str' object has no attribute 'nextset'
Process finished with exit code 1
Any suggestions?
I suspect your might stem from using a dict to hold the arguments to .execute(), but not using named string patterns in the SQL statement.
The docs suggest using %s when passing a list or tuple, but rather use %(name)s when passing a dict.
I suggest you try this code:
def new_entry(name, date, task, time, notes):
# Build dictionary with new entry information
myDict = {
'Employee': name, # Name of employee
'Date': date, # Date of worked task
'Task': task, # Title of Task
'Time': time, # Time spent on task
'Notes': notes # Notes on the task
}
table = ('timesheet')
column_list = []
placeholder_list = []
for k in myDict:
column_list.append(k)
placeholder_list.append('%(' + k + ')s')
sql = "INSERT INTO %s ( %s ) VALUES ( %s )" % (
table,
', '.join(column_list),
', '.join(placeholder_list))
pymysql.cursors.Cursor.execute(sql, myDict)
This will also ensure that the column names and the placeholders are in the same order. Your original code did not consider that (remember, iterating over dicts multimple time is not garanteed to give the same order each time).
I totally overlooked the part where you establish a connection to the database. You need to pass that connection as a parameter to new_entry() and use it.
Try this:
def new_entry(cnx, name, date, task, time, notes):
sql = "INSERT INTO timesheet (Employee, Date, Task, Time, Notes) VALUES (%s, %s, %s, %s, %s)"
values = (name, date, task, time, notes)
with cnx.cursor() as cursor:
cursor.execute(sql, values)
cnx = pymysql.connect(user='root', password='password', database='me10_mig')
new_entry(cnx, ...)

Sqlite select column text with multple words

So i have a table with all of the products and their language availability. I want to write a function to check the language availability when input the product name and language.
My code is as follow:
"CREATE TABLE t (Language,French, Italian, German, Spanish, Japanese, Korean, 'Traditional Chinese');")
//insert data to table t
def checkLanguageAvailability(self, product, language):
query = "SELECT " + language + " FROM t WHERE Language = '" + product + "'"
cur = self.df.cursor()
cur.execute(query)
# print cur.fetchall()
res = cur.fetchall()
if res[0][0] == '':
return False
elif int(float(res[0][0])) != 0:
return True
so when i test it , it all works fine with one-word text
checkLanguageAvailability("productname",'French')) --> True
But with multiple-word text
checkLanguageAvailability("productname",'Traditional Chinese'))
it raise this error :
cur.execute(query)
sqlite3.OperationalError: no such column: Traditional
It seems that instead of taking the whole string 'Traditional Chinese' as a parameter, it just take 'traditional' and there is no column have this name in table
I disagree with your table structure and also with your code. Adding a new column for each language is costly and maximally inflexible. This approach requires a major schema change each time you decide to support a new language. In addition, your current concatenated query string is prone to SQL injection. Beyond this, you should generally not make the column names in a query as parameters. When you find yourself doing this, it might indicate bad design or a hack. Instead, I propose the following table:
CREATE TABLE t (language TEXT, product TEXT)
This design represents the presence of a given product and language as a single row. Hence, if we find a record entry for a given product and language then we know it is present.
Try using code something like the following:
def checkLanguageAvailability(self, product, language):
cur = self.df.cursor()
cmd = cur.execute("SELECT 1 FROM t WHERE product = ? AND language = ?", (product, language))
res = cur.fetchall()
cnt = len(res)
if cnt == 0
return False
else
return True
Use LIKE:
def checkLanguageAvailability(self, product, language):
query = "SELECT " + language + " FROM t WHERE Language LIKE '%" + product + "%'"
cur = self.df.cursor()
cur.execute(query)
# print cur.fetchall()
res = cur.fetchall()
if res[0][0] == '':
return False
elif int(float(res[0][0])) != 0:
return True
And is this query accepting any external input? Because if so, you should use prepared statements.

return a list of tuples from database records with python and postgresql

Hello I'm having a hard time trying to make this function in which I have to:
"""Returns a list of the players and their win records, sorted by wins.
The first entry in the list should be the player in first place, or a player
tied for first place if there is currently a tie.
Returns:
A list of tuples, each of which contains (id, name, wins, matches):
id: the player's unique id (assigned by the database)
name: the player's full name (as registered)
wins: the number of matches the player has won
matches: the number of matches the player has played
"""
currently I have this function to try solve that:
def playerStandings():
conn = connect()
c = conn.cursor()
c.execute("SELECT id, name \
FROM players LEFT JOIN matches \
ON players.id = matches.id_winner \
ORDER BY players.id")
result = c.fetchall()
conn.close()
return result
and when I run the code I get this error msg:
Traceback (most recent call last): File "tournament_test.py", line
152, in
testStandingsBeforeMatches() File "tournament_test.py", line 61, in testStandingsBeforeMatches
raise ValueError("Each playerStandings row should have four columns.") ValueError: Each playerStandings row should have four
columns.
line 152 in tournament_test.py is:
testStandingsBeforeMatches()
and line 61 is:
if len(standings[0]) != 4:
raise ValueError("Each playerStandings row should have four columns.")
[(id1, name1, wins1, matches1), (id2, name2, wins2, matches2)] = standings
and finally variable "standings" is a call to my function playerStandings() in line 54
standings = playerStandings()
this is my sql script to create the database and the tables:
CREATE DATABASE tournament;
\c tournament;
CREATE TABLE players (id SERIAL, name TEXT, PRIMARY KEY (id));
CREATE TABLE matches (
id_match SERIAL,
id_winner SERIAL REFERENCES players(id),
id_looser SERIAL REFERENCES players(id),
PRIMARY KEY (id_match)
);
what can I do to solve this? I'm really new with python so I don't understand it very well
I don't use postgresql, the code may not use in your routine directly, so you need modify on this basis to let it work. I just give you some hints to let you know how to fix the problem.
def playerStandings():
conn = connect()
c = conn.cursor()
c.execute("SELECT id, name \
FROM players LEFT JOIN matches \
ON players.id = matches.id_winner \
ORDER BY players.id")
result = c.fetchall()#get all id and name, I don't know the type of result, assume its a list of dicts.
for row in result:
#sql to get wins
c.execute("SELECT COUNT(*) AS wins FROM WHERE id_winner = row['id']");
win_data = c.fetch()
row['wins'] = win_data['wins']
#sql to get matches
c.execute("SELECT COUNT(*) AS matches FROM WHERE id_winner = row['id']" OR id_looser = row['id'])
match_data = c.fetch()
row['matches'] = match_data['matches']
conn.close()
return result

Operational Error in SQL

I'm running sqlite3 and I cannot, for the life of me work out what is going wrong in my code. Baring in mind that it doesn't crash when creating other tables that come before it in the database. Part of me suspects it may be a case of capitalisation somewhere on an SQL statement but it was working normally a few days ago.
Create Table function
def create_table(db_name,table_name,sql):
with sqlite3.connect(db_name) as db:
cursor = db.cursor()
cursor.execute("select name from sqlite_master where name=?",(table_name,))
result = cursor.fetchall()
keep_table = True
if len(result) == 1:
response = input("The table {0} already exists, do you wish to recreate (y/n): ".format(table_name)) #option to recreate the database
if response == 'y':
keep_table = False
print("The {0} table will be recreated - all existing data will be lost".format(table_name))
cursor.execute("drop table if exists {0}".format(table_name))
db.commit()
elif response == 'n':
print("The existing table was kept")
else:
print("Incorrect input, please try again.") #validation measure
if len(result) == 1:
response = input("The table {0} already exists, do you wish to recreate (y/n): ".format(table_name))
if response == 'y':
keep_table = False
print("The {0} table will be recreated - all existing data will be lost".format(table_name))
cursor.execute("drop table if exists {0}".format(table_name))
db.commit()
else:
keep_table = False
if not keep_table:
cursor.execute(sql)
db.commit()
Tables that are causing the problem?
def create_customer_table():
sql = """create table Customer
(CustomerID integer,
FirstName text,
LastName text,
Street text,
Town text,
Postcode text,
TelephoneNumber text,
EmailAddress text
primary key(CustomerID))"""
create_table(db_name, "Customer", sql)
*ignore the fact it isn't indented, it is on my program.
def create_customer_order_table():
sql = """create table CustomerOrder
(OrderID integer,
CustomerID integer,
Date date,
Time integer
primary key(OrderID)
foreign key(CustomerID) references Customer(CustomerID))"""
create_table(db_name, "CustomerOrder", sql)
Here is the error I receive:
Traceback (most recent call last):
File "/Users/X/Downloads/manage_table_March_2015.py", line 110, in <module>
create_customer_table()
File "/Users/X/Downloads/manage_table_March_2015.py", line 78, in create_customer_table
create_table(db_name, "Customer", sql)
File "/Users/X/Downloads/manage_table_March_2015.py", line 33, in create_table
cursor.execute(sql)
ysqlite3.OperationalError: near "(": syntax error

Why doesn't this work (sqlite, python)

I tried to do this in the interpreter and I can get it to work but inside my function it doesn't
What I'm trying to do:
cursor = dbconnect.cursor()
cursor.execute("""SELECT * FROM credits WHERE phone = ?""",(phone,))
data = cursor.fetchone()
firstname = data[1] #the db is set as firstname in position 1 after the id(primekey)
I'm actually extracting all the data using this method just with different variables
The Error I get when I do it inside the function:
firstname = data[1]
TypeError: 'NoneType' object is not subscriptable
As a note: I put a print statement after the data object to see what it was returning, in the interpreter it returns the tuple i'm searching for, inside the function it's returning
'None'
FULL CODE:
def FindByPhone(self,phone):
'''Find Credit by phone number ONLY'''
dbconnect = sqlite3.connect(self.dbname)
cursor = dbconnect.cursor()
cursor.execute("""SELECT * FROM credits WHERE phone = ?""",(phone,))
data = cursor.fetchone()
first = data[1]
last = data[2]
phone = data[3]
credit = data[4]
cid = data[0]
self.SetVariables(first,last,phone,credit,cid)
cursor.close()
dbconnect.close()
return
I think the problem is that your function doesn't check if there was a matching row in the database. you will get this error if no row is being returned:
#!/usr/bin/python
try:
import sqlite3
except:
from pysqlite2 import dbapi2 as sqlite3
#prepare testcase
db="/tmp/soverflow.sqlite"
dbconnect = sqlite3.connect(db)
c = dbconnect.cursor()
c.execute("""create table credits
(id int not null primary key, firstname varchar(50), phone varchar(30),amount int not null)""")
c.execute("""INSERT INTO credits (id,firstname,phone,amount) VALUES (1,'guybrush','123-456',24)""")
c.execute("""INSERT INTO credits (id,firstname, phone,amount) VALUES (2,'elaine','1337-1337',18)""")
dbconnect.commit()
c.close()
def print_firstname(phone):
cursor = dbconnect.cursor()
cursor.execute("""SELECT * FROM credits WHERE phone = ?""",(phone,))
data = cursor.fetchone()
firstname = data[1]
cursor.close() # cleanup
print firstname
print "testing existing row"
print_firstname('1337-1337')
print "testing missing row"
print_firstname('nothere')
=>
./soverflow_sqlite.py
testing existing row
elaine
testing missing row
Traceback (most recent call last):
File "./soverflow_sqlite.py", line 31, in <module>
print_firstname('not-in-db')
File "./soverflow_sqlite.py", line 23, in print_firstname
firstname = data[1]
TypeError: 'NoneType' object is not subscriptable
Solution:
Add a check if there was a row returned from your query

Categories