How to insert variable as text in Python? - python

Here is my code, it is to insert data into a database, , if i use numbers it works, but not with text, how do i solve it? I think i need to put «data» between two quotation marks ", how do i do that?
Thanks
def aggiungi():
print('funzione \'aggiungi\'')
conn = db.connect(NOMEDB)
print
"Database aperto con successo";
cognome, nome, indirizzo, mail, tel_fisso, tel_cell = input(
"Inserire cognome, nome, indirizzo, mail, tel_fisso, tel_cell (separati da virgola): ").split(",")
dati = cognome + "," + nome + "," + indirizzo + "," + mail + "," + tel_fisso + "," + tel_cell
conn.execute("INSERT INTO contatti (cognome, nome, "
f"indirizzo, mail, tel_fisso, tel_cell) VALUES ({dati})");
conn.commit()
print ("Records created successfully)")
conn.close()
return

You are missing a + to concatenate strings "INSERT INTO contatti (cognome, nome, " and f"indirizzo, mail, tel_fisso, tel_cell) VALUES ({dati})".
However, I should point out that this approach is highly dangerous for the security of your database, as it could be attacked with SQL injection. Basically, you are inserting a generic string into your query, without checking its content.
For instance, a malicious user could add this string for tel_cell:
3290000000);SELECT * FROM contatti --
This would cause your database to execute whatever query the malicious user likes.
Solution is to prepare your query. Further readings on this:
https://docs.python.org/3/library/sqlite3.html (see last example before "Module functions and constants")
https://www.websec.ca/kb/sql_injection

Related

Python: Search database using SQL

I am new to programming and working on a homework assignment. I am trying to search a database by comparing a user's search term with any matching values from a selected column. If a user searches "Smith" and clicks on the "Smith" radio button in my GUI, all the records containing "Smith" as its author should appear. I am able to print all the records in the database, but not the records that relate to my search.
db = None
colNum = None
def search_db(self):
global db
global colNum
self.searchTerm = self.searchvalue.get()
dbname = 'books.db'
if os.path.exists(dbname):
db = sqlite3.connect(dbname)
cursor = db.cursor()
sql = 'SELECT * FROM BOOKS'
cursor.execute(sql)
rows = cursor.fetchall()
for record in rows:
sql_search = 'SELECT * FROM BOOKS WHERE' + ' ' + record[colNum] + ' ' + 'LIKE "%' + ' ' + self.searchTerm + '%"'
cursor.execute(sql_search)
searched_rows = cursor.fetchall()
print(searched_rows)
The error I'm receiving is "sqlite3.OperationalError: no such column:"
There isn't enough information in your question to be sure, but this certainly is fishy:
sql_search = 'SELECT * FROM BOOKS WHERE' + ' ' + record[colNum] + ' ' + 'LIKE "%' + ' ' + self.searchTerm + '%"'
That record[colNum] is the value in a row for your column, not the name of the column. For example, if the column you wanted is Title, you're going to treat every title of every book as if it were a column name.
So, you end up running queries like this:
SELECT * FROM BOOKS WHERE The Meaning of Life: The Script like %Spam%
Even if that were valid SQL (quoted properly), The Meaning of Life: The Script is probably not a column in the BOOKS table.
Meanwhile, SELECT * returns the columns in an arbitrary order, so using colNum isn't really guaranteed to do anything useful. But, if you really want to do what you're trying to do, I think it's this:
sql = 'SELECT * FROM BOOKS'
cursor.execute(sql)
colName = cursor.description[colNum][0]
sql_search = 'SELECT * FROM BOOKS WHERE ' + colName + ' LIKE "%' + ' ' + self.searchTerm + '%"'
However, you really shouldn't be wanting to do that…
You need to get the column name from the fields of the table, or from somewhere else. Your query uses record[colNum] but record contains rows of data. Instead, to get the field names, use something like this:
fields = []
for field in cursor.description:
fields.append(field[0])
When you use rows = cursor.fetchall(), you are only getting data (and not the column headers).
It looks to me like you are just not forming the SQL correctly. Remember that whatever you put after the LIKE clause needs to be quoted. Your SQL needs to look like
SELECT * FROM BOOKS WHERE Title like '%Spam%'
So you need another set of single quotes in there so that's why I would use double quotes to surround your Python string:
sql_search = "SELECT * FROM BOOKS WHERE " + record[colNum] + " LIKE '%" + self.searchTerm + "%'"

pyodbc - Insert into MySQL not working

I am writing a script that reads data from one table, translates text in one of the columns into German using Google Translate API and load the data back into another table. Everything works except the last step which is the insert into the second table. I printed out the sql statement that is constructed in the script. If i hard code that output and execute the SQL it works just fine. But if i pass it as an argument it fails with the following error:
pyodbc.ProgrammingError: ('42000', "[42000] [MySQL][ODBC 5.2(w) Driver][mysqld-5.6.12-log]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 'Pipedly' at line 1 (1064) (SQLExecDirectW)")
The script is as follows (masked db credentials & API key). Please read the comments in the script to follow my description above. Thanks to everyone for the help
import pyodbc
import json
import collections
import urllib
import urlparse
import os
import time
import string
def insertData(databaseName, tableName, insertList):
insertStatement = "INSERT INTO " + databaseName + "." + tableName
for setLine in insertList:
insertStatement = insertStatement + setLine
return insertStatement
def createInsertFtpStatusList(customer, text, location, channel):
insertList = []
insertList.append("(`customer`, ")
insertList.append("`text`, ")
insertList.append("`location`, ")
insertList.append("`channel`) ")
insertList.append(" VALUES ('%s', '%s', '%s', '%s');" % (customer, text, location, channel))
return insertList
def url_fix(s, charset='utf-8'):
if isinstance(s, unicode):
s = s.encode(charset, 'ignore')
scheme, netloc, path, qs, anchor = urlparse.urlsplit(s)
path = urllib.quote(path, '/%')
qs = urllib.quote_plus(qs, ':&=')
return urlparse.urlunsplit((scheme, netloc, path, qs, anchor))
cnxn = pyodbc.connect("DSN=*mydsn*;UID=*username*; PWD=*password*")
cursor = cnxn.cursor()
cursor.execute("""
SELECT customer, replace(text,'#','') as text, location, channel FROM feeds.vw_pp;
""")
url1="https://www.googleapis.com/language/translate/v2?key=*myAPIkey*&q="
url2="&source=en&target=de"
rows = cursor.fetchall()
for field in rows:
text= field.text
text= text.replace(" ", "%20")
url=url1 + text + url2
url = url_fix(url)
result = urllib.urlopen(url)
data = json.load(result)
ts_text= data["data"]["translations"][0]["translatedText"]
ts_text= ts_text.replace("% 20% 20","")
ts_text= ts_text.replace(" 20%","")
ts_text= ts_text.replace("%","")
ts_text= ts_text.replace("20","")
ts_text= ts_text.replace(" "," ")
insertList= createInsertFtpStatusList(field.customer, ts_text, field.location, field.channel)
sqlStatement= '"' + insertData("feeds", "translated_pp", insertList) + '"'
print sqlStatement
# The sql statement that prints above:
# "INSERT INTO feeds.translated_pp(`customer`, `text`, `location`, `channel`) VALUES ('Pipedly', 'pipedly kommen und seine gehen bis fantastisch sein!', '', 'Facebook');"
# Success - If i copy paste the statement above and execute hardcoded as below, it works just fine.
cnxn.execute("INSERT INTO feeds.translated_pp(`customer`, `text`, `location`, `channel`) VALUES ('Pipedly', 'pipedly kommen und seine gehen bis fantastisch sein!', '', 'Facebook');"
)
# Fail - But if i pass the string as an argument it fails :(
cnxn.execute(sqlStatement)
Don't interpolate data into SQL statements yourself; leave proper escaping to the database adapter by using SQL parameters:
sqlStatement = "INSERT INTO feeds.translated_pp(`customer`, `text`, `location`, `channel`) VALUES (%s, %s, %s, %s)"
cnxn.execute(sqlStatement, (field.customer, ts_text, field.location, field.channel))
The database adapter then ensures that each value is properly escaped, including handling of embedded quotes in the value.

How to trim white space in MySQLdb using python

I have a web form taking user data and putting it into a mysql database. I need to trim leading and trailing blanks/spaces. I currently am utilizing the strip() method, but it only trims them for the fields, NOT for the mysql database.
My code is:
first_name = first_name.strip()
last_name = last_name.strip()
so on and so forth. It strips it perfectly fine for the webpage, but not when it is entered into the SQL database. The spaces still exist. How do I remove them?
EDIT:
db = MySQLdb.connect("localhost","user","pass","db_name")
cursor = db.cursor()
cursor.execute("Select * FROM registrants")
cursor.execute("INSERT INTO registrants VALUES( " + "'" + first_name + "'" + ", " + "'" + last_name + "'" + ");")
db.commit()
db.close()
It could be a scope issue.
If the stripping occurs in a different scope (ex: first_name is a global variable and the strip() occurs in a function) then you will not benefit from it in another scope (if the insert is happening in another function for example).
Have you tried this for a test:
cursor.execute("INSERT INTO registrants VALUES( " + "'" + first_name.strip() + "'" + ", " + "'" + last_name.strip() + "'" + ");")
btw, how do you know there's a space in the db? There could be an issue with the way the data is retrieved or displayed..
I think you should be passing the values into the INSERT differently
cursor.execute("INSERT INTO registrants (fname, lname) VALUES (%s, %s)", (first_name, last_name)
I'm not sure if that's where you're getting the whitespace, but it opens you up to sql injection so it's bad form to put the variables straight into the query.

Python - update database

How would I update an entry that is already in a database using sqlite3?
I've tried:
db_curs.execute("INSERT INTO `database` (cID) VALUES ('Updated')")
But this, of course, creates a new entry. I can obtain the (line(?)) number (of the entry) and what is the command to update the database rather than create a new entry?
EDIT:
Put a bit better, when I convert the SQL entry to a python list I get the following,
(1, u'GGS-04', u'John', u'Smith', 9, u'0')
I need to be able to add a digit to the last item. Here is what I have.
info = (1, u'GGS-04', u'John', u'Smith', 9, u'0')
for result in info:
ln = str(result[0])
ggs = str(result[1])
first_name = str(result[2])
last_name = str(result[3])
dob = str(result[4])
spend = str(result[5])
while True:
res = raw_input("Enter points to add: ")
try:
int(res)
break
except:
print "Please enter a number..."
pass
spend = str(int(spend) + int(res))
db_curs.execute("UPDATE `" + db_name + "` (cID, first_name, last_name, date_of_birth, spend) VALUES ('" + srce + "', '" + first_name + "', '" + last_name + "', '" + dob + "' WHERE '" + spend + "')")
db_connection.commit()
Could someone please explain the correct syntax for this command? It would be awesome if I could just update the "Spend" column than having to update them all from prefixed variables.
Thank you :)
This shall work:
db_curs.execute("UPDATE database SET spend =`" + spend + "` WHERE cID="+ cID)
See also SQL Update Syntax
Btw, "database" isn't a useful name for a database's table. What about "users" or "spendtime" or sth more descriptive?

cant resolve cryptic error in Python/sqlite program

Im running into this error that I can't work out
Im writing some code in Python using tkinter interface to transfer data from a text file to sqlite.
first, here is the relevant code:
def submit_data(self):
self.new_filename = self.file_entry.get()
self.new_tablename = self.table_entry.get()
self.new_fieldname = self.field_entry.get().split(',')
#print(self.new_fieldname)
self.create_new.destroy()
from sqlite3 import dbapi2 as sqlite
con = sqlite.connect(self.new_filename)
cur = con.cursor()
cur.execute('CREATE TABLE ' + self.new_tablename + '(id INTEGER PRIMARY KEY)')
for field in self.new_fieldname:
cur.execute('ALTER TABLE ' + self.new_tablename + ' ADD ' + field)
with open(self.filename, 'r', encoding='latin-1') as self.the_file:
status = True
#_keynumber=1
while status:
_row = self._next_line()
if _row:
_entry_list = _row.split(',')
# add space after text line comma for formatting
_entry_list = ', '.join(_entry_list)
#print(_entry_list)
#entries = {'row': _keynumber, 'entry': _entry_list}
#row_entry = "INSERT INTO " + self.new_tablename + " VALUES(" + _entry_list + ")"
cur.execute("INSERT INTO " + self.new_tablename + " VALUES(" + _entry_list + ")")
#_colrange = range(_colamount)
#_keynumber+=1
else:
status = False
con.commit()
At the cur.execute("INSERT INTO " ... line (about 6 lines up) I get this error:
** cur.execute("INSERT INTO " + self.new_tablename + " VALUES(" + _entry_list + ")")
sqlite3.OperationalError: near ".": syntax error**
I have changed this around in many different ways. At one time I had the whole "INSERT INTO ... VALUES ...." string as a variable and used
cur.execute(*variable*)
when I did it this way the error was the same except "OperationalError: near "." was "OperationalError: near "of" ... and there was no 'of' anywhere.
Im really confused and frustrated. Someone break this down for my please??
Thanks
F
the text file lines its reading are set up like this:
A Big Star In Hollywood,Sandra Dickinson
so I had figured that if I use .join() to put a space after the comma then the string would be the equivalent of two VALUES for the INSERT INTO statement.
Remove
_entry_list = ', '.join(_entry_list)
and use
cur.execute("INSERT INTO " + self.new_tablename + "(" + ",".join(self.new_fieldname) +") VALUES(" + ",".join(("?" for i in xrange(len(_entry_list)))) + ")", _entry_list)
This will parameterize your query and automatically quote all value in _entry_list.
You still have to manually quote self.new_tablename and self.new_fieldname. This should be before you use them in any sql statements.
You need to quote your strings.
As written, your SQL statement is:
INSERT INTO foo VALUES(Hello there, world, I am, unquoted, string, not good)
You should use:
INSERT INTO foo VALUES("Hello there","world","I am","quoted","string","hooray")
I suggest you do the following:
a) Instead of executing the statement, print it to the console. Change the line:
cur.execute("INSERT INTO " + self.new_tablename + ...)
to:
print "INSERT INTO " + self.new_tablename + ...
b) Run your program after making this change. Take a look at the SQL statements that you print to the console. Are they valid SQL statements? Start a SQLite command-line, and copy/paste the statements produced by your program. Does SQLite give any errors when you try to execute the pasted statements?

Categories

Resources