How to create a database with psycopg2 using execute() second argument? - python

I'm trying to create a database with the name a user will provide. As far as I know the correct way is to use the second argument of execute().
So I did as follows:
import psycopg2
conn = psycopg2.connect(host="...", dbname="...",
user="...", password="...", port='...')
cursor = conn.cursor()
query = ''' CREATE DATABASE %s ;'''
name = 'stackoverflow_example_db'
conn.autocommit = True
cursor.execute(query, (name,))
cursor.close()
conn.close()
And I got this error:
psycopg2.errors.SyntaxError: syntax error at or near "'stackoverflow_example_db'"
LINE 1: CREATE DATABASE 'stackoverflow_example_db' ;
I need to do this statement avoiding SQL injection, so using the second argument is a must.

You can't pass values as second argument of execute(), if the statement is a CREATE DATABASE one.
As pointed out by unutbu one way to approach this is using the psycopg2.sql submodule and use identifiers to build the statement avoiding SQL injection.
The code:
import psycopg2
from psycopg2 import sql
conn = psycopg2.connect(host="...", dbname="...",
user="...", password="...", port='...')
cursor = conn.cursor()
query = ''' CREATE DATABASE {} ;'''
name = 'stackoverflow_example_db'
conn.autocommit = True
cursor.execute(sql.SQL(query).format(
sql.Identifier(name)))
cursor.close()
conn.close()
Other aditional observations:
format() do not work with %s, use {} instead
Autocommit mode is a must for this statement to work
The specified connection user needs creation privileges

Related

how to insert string into query in python pymysql

I have a following query:
cursor = connection.cursor()
query = """
SELECT *
FROM `my_database`.table_a
"""
result = cursor.execute(query)
which works as expected. But I need to change my_database in cursor.execute. I try:
cursor = connection.cursor()
query = """
SELECT *
FROM %s.table_a
"""
result = cursor.execute(query, ("my_database",))
which gives an error pymysql.err.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 ''my_database'.table_a at line 2")
how can I insert database name in cursor.execute please?
It is not possible to bind a database name (or any other database object name) using a placeholder in a prepared statement. This would be, among other problems, a security risk. However, you might be able to use an f-string here instead:
cursor = connection.cursor()
db_name = "my_database"
query = f"""
SELECT *
FROM {db_name}.table_a
"""
result = cursor.execute(query)
It should also be mentioned that the above is only SQL injection safe if you are certain that the database name is not coming from outside your own application.

Inserting Query Results into Singlestore Table with Python and Sqlalchemy

I have parameterized queries with f strings such that the queries will select some data from a series of tables and joins, and I want to insert the resulting set of data into another pre-created table (tables been designed to house these results).
Python executes the code but the query results never show up in my table.
Assuming target_table is already created in singlestore database:
qry_load = 'insert into target_table select * from some_tables'
conn = engine.connect()
trans = conn.begin()
try:
conn.execute(qry_load)
trans.commit()
except:
trans.rollback()
raise
The code executes and acts as if all is ok, but the data never shows up in the target table.
How do I see what singlestore is passing back to better debug what is happening within the database?
Just replace begin() with cursor() function:
conn = engine.connect()
trans = conn.cursor()
If not resolved
1- Verify structure of source and destination tables if they are same or not.
2- remove try ,except and rollback() block so you can know the actual error.
Ex.
qry_load = 'insert into target_table select * from some_tables'
conn = engine.connect()
trans = conn.cursor()
conn.execute(qry_load)
trans.commit()

How do you bind parameters in the Python pymysql library?

As described here https://peps.python.org/pep-0249/#paramstyle, in MySql it should be possible to bind parameters using the keyword syntax, like this: email=:email. This is different from using an unnamed placehoder syntax, like email=%s.
But this code doesn't work:
import pymysql
con = pymysql.connect(host='localhost', user='root', password=pw, database=db_name, port=4306)
stmt = "INSERT INTO `test_table` (`email`, `password`) VALUES (:email, :password)"
with con.cursor() as cursor:
# Create a new record
cursor.execute(stmt, {'email': "FOO", 'password': "BAR"})
con.commit()
Not even adding
pymysql.paramstyle = 'named'
at the top.
The error is
(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 ':email, password=:password)' at line 1")
but unfortunately, I'm not able to find such documentation (This page doesn't document anything.. https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html)
What is the right syntax?
Thanks!
https://pymysql.readthedocs.io/en/latest/modules/cursors.html says:
If args is a list or tuple, %s can be used as a placeholder in the query. If args is a dict, %(name)s can be used as a placeholder in the query.
Even though the :name placeholder format is in the PEP you reference, the pymysql package does not seem to implement that format.
This should work:
stmt = "INSERT INTO `test_table` (`email`, `password`) VALUES (%(email)s, %(password)s)"
with con.cursor() as cursor:
# Create a new record
cursor.execute(stmt, {'email': "FOO", 'password': "BAR"})

Can python cursor.execute accept multiple queries in one go?

Can the cursor.execute call below execute multiple SQL queries in one go?
cursor.execute("use testdb;CREATE USER MyLogin")
I don't have python setup yet but want to know if above form is supported by cursor.execute?
import pyodbc
# Some other example server values are
# server = 'localhost\sqlexpress' # for a named instance
# server = 'myserver,port' # to specify an alternate port
server = 'tcp:myserver.database.windows.net'
database = 'mydb'
username = 'myusername'
password = 'mypassword'
cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)
cursor = cnxn.cursor()
#Sample select query
cursor.execute("SELECT ##version;")
row = cursor.fetchone()
while row:
print(row[0])
row = cursor.fetchone()
Multiple SQL statements in a single string is often referred to as an "anonymous code block".
There is nothing in pyodbc (or pypyodbc) to prevent you from passing a string containing an anonymous code block to the Cursor.execute() method. They simply pass the string to the ODBC Driver Manager (DM) which in turn passes it to the ODBC Driver.
However, not all ODBC drivers accept anonymous code blocks by default. Some databases default to allowing only a single SQL statement per .execute() to protect us from SQL injection issues.
For example, MySQL/Connector ODBC defaults MULTI_STATEMENTS to 0 (off) so if you want to run an anonymous code block you will have to include MULTI_STATEMENTS=1 in your connection string.
Note also that changing the current database by including a USE … statement in an anonymous code block can sometimes cause problems because the database context changes in the middle of a transaction. It is often better to execute a USE … statement by itself and then continue executing other SQL statements.
Yes, it is possible.
operation = 'SELECT 1; INSERT INTO t1 VALUES (); SELECT 2'
for result in cursor.execute(operation, multi=True):
But it is not a comprehensive solution. For example, in queries with two selections, you have problems.
Consider that two types of answers must be fetch all in the cursor!
So the best solution is to break the query to sub queries and do your work step by step.
for example :
s = "USE some_db; SELECT * FROM some_table;"
s = filter(None, s.split(';'))
for i in s:
cur.execute(i.strip() + ';')
in the pyodbc documentation should give you the example your looking for. more over in the GitHub wiki: https://github.com/mkleehammer/pyodbc/wiki/Objects#cursors
you can see an example here:
cnxn = pyodbc.connect(...)
cursor = cnxn.cursor()
cursor.execute("""
select user_id, last_logon
from users
where last_logon > ?
and user_type <> 'admin'
""", twoweeks)
rows = cursor.fetchall()
for row in rows:
print('user %s logged on at %s' % (row.user_id, row.last_logon))
from this example and exploring the code, I would say your next step is testing a multi cursor.execute("<your_sql_Querie>").
if this test works, maybe try and create a CLASS then create instances of that class for each query you want to run.
This would be the basic evolution of a developers effort of reproducing documentation...hope this helps you :)
Yes, you can results for multiple queries by using the nextset() method...
query = "select * from Table1; select * from Table2"
cursor = connection.cursor()
cursor.execute(query)
table1 = cursor.fetchall()
cursor.nextset()
table2 = cursor.fetchall()
The code explains it... cursors return result "sets", which you can move between using the nextset() method.

Prepared Statements in MySQL - Trying to remove a row results in ProgrammingError

I want to use prepared statements to remove a row from a table, but it results in an error: mysql.connector.errors.ProgrammingError: Not all parameters were used in the SQL statement
Relevant code:
db = mysql.connector.connect(
host='localhost',
user='user',
database='web_board',
password='password',
auth_plugin='mysql_native_password'
)
crs = db.cursor()
# construct the query and remove post from the database
query = 'DELETE FROM posts WHERE postid=%s'
crs.execute(query, tuple(request.data))
db.commit()
crs.close()
db.close()
request.data looks like this: b'9b23f24e-ff4d-4113-85ae-ff8a4a5de3be'
As the documentation states, to use prepared statements, you should instantiate your cursor with following config:
crs = db.cursor(prepared=True)
Prepared statements executed with MySQLCursorPrepared can use the format (%s) or qmark (?) parameterization style.

Categories