I'm trying to insert several variables in a insert query on postgres using python. I can't wrap my head around how to use the string formatting.
For example, this works fine:
cursor.execute('''CREATE TABLE %s
(id SERIAL PRIMARY KEY,
sender varchar(255) not null,
receiver varchar(255) not null,
message varchar(255))''' %username)
as does this:
cursor.execute('''INSERT INTO test (sender, receiver, message)
VALUES(%s,%s,%s)''', (sender, receiver,message))
My problem is that I want to have the table name as a variable too. I have tried:
cursor.execute('''INSERT INTO %s (sender, receiver, message)
VALUES(%s,%s,%s)''' %username, (sender, receiver, message))
I get the following error:
TypeError: not enough arguments for format string
I get that I have to change the parentheses somehow, but I don't know how.
Thanks in advance.
EDIT:
Choose a different approach from this psycopg2 which worked perfectly.
You are passing the arguments in a wrong way. The arguments passed are causing you the trouble. Use format function instead of % as it is more sophisticated and readable.
"INSERT INTO {} (sender, receiver, message) VALUES({},{},{})".format("some", "world", "world","hello")
The output of the above:
'INSERT INTO some (sender, receiver, message) VALUES(world,world,hello)'
Use the high level sql module to avoid likely mistakes:
from psycopg2 import sql
query = sql.SQL('''
insert into {} (sender, receiver, message)
values (%s, %s, %s)
''').format(sql.Identifier(username))
cursor.execute (query, (sender, receiver, message))
Related
I wanted to write records in Postgres with a column type set as json. In Python version of JdbcIO, WriteToJdbc has a "statement" parameter which is suppose to override the generated insert statement. It seems that it is not working at all
| 'Write to jdbc' >> WriteToJdbc(
table_name="teacher",
driver_class_name='org.postgresql.Driver',
jdbc_url='jdbc:{}://{}:{}/{}'.format("postgresql", "your ip address", "5432", "postgres"),
username="postgres",
password="password"
statement = 'insert into researcher(id, first_name, last_name, total, payload) values (?, ?, ?, ?, cast(? as json))'
)
Am I missing something here ?
The Python version of JdbcIO is still experimental and not fully supported. There's an open Beam JIRA ticket for this feature: https://issues.apache.org/jira/browse/BEAM-10750
I am trying to create a system (with a discord bot, but that's not relevant to this) where it lists infractions of a user, like when it happened, where, why, etc. and I want a "date" datatype that logs the timestamp that it happened.
I tried having the DATE datatype to be "timestamp" (as well as "datetime", but the same error happens)
conn1 = apsw.Connection('./dbs/warns.db')
warns = conn1.cursor()
warns.execute(
"""
CREATE TABLE IF NOT EXISTS warns
(id INTEGER PRIMARY KEY AUTOINCREMENT,
date timestamp,
server string,
user string,
author string,
reason string)
"""
)
def add_warn(guild: str, user: str, author: str, reason):
now = datetime.datetime.utcnow()
with conn1:
warns.execute("INSERT INTO warns (date, server, user, author, reason) VALUES (?, ?, ?, ?, ?)", (now, guild, user, author, reason))
I end up getting a TypeError: Bad binding argument type supplied - argument #1: type datetime.datetime error
From the syntax of the create table statement (AUTOINCREMENT without an underscore) and the apsw tag, I suspect that you are using a SQLite database.
If you are looking to insert the current timestamp to a timestamp column, my first suggestion is to do it directly in SQL, instead of using a variable generated in python. In sqlite, CURRENT_TIMESTAP gives you the current date/time as a timestamp:
warns.execute(
"INSERT INTO warns (wdate, server, user, author, reason) VALUES (CURRENT_TIMESTAMP, ?, ?, ?, ?)",
(guild, user, author, reason)
)
Another option, that would furthermore simplify your code, is to set a default for the timestamp column when creating the table. Then, you can just ignore this column when inserting, and rest assured that the correct value will be assigned:
warns.execute(
"""
CREATE TABLE IF NOT EXISTS warns (
id INTEGER PRIMARY KEY AUTOINCREMENT,
wdate timestamp DEFAULT CURRENT_TIMESTAMP,
server string,
user string,
author string,
reason string
)
"""
)
def add_warn(guild: str, user: str, author: str, reason):
with conn1:
warns.execute(
"INSERT INTO warns (server, user, author, reason) VALUES (?, ?, ?, ?)",
(now, guild, user, author, reason)
)
Note: date is not a sensible column name, since it clashes with a datatype name. I renamed it wdate in all the above code.
I've tried to use couple of methods to insert data into mysql database but getting error in all:
In the first method:
sql = ('''Insert into lgemployees (EmpID,Name,Gender,DOB,Address,PhoneNumber,Email)
VALUES (%d,$s,$s,$s,$s,$d,$s)''', (eid, name, gen, dob, add, mob, email))
mycursor.execute(sql)
mycursor.commit()
Error in this approach:
'tuple' object has no attribute 'encode'
2nd method:
sql = "Insert into lgemployees (EmpID,Name,Gender,DOB,Address,PhoneNumber,Email) VALUES(?,?,?,?,?,?,?,)"
val = (eid, name, gen, dob, add, mob, email)
mycursor.execute(sql, val)
mycursor.commit()
Error in this approach :
"Not all parameters were used in the SQL statement")
mysql.connector.errors.ProgrammingError: Not all parameters were used in the SQL statement
I've troubleshooted a lot from my end but no luck. Can any one please help as where am I wrong or what else can be a good option to insert data into mysql from python.
I dont know where you error is at, but ive tested with this code and it works.
insert_tuple = (eid, name, gen, dob, add, mob, email)
sql = """INSERT INTO lgemployees (`EmpID `,
`Name`,`Gender`, `DOB`, `Address`, `PhoneNumber`, `Email`)
VALUES (%s,%s,%s,%s,%s,%s,%s)"""
mycursor = mySQLconnection.cursor()
mycursor.execute(sql, insert_tuple)
mySQLconnection.commit()
mycursor.close()
your code throws this because one of the parameters are empty or are in a format it cant read.
"Not all parameters were used in the SQL statement")
mysql.connector.errors.ProgrammingError: Not all parameters were used in the SQL statement
I am having a hard time understanding why psycopg2 has a problem with the word 'user'. I am trying to insert values into a table called user with the columns user_id, name, password. I am getting a programmingError: syntax error at or near "user". open_cursor() is a function used to open a cursor for database operations.
Here is my code:
query = """INSERT INTO user (name, password) VALUES (%s, %s);"""
data = ('psycouser', 'sha1$ba316b$52dd71da1e331247f0a7ab869e1b072210add9c1')
with open_cursor() as cursor:
cursor.execute(query, data)
print "Done."
because user is a part of sql language.
try taking it in dbl quotes:
query = 'INSERT INTO "user" (name, password) VALUES (%s, %s);'
This question already has answers here:
Python SQLite3 SQL Injection Vulnerable Code
(3 answers)
Closed 7 years ago.
I am supposed to look at this chunk of code and decide what parts could be vulnerable to SQL Injection, why and add fixes to them. I have been scanning the code looking for places that have too vague of parameters and such but i am having trouble finding places that could possibly be vulnerable. If anyone can just quickly scan through this code and point out any blatant vulnerabilities that would be great. The program really likes to give error messages when input is given with single quotes. This code is part of a program that tracks activities. There are 3 input fields, username, password and name of activity. Can post more code if anyone wants
#!/usr/bin/python3.4
import readline
import sqlite3
def audit(handle, event, obj=None):
"""Log an audit event."""
if handle[2] is None:
handle[2]=-1;
if obj==None:
handle[0].execute("insert into auditlog(userid, event)"
" values({0}, '{1}')".format(handle[2],event))
else:
handle[0].execute("insert into auditlog(userid, event, object)"
" values({0}, '{1}', {2})".format(str(handle[2]),
event, obj))
if handle[0].lastrowid is None:
"""On error, raise a SystemException"""
handle[1].commit()
handle[1].close()
raise SystemError("Error creating audit log entry.",
handle[2],event,obj)
handle[1].commit()
def register(cursor, connection, username, password):
"""Register a new user and return a connection to the database."""
cursor.execute("insert into user(username, password)"
" values('{0}', '{1}')".format(username, password))
userid=cursor.lastrowid;
if userid>0:
audit((cursor, connection, userid), "registered")
connection.commit()
print("Welcome, new user!")
return (cursor, connection, userid)
"""If the user could not be registered, raise a SystemError."""
audit((cursor, connection, 0),
"registeration error for {0}".format(username))
connection.commit()
connection.close()
raise SystemError("Unknown error registering user",username)
def connect(username, password):
"""Attempt to log in as the specified user."""
connection=sqlite3.connect('timelog.db')
cursor=connection.cursor()
"""The database is created if necessary."""
cursor.execute("create table if not exists user"
"( id integer primary key,"
" username varchar(50) unique not null,"
" password char(40) not null,"
" created datetime default CURRENT_TIMESTAMP,"
" modified datetime default CURRENT_TIMESTAMP"
")")
For example this statement is vulnerable to SQL injection:
cursor.execute("insert into user(username, password)"
" values('{0}', '{1}')".format(username, password))
I could for example enter the username:
test','secret');update user set password='';--
You should use parametrised queries instead. Using SQLLite you can call the sql like this instead:
cmd = "insert into user(username, password values(?, ?)"
curs.execute(cmd, (username, password))