I am now starting to use Python scripts to manage databases in association with MySQL.
I am facing an issue of Syntax error and can't seem to figure out why.
When i run the following code:
import MySQLdb
import time
conn = MySQLdb.connect("localhost","username","password","DataBase")
c= conn.cursor()
c.execute("SELECT * FROM table")
rows=c.fetchall()
for eachRow in rows:
print eachRow
I can get the rows in my table so everything is fine.
However when i use the INSERT statment as follows:
import MySQLdb
import time
conn = MySQLdb.connect("localhost","username","password","DataBase")
c= conn.cursor()
c.execute("INSERT INTO table(column1, column2) VALUES(23:EA:4A:7F:A1,Someone)")
c.execute("SELECT * FROM table")
rows=c.fetchall()
for eachRow in rows:
print eachRow
I get a syntax error
"near 'Column1,column2) Values(23:EA:4A:7F:A1,Someone)' at line 1"
I have checked the documentation and believe I am using the right syntax.
Have tried using multiple field types (varchar, text,...) and with semicolon at the end or not.
column1 is of type varchar(14)
column1 is of type text
Using mysql Ver 14.14 Distrib 5.5.57 for debian-linux-gnu (armv71)
Try it like this:
INSERT INTO "table" (column1, column2) VALUES('23:EA:4A:7F:A1','Someone')
table is a reserved keyword in SQL, so you should avoid naming your table table. It's like naming your kid Kid, oh wait.. But anyway if you are planning to use reserved keywords, you have to wrap them in double quotes.
As for the values, Someone is a string, so you should definitely wrap it in single quotes. I'm not sure about the type of 23:EA:4A:7F:A1, but I guess that's also a string, so better wrap that too.
Related
I don't know how to make this SQL Injection work in SQLite. I'm using a function in Python that connects to a database and inserts a string.
I have "database.db" that has two tables: "feedback" and "users".
The feedback table has 1 column: message.
The users table has 2 columns: username and password.
def send_feedback(feedback):
conn = sqlite3.connect("database.db")
curs = conn.cursor()
curs.execute("INSERT INTO feedback VALUES ('%s')" % (feedback))
print(curs.fetchall())
conn.close()
I know that the execute function allows me to make a single query to the database, so I can't use ";" to
make multiple queries.
What I have tried, is to make the string look like this:
a') SELECT password FROM users --
feedback = "INSERT INTO feedback VALUES ('a') SELECT password FROM users --')"
But this gives me the following error:
sqlite3.OperationalError: near "SELECT": syntax error
So I've tried to use the UNION command:
a') UNION SELECT password FROM users --
feedback = "INSERT INTO feedback VALUES ('a') UNION SELECT password FROM users --')"
This one works but the fetchall function returns an empty list.
Most SQL injections result in nothing useful to the perpetrator, just a syntax error.
For example, pass the string "I'm not satisfied" to this feedback function and the extra ' character would cause the quotes to be imbalanced, and this would result in an error, causing the INSERT to fail.
sqlite3.OperationalError: near "m": syntax error
That's technically SQL injection. The content interpolated into the query has affected the syntax of the SQL statement. That's all. It doesn't necessarily result in a successful "Mission: Impossible" kind of infiltration.
I can't think of a way to exploit the INSERT statement you show to make it do something clever, besides causing an error.
You can't change an INSERT into a SELECT that produces a result set. Even if you try to inject a semicolon followed by a second SQL query, you just get sqlite3.Warning: You can only execute one statement at a time
Your first try above resulted in a syntax error because you had both a VALUES clause and a SELECT as a source for the data to insert. You can use either one but not both in SQL syntax. See https://www.sqlite.org/lang_insert.html
You probably already know how to make the code safe, so unsafe content cannot even cause a syntax error. But I'll include it for other readers:
curs.execute("INSERT INTO feedback VALUES (?)", (feedback,))
You can do it, for example to get table name
a' || (SELECT tbl_name FROM sqlite_master WHERE type='table' and tbl_name NOT like 'sqlite_%'))-- -
I'm attempting to test adding data to a database via python. I have recognized that many people have issues with the "INSERT INTO" statement, and I have as well. I have received a range of errors, followed by changing the syntax multiple times, and then receiving new errors.
Currently, I have this as my statement:
cursor.execute("""INSERT INTO test (Column 1,Column 2) VALUES (%s,%s)"""% arg)
Where:
arg=("'5','2'")
Running the code outputs the standard 1064 MySQL error.
If someone can explain to me the standard syntax that would be great, because I can't seem to find it anywhere.
If fields or tables have spaces or other special characters in their names, they need delimited with `.
INSERT INTO test (`Column 1`,`Column 2`) ...
It is also a good habit to get into because it prevents hard to diagnose issues with using identifiers that might be confused with reserved or keywords.
It is never the best way to deal with these problems, but it always works to use the "".join(string)
arg=(5,2)
query = "".join(["INSERT INTO test (Column 1,Column 2) VALUES (" , str(arg[0]), ", ", str(arg[1]),")"])
query
Out[25]: 'INSERT INTO test (Column 1,Column 2) VALUES (5, 2)'
And then you execute() it. Cheers !
try this one out. I changed the % -> , and added the values at the end
cursor.execute("""INSERT INTO test (`Column 1`,`Column 2`) VALUES (%s,%s)""", (5,2))
I appreciate your answers but I found a solution. I ended up changing the rows in the DB to "Column1" instead of "Column 1", and this solved the issue.
import MySQLdb as mariadb
db = mariadb.connect(host="", user="root", passwd="", db="")
cursor = db.cursor()
sql = "INSERT INTO test (Column 1,Column 2) VALUES (%s,%s)"
#sqltime=datetime.now().strftime('%Y-%m-%d %H:%M:%S')
arg = ('5',"'2'") #argument input
try:
cursor.execute("""INSERT INTO test (Column1,Column2) VALUES (%s,%s)"""% arg)
db.commit()
except:
cursor.execute('show profiles')
for row in cursor:
print(row)
raise
db.close()
I have this simple code which I can't make work.
import sqlite3
conn = sqlite3.connect('db\\books')
c = conn.cursor()
col = []
title = input('title')
text = input('text')
tags = input('tags')
col.append(title)
col.append(text)
col.append(tags)
c.executescript("INSERT INTO books (title,text,tags) "
"VALUES (col[0],col[1],col[2])")
The db code (connection and normal insert) works but the problem rise when I want to do what you see above.
The goal I would like to achieve is to let the user insert the data into db (all strings). I don't know if this is the right way to do this...
How can I do this ?
Thanks
One option is to change your last line to:
c.execute("INSERT INTO books (title,text,tags) VALUES (?,?,?)", (col[0], col[1], col[2]))
And then commit and close the connection if you're done making changes:
conn.commit()
conn.close()
This line:
c.executescript("INSERT INTO books (title,text,tags) "
"VALUES (col[0],col[1],col[2])")
Is not a valid SQL. Now since c is defined as a cursor, you can run execute from it directly instead of executescript, which the latter is suppose to create a cursor from a connection and execute a SQL. Just replace that line with the following should work:
c.execute("INSERT INTO books (title,text,tags) "
"VALUES (?,?,?)", col)
The SQL above uses a "qmark style" placeholder, which takes actual value from the parameter list that follows it.
There are several similar issues like this scattered throughout the internet, but none that address my particular issue exactly.
Hopefully you folks can help!
Here is a small portion of my script:
import psycopg2 as p
import psycopg2.extras as e
# The 'AsIs' extension is here because I've attempted using it to fix my issue - with no luck unfortunately...
from psycopg2.extensions import AsIs
con = p.connect("dbname='my_db' user='user_name' host='123.45.67.89' port='5432'")
cur = con.cursor(cursor_factory=e.DictCursor)
query = "INSERT INTO happy_alerts_triggered (happy_affiliate_id, alert_format, alert_minutes, happy_client_internal_id, alert_triggered_date, alert_processed_date, alert_id, affiliate_name, client_name)
SELECT r.happy_affiliate_id, r.alert_format, r.alert_minutes, r.happy_client_internal_id, now() as alert_triggered_date, null as alert_processed_date, r.id, ha.happy_affiliate_description, hc.happy_client_description
FROM happy_alerts_config r
INNER JOIN happy_affiliates ha ON r.happy_affiliate_id = ha.id
INNER JOIN happy_clients hc ON r.happy_client_internal_id = hc.id
WHERE not exists
(SELECT 1 FROM "happyEvents" he
WHERE he."messageType" = r.alert_format
AND he."affiliateClient" = hc.happy_client_description
AND he."insertTime" > (now() - (r.alert_minutes * interval '1 minute')))"
cur.execute(query)
con.commit()
cur.close()
As you can see in the final SELECT statment, I am attempting to SELECT from a table with a name formatted in camelCase (which is not able to be changed :/).
I have tried the AsIs extension in a few different ways with no luck.
I have attempted parameterizing the camelCase variables, however this causes issues when attempting to do so with table names.
If I have researched correctly, parameterizing with 'AsIs' only fixes the camelCase issue when the parameters themselves are VALUES not tables/indexable items.
Lastly, the reason for this script is to UPDATE a table in my DB (with the query above), then use another query to return data from that table which will be used as information in an email generated within this same script.
If there are suggestions on how to run this query in other ways (i.e. within a bash script using psql commands, a node.js file, or any other file type that can be set to a crontab), I am open to suggestions. The query does not have to remain in this file, although I would like it to. (pgAgent is NOT a preferred method.)
I am running this on an Ubuntu 14.04 server.
Any help is appreciated! Thanks!
Your double quotes around your identifiers are not escaped. Use block quotes instead.
query = """
INSERT INTO happy_alerts_triggered (happy_affiliate_id, alert_format, alert_minutes, happy_client_internal_id, alert_triggered_date, alert_processed_date, alert_id, affiliate_name, client_name)
SELECT r.happy_affiliate_id, r.alert_format, r.alert_minutes, r.happy_client_internal_id, now() as alert_triggered_date, null as alert_processed_date, r.id, ha.happy_affiliate_description, hc.happy_client_description
FROM happy_alerts_config r
INNER JOIN happy_affiliates ha ON r.happy_affiliate_id = ha.id
INNER JOIN happy_clients hc ON r.happy_client_internal_id = hc.id
WHERE not exists
(SELECT 1 FROM "happyEvents" he
WHERE he."messageType" = r.alert_format
AND he."affiliateClient" = hc.happy_client_description
AND he."insertTime" > (now() - (r.alert_minutes * interval '1 minute')))
"""
cur.execute("select * from %s", (AsIs('"MyTable"'),))
I am using postgres with a psycopg2 python/flask web app.
I am having an encoding problem that I'm sure is something stupid I'm missing (I'm new to programming). The following statement works perfectly:
cur.execute("SELECT column_name FROM information_schema.columns where table_name = %s;", (tablename,))
I use fetchall() to create a list of column names in my table. However, another statement doesn't work:
cur.execute("ALTER TABLE %s ADD COLUMN %s varchar;", (tablename, col,))
Here is the error:
psycopg2.ProgrammingError
ProgrammingError: syntax error at or near "E'flatresponses_1'"
LINE 1: ALTER TABLE E'flatresponses_1' ADD COLUMN E'What was the bes...
('flatresponses_1' is the 'tablename', and 'What was the best...' is the start of 'col'.)
I did 'print cur.query' and here is the result:
>>> print cur.query
>>> ALTER TABLE E'flatresponses_1' ADD COLUMN E'What was the best part of your ENT clinic visit today? Why?' varchar;
I'm getting E' encoding in the second query but not the first. I've also tried str(tablename).
What am I missing?!
I ended up using the AsIs psycopg2 extension as described in this post. Worked like a charm!
Table and column names aren't text types, they are identifiers (type = name). They do not take escaped string literals and presumably you need something other than %s for your placeholder.
http://www.postgresql.org/docs/9.2/static/datatype-character.html