Test if PostgreSQL table does NOT exist (with psycopg2) - python

Using Psycopg2, I need to test whether a postgresql table exists or not.
In a similar question, it is recommended to use the following test:
cursor.execute("select exists(select * from myDb.mytable_%s)" % complementName)
tableExists = cursor.fetchone()[0]
print(tableExists)
This works great if the table already exists, and returns True, but it does not work if the table does not exist. Instead of returning False like I would need, I get an error
ProgrammingError: relation "myDb.mytable_001"
does not exist
What am I doing wrong? What should I do in order to get a False statement if the table doesn't exist? Thanks for any help!
EDIT
Following advice in comments, I tried also:
tableExists = cursor.execute("SELECT 1 AS result FROM pg_database WHERE datname='mytable_001'")
and
tableExists = cursor.execute("SELECT EXISTS (SELECT 1 AS result FROM pg_tables WHERE schemaname = 'mySchema' AND tablename = 'mytable_001)')")
But both simply return None, whether the table exists or not. However, I'm not sure of the syntax, maybe you can point out some novice mistake I may be making? Thanks!
EDIT 2
Finally the solution consisted in a combination of the latter query above, and fetching the boolean result as follows:
cursor.execute("SELECT EXISTS (SELECT 1 AS result FROM pg_tables WHERE schemaname = 'mySchema' AND tablename = 'mytable_001');")
tableExists = cursor.fetchone()[0]

You can get info from information schema like:
SELECT table_schema,table_name
FROM information_schema.tables
WHERE table_name like 'pg_database';

Your query does not seem to right. You are supposed to provide table name for which you are verifying whether it is exist or not...... There are many more ways to verify whether table exist or not why to make it so complex.....
SELECT table_name FROM information_schema.tables where table_schema = 'your schema name' & store output in any variable then verify whether it is empty or not...you should be fine....
or use
query = SELECT EXISTS (SELECT relname FROM pg_class WHERE relname = 'table
name');
resp = cur.execute(query)
rows = cur.fetchone()
print(rows[0])
this will return True if table exist otherwise False....

Related

Python find a string with single quote symbol in postgresql table

I need to look up for a string that contains multiple single quotes from my psql table. My current solution is replacing the single quotes with double single quotes like this:
sql_query = f"""SELECT exists (SELECT 1 FROM {table_name} WHERE my_column = '{my_string.replace("'","''")}' LIMIT 1);"""
cursor = connection.cursor()
cursor.execute(sql_query)
Is there a nicer solution for this kind of formatting ?
I solved this by making the query like this
sql_query = f"""SELECT exists (SELECT 1 FROM {table_name} WHERE my_column = %s LIMIT 1);"""
cursor = connection.cursor()
cursor.execute(sql_query, (mystring,))
In this case it formats mystring in such way that it is not executed as sql query and doesn't cause the problems mentioned in the question

Alter query according to user selection in sqlite python

I have a sqlite database named StudentDB which has 3 columns Roll number, Name, Marks. Now I want to fetch only the columns that user selects in the IDE. User can select one column or two or all the three. How can I alter the query accordingly using Python?
I tried:
import sqlite3
sel={"Roll Number":12}
query = 'select * from StudentDB Where({seq})'.format(seq=','.join(['?']*len(sel))),[i for k,i in sel.items()]
con = sqlite3.connect(database)
cur = con.cursor()
cur.execute(query)
all_data = cur.fetchall()
all_data
I am getting:
operation parameter must be str
You should control the text of the query. The where clause shall allways be in the form WHERE colname=value [AND colname2=...] or (better) WHERE colname=? [AND ...] if you want to build a parameterized query.
So you want:
query = 'select * from StudentDB Where ' + ' AND '.join('"{}"=?'.format(col)
for col in sel.keys())
...
cur.execute(query, tuple(sel.values()))
In your code, the query is now a tuple instead of str and that is why the error.
I assume you want to execute a query like below -
select * from StudentDB Where "Roll number"=?
Then you can change the sql query like this (assuming you want and and not or) -
query = "select * from StudentDB Where {seq}".format(seq=" and ".join('"{}"=?'.format(k) for k in sel.keys()))
and execute the query like -
cur.execute(query, tuple(sel.values()))
Please make sure in your code the provided database is defined and contains the database name and studentDB is indeed the table name and not database name.

Passing parameter in psycopg2

I am trying to access PostgreSQL using psycopg2:
sql = """
SELECT
%s
FROM
table;
"""
cur = con.cursor()
input = (['id', 'name'], )
cur.execute(sql, input)
data = pd.DataFrame.from_records(cur.fetchall())
However, the returned result is:
0
0 [id, name]
1 [id, name]
2 [id, name]
3 [id, name]
4 [id, name]
If I try to access single column, it looks like:
0
0 id
1 id
2 id
3 id
4 id
It looks like something is wrong with the quoting around column name (single quote which should not be there):
In [49]: print cur.mogrify(sql, input)
SELECT
'id'
FROM
table;
but I am following doc: http://initd.org/psycopg/docs/usage.html#
Anyone can tell me what is going on here? Thanks a lot!!!
Use the AsIs extension
import psycopg2
from psycopg2.extensions import AsIs
column_list = ['id','name']
columns = ', '.join(column_list)
cursor.execute("SELECT %s FROM table", (AsIs(columns),))
And mogrify will show that it is not quoting the column names and passing them in as is.
Nowadays, you can use sql.Identifier to do this in a clean and secure way :
from psycopg2 import sql
statement = """
SELECT
{id}, {name}
FROM
table;
"""
with con.cursor() as cur:
cur.execute(sql.SQL(statement).format(
id=sql.SQL.Identifier("id"),
name=sql.SQL.Identifier("name")
))
data = pd.DataFrame.from_records(cur.fetchall())
More information on query composition here : https://www.psycopg.org/docs/sql.html
The reason was that you were passing the string representation of the array ['id', 'name'] as SQL query parameter but not as the column names. So the resulting query was similar to
SELECT 'id, name' FROM table
Looks your table had 5 rows so the returned result was just this literal for each row.
Column names cannot be the SQL query parameters but can be just the usual string parameters which you can prepare before executing the query-
sql = """
SELECT
%s
FROM
table;
"""
input = 'id, name'
sql = sql % input
print(sql)
cur = con.cursor()
cur.execute(sql)
data = pd.DataFrame.from_records(cur.fetchall())
In this case the resulting query is
SELECT
id, name
FROM
table;

Select query in pymysql

When executing the following:
import pymysql
db = pymysql.connect(host='localhost', port=3306, user='root')
cur = db.cursor()
print(cur.execute("SELECT ParentGuardianID FROM ParentGuardianInformation WHERE UserID ='" + UserID + "'"))
The output is1
How could I alter the code so that the actual value of the ParentGuardianID (which is '001') is printed as opposed to 1.
I'm sure the answer is simple but I am a beginner so any help would be much appreciated - thanks!
cur.execute() just returns the number of rows affected. You should do cur.fetchone() to get the actual result, or cur.fetchall() if you are expecting multiple rows.
The cursor.execute() method gives out a cursor related to the result of the SQL sentence. In case of a select query, it returns the rows (if any) that meet it. So, you can iterate over these rows using a for loop for instance. In addition, I would recommend you to use pymysql.cursors.DictCursor because it allows treating the query results as a dictionary.
import pymysql
db = pymysql.connect(host='localhost', port=3306, user='root')
cur = db.cursor(pymysql.cursors.DictCursor)
UserId = 'whatsoever'
sql = "SELECT ParentGuardianID FROM ParentGuardianInformation WHERE UserID ='%s'"
cur.execute(sql % UserId)
for row in cur:
print(row['ParentGuardianID'])
Good luck!

Return all values when a condition value is NULL

Suppose I have the following very simple query:
query = 'SELECT * FROM table1 WHERE id = %s'
And I'm calling it from a python sql wrapper, in this case psycopg:
cur.execute(query, (row_id))
The thing is that if row_id is None, I would like to get all the rows, but that query would return an empty table instead.
The easy way to approach this would be:
if row_id:
cur.execute(query, (row_id))
else:
cur.execute("SELECT * FROM table1")
Of course this is non idiomatic and gets unnecessarily complex with non-trivial queries. I guess there is a way to handle this in the SQL itself but couldn't find anything. What is the right way?
Try to use COALESCE function as below
query = 'SELECT * FROM table1 WHERE id = COALESCE(%s,id)'
SELECT * FROM table1 WHERE id = %s OR %s IS NULL
But depending how the variable is forwarded to the query it might be better to make it 0 if it is None
SELECT * FROM table1 WHERE id = %s OR %s = 0

Categories

Resources