psycopg2, SELECT, and schemas - python

I'm trying to do a simple select statement on a table that's part of the "dam_vector" schema. The error I get is:
psycopg2.ProgrammingError: relation
"dam_vector.parcels_full" does not
exist LINE 1: SELECT * FROM
"dam_vector.parcels_full"
I can't figure this out and know I'm missing something obvious. Any help you can provide would be great.
Here's the code I'm using. db is a connection string that successfully connects to the database.
cur = db.cursor()
query = 'SELECT * FROM "dam_vector.parcels_full"'
cur.execute(query)
results = cur.fetchall()
and when that failed and after I did some research on Google I tried this. Same error.
cur.execute("SET search_path TO dam_vector,public")
db.commit()
cur = db.cursor()
query = 'SELECT * FROM "parcels_full"'
cur.execute(query)
results = cur.fetchall()

Double quotes makes whatever is in them an identifier, so query
SELECT * FROM "dam_vector.parcels_full";
hits table dam_vector.parcels_full (period interpreted as part of table name) from schama public (or anything in search path).
As Adam said, you don't need quotes with names without some special characters.
Try:
SELECT * FROM dam_vector.parcels_full;
If you really want to use a double quotes, go for:
SELECT * FROM "dam_vector"."parcels_full";

You shouldn't need the quotes around dam_vector.parcels_full.
Does the output of the following show that a parcels_full table is indeed present?
cur.execute("""SELECT tablename
FROM pg_tables
WHERE tablename NOT LIKE ALL (ARRAY['pg_%','sql_%']);""")
cur.fetchall()

Related

How to specify a dot separated table as a parameter into the sql query

For purposes of this question, let's say there is a table schema foo.bar.baz
And we have created a cursor object using following boilerplate
import snowflake.connector
ctx = snowflake.connector.connect(...)
cur = ctx.cursor()
With that cursor object, we can put the whole dot deliminated schema into a query like so:
cur.execute('''
select * from foo.bar.baz
'''
)
and have no issues, but we wouldn't be able to do:
cur.execute('''
select * from %(tbl)s
''', {'tbl': 'foo.bar.baz'}
)
Doing that throws this type of error: ProgrammingError: 001011 (42601): SQL compilation error: invalid URL prefix found in: foo.bar.baz
I'm guessing this is because the dots are sql identifiers and not strings, but I don't see any workaround in the snowflake documentation. Does anyone know how this could be done without having to change the connection object.
Using TABLE:
In a FROM clause, the syntax TABLE( { string_literal | session_variable | bind_variable } ) can be used
select * from TABLE(%(tbl)s)

Python -> MySQL "select * from brand WHERE text='L\'Orial'" (quote inside search text)

From Python 3.9 i'm trying to do a MySql query like this
select * from brand WHERE text='L\'Orial'.
It works fine from phpMyAdmin but fails from python for all text including quote "'"
brand = "L'Orial"
where = f"text='{brand}'"
brand_pk_id = self.getPrimaryKeyIfExistInTable('brand', where)
def getPrimaryKeyIfExistInTable(self, table, where, key='id'):
try:
sql = f"SELECT {key} FROM {table} WHERE {where}"
self.cursor.execute(sql)
result = self.cursor.fetchone()
return result[key if self.bUseDictCursor else 0] if result else None
except pymysql.MySQLError as e:
logging.error(e)
return None
I can see that python escapes all quotes, which probably causes the problem, but can not figure out how to handle it properly !!
If I turn it around and use query LIKE with underscore( _ ) as wildcard:
brand = "L_Orial"
sql = f"SELECT {key} FROM {table} WHERE text LIKE '{brand}'"
It works fine, but this is not what I want !!
If I am understanding your question correctly, your problem is as follows:
Your query must exactly read:
SELECT * from brand WHERE text='L\'Orial'
But you are currently getting something like this, when you use python to execute the query:
SELECT * from brand WHERE text='L'Orial'
If this is indeed the issue, you should be able to resolve this by simply escaping the backslash that you need to have in the query. The complete python string for your query would be:
# Python String:
"SELECT * from brand WHERE text='L\\'Orial'"
# Resulting Query
SELECT * from brand WHERE text='L\'Orial'
If you wanted to automatically fix this issue for all brands that might include a ', you can simply replace the ' with \\' before making the query. Example:
brand = "L'Orial"
brand = brand.replace("'", "\\'")
# New Python string:
# "L\\'Orial"
# Output in SQL
# "L\'Orial"
Had to fire up my local instance just to make a point.
First, some prep work...
import pymysql
table = 'ps_carrier'
key = 'id_carrier'
mysql = {
"charset": "utf8",
"database": "mystore",
"host": "localhost",
"password": "secret",
"user": "justin"
}
As somebody suggested in the comments, the following
sql = "SELECT %s FROM %s WHERE %s"
where = "name='UPS'"
with pymysql.connect(**mysql) as conn:
with conn.cursor() as cur:
cur.execute(sql, (key, table, where))
Raises an error as expected since all the (string) params are quoted, even the table name!
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
...
File "C:\Python38\site-packages\pymysql\err.py", line 143, in raise_mysql_exception
raise errorclass(errno, errval)
pymysql.err.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''ps_carrier' WHERE 'name=\\'UPS\\''' at line 1")
If you can trust the inputs for the table name, the key, and the column name(s) then perhaps a simple query builder can help.
params = {'name': 'UPS'} # add more key--value pairs here
# use backticks in case we need to escape reserved words (OP uses MySQL)
where = " AND ".join(f"`{k}` = %s" for k in params.keys()) # .keys() just to be explicit
args = tuple([v for v in params.values()])
# backticks again
sql = f"SELECT `{key}` FROM `{table}` WHERE {where}"
print(sql)
print(args)
with pymysql.connect(**mysql) as conn:
with conn.cursor() as cur:
cur.execute(sql, args)
print(cur.fetchall())
If you need something more elaborate, there are a few modules such as Mysql Simple Query Builder and PyPika - Python Query Builder that you may want to look at (I've not used any of these.)

why the select query through python throwing syntax error?

I am trying to connect to a Postgres DB and execute a simple select query. But I am getting errors. Below is the sample program
import psycopg2 as ps
param_dic = ps.connect(
host="localhost",
database="Test_DB",
user="username",
password="password"
)
cur = param_dic.cursor()
cur.execute("select * from <schema_name>.'employee_tbl'") # I am
rows = cur.fetchall()
for r in rows:
print(r)
I get below error:
psycopg2.errors.SyntaxError: syntax error at or near "'tbl_name'"
LINE 1: select * from <schema_name>.'tbl_name'
If I use
cur.execute("select * from <schema_name>.'Employee_TBL'")
Still, I get the same error.
Note: when I check my pgAdmin, I see below as the table name
<schema_name>.Employee_TBL
So, what is the right way to execute SQL queries on a Postgres table?
replace <schema_name>.'Employee_TBL'" with true value :
dbo.Employee_TBL or another schema name in your database
Maybe it's just a typo, use double quotes for the table if you need to.
Single quotes indicate a string literal.
import psycopg2
conn = psycopg2.connect(...)
cur = conn.cursor()
cur.execute('SELECT * FROM public.servers')
print(len(cur.fetchall()))
cur.execute('SELECT * FROM PUBLIC."servers"')
print(len(cur.fetchall()))
Out:
6
6
Try removing quotes around ‘emloyee_tbl’
The overriding issue is that you created a table name with quoted mixed case. This means that from then on you need to quote the name to be able to use it:
create table "Mixed_Case" (id int, fld_1 varchar);
select * from mixed_case;
ERROR: relation "mixed_case" does not exist
LINE 1: select * from mixed_case;
select * from "Mixed_Case";
id | fld_1
----+-------
(0 rows)
--NOTE the double quotes.
For more information see 4.1.1. Identifiers and Key Words
For the psycopg2 case:
import psycopg2
con = psycopg2.connect("dbname='test' host='localhost' user='aklaver'")
cur = con.cursor()
# Single quoted
cur.execute("select * from public.'Mixed_Case'")
SyntaxError: syntax error at or near "'Mixed_Case'"
LINE 1: select * from public.'Mixed_Case'
# Identifiers need double quotes
# Changing to double quotes
cur.execute('select * from public."Mixed_Case"')
# No error.
# You can also use Postgres functions
cur.execute("select * from quote_ident('public.Mixed_Case')")
For more on Postgres functions and methods see string functions
Also in psycopg2 there is the sql module that allows you to work with identifiers:
from psycopg2 import sql
sql_str = sql.SQL("select * from public.{}").format(sql.Identifier('Mixed_Case'))
print(sql_str.as_string(con))
select * from public."Mixed_Case"
cur.execute(sql_str)

Python2.7 - SQLite3 library outputs error message "sqlite3.OperationalError: near "?": syntax error"

Code is follow. How to get replaced ? by value of variables [table, url]?
Expected SQL command is select * from OTHER_URL where url="http://a.com/a.jpg"
This SQL command occurs no error on the sqlite3 command line interface.
import sqlite3
from contextlib import closing
dbname = "ng.db"
with closing(sqlite3.connect(dbname)) as conn:
c = conn.cursor()
c.execute("CREATE TABLE IF NOT EXISTS OTHER_URL (url TEXT)")
conn.commit()
table = "OTHER_URL"
url = "http://a.com/a.jpg"
with closing(sqlite3.connect(dbname)) as conn:
c = conn.cursor()
c.execute('select * from ? where url="?"', [table, url])
print c.fetchone()
There are two errors here. Firstly, you can't use parameter substitution for table names (or column names), only for values. You need to use string interpolation for anything else.
Secondly, you don't need quotes around the value parameter; the substitution will take care of that.
So:
c.execute('select * from {} where url=?'.format(table), [url])

Getting data from schema in psycopg2

I try to connect to Postgres database inside my Python app.
I use psycopg2 library.
If I execute select statement like this:
cursor.execute("""select schema_name from information_schema.schemata;""")
rows = cursor.fetchall()
print(rows)
and I get :
[('DB_FZ',), ('DB_FZ_TEMP',), ...]
but if I execute statement
cursor.execute("""select * from DB_FZ.d_results;""")
rows = cursor.fetchall()
print(rows)
I get error
psycopg2.ProgrammingError: schema "db_fz" does not exist
LINE 1: select * from DB_FZ.d_results;
What could be wrong?
The schema name is in uppercase, you should put it in double quotes:
cursor.execute("""select * from "DB_FZ".d_results;""")
See also Are PostgreSQL column names case-sensitive?

Categories