Psycopg2 : Create a table in a stored procedure Postgres - python

Stored Procedure :
CREATE OR REPLACE FUNCTION try_create() RETURNS INT AS $$
BEGIN
CREATE TABLE hello(id SERIAL PRIMARY KEY, name TEXT);
RETURN 1;
END ;
$$ LANGUAGE plpgsql;
test.py
import psycopg2
conn = psycopg2.connect(user='a', password='a', dbname='a')
cur = conn.cursor()
cur.callproc('try_create', ())
print cur.fetchall()
I am trying to create a stored procedure which will create a table named hello. I am invoking the same using a python script. Upon running the above script I see the following output
[root#localhost partitioning]# python test.py
[(1,)]
But the table is not created at the db. Am I making something wrong here? Thanks.

You should commit the transaction, add the commands:
...
conn.commit()
conn.close()
Alternatively, you can set the connection in autocommit mode:
conn = psycopg2.connect(user='a', password='a', dbname='a')
conn.autocommit = True
cur = conn.cursor()
cur.callproc('try_create', ())
conn.close()
Read more about transactions in psycopg2.

Related

SQLITE with python : Adding the database name in SELECT statement

I am using sqlite3 with python, and after connecting to the database and creating a table, sqlite3 shows an error when I try to execute a SELECT statment on the table with the name of the databse in it :
con = sqlite3.connect("my_databse")
cur = con.cursor()
cur.execute('''CREATE TABLE my_table ... ''')
cur.execute("SELECT * FROM my_database.my_table") # this works fine without the name of the database before the table name
but I get this error from sqlite3 :
no such table : my_database.my_table
Is there a way to do a SELECT statment with the name of the database in it ?
The short answer is no you can't do this with SQLite. This is because you already specify the database name with sqlite3.connect() and SQLite3 doesn't allow multiple databases in the same file.
Make sure of the database is in the same directory with the python script. In order to verify this you can use os library and os.listdir() method. After connecting the database and creating the cursor, you can query with the table name.
cur.execute('SELECT * FROM my_table')

Is there a proper way to handle cursors returned from a postgresql function in psycopg?

I'm trying to make friends with postgresql (14.0 build 1914 64-bit on windows), psycopg2 (2.9.1 installed using pip) and python 3.8.10 on windows.
I have created a postgresql function in a database that returns a cursor, somthing like below
CREATE get_rows
...
RETURNS refcursor
...
DECLARE
res1 refcursor;
BEGIN
OPEN res1 FOR
SELECT some_field, and_another_field FROM some_table;
RETURN res1;
END
The function can be run from pgAdmin4 Quert tool
SELECT get_rows();
and will then return a cursor like "<unnamed portal 1>"
Still within query tool in pgAdmin4 I can issue:
BEGIN;
SELECT get_rows();
FETCH ALL IN "<unnamed portal 2>"; -- Adjust counter number
And this will get me the rows returned by the cursor.
Now I want to replicate this using psycopg instead of pgAdmin4
I have the below code
conn = psycopg2.connect("dbname='" + db_name + "' "\
"user='" + db_user + "' " +\
"host='" + db_host + "' "+\
"password='" + db_passwd + "'")
cursor = conn.cursor()
cursor.callproc('get_rows')
print("cursor.description: ", end = '')
print(cursor.description)
for record in cursor:
print("record: ", end = '')
print (record)
The above code only gives the cursor string name (as returned by the postgresql function 'get_rows') in the single record of the cursor created by psycopg.
How can I get a cursor-class object from psycopg that provides access the cursor returned by 'get_rows'?
https://www.psycopg.org/docs/cursor.html says cursor.name is read-only and I dont see an obvious way to connect the cursor from 'get_rows' with a psycopg cursor-instance
The cursor link you show refers to the Python DB API cursor not the Postgres one. There is an example of how to do what you want here Server side cursor in section:
Note It is also possible to use a named cursor to consume a cursor created in some other way than using the DECLARE executed by execute(). For example, you may have a PL/pgSQL function returning a cursor:
CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS $$
BEGIN
OPEN $1 FOR SELECT col FROM test;
RETURN $1;
END;
$$ LANGUAGE plpgsql;
You can read the cursor content by calling the function with a regular, non-named, Psycopg cursor:
cur1 = conn.cursor()
cur1.callproc('reffunc', ['curname'])
and then use a named cursor in the same transaction to “steal the cursor”:
cur2 = conn.cursor('curname')
for record in cur2: # or cur2.fetchone, fetchmany...
# do something with record
pass
UPDATE
Be sure and close the named cursor(cur2) to release the server side cursor. So:
cur2.close()

Python2 print postgresql stored procedure raise notice

How can I print postgres's stored procedure on python script?
Example of stored procedure in postgres is as below:
create or replace function checktime() returns void
language plpgsql
as $$
DECLARE timestart TIMESTAMP;
FOR id from rt LOOP
SELECT timeofday() into timestart;
RAISE NOTICE 'Time now : %', timestart;
END LOOP;
END;
$$
;
From python, my script is:
import psycopg2
conn = psycopg2.connect(host="", database="",
user="", password="")
print("Database Connected")
cur = conn.cursor()
rowcount = cur.rowcount
cur.callproc('rt_visits_function_gz')
# how can i display the raise notice in here?
I would like for each loop the result is displayed when i run python.
Thank you
Try using 'notices'
print(conn.notices)
http://initd.org/psycopg/docs/connection.html?highlight=notice#connection.notices

Can't retrieve OUT parameters from stored procedures (MySQL)

I'm trying to call stored procedure from MySQL and obtain OUT param.
I have code like this one,
Call procedure from Python
from django.db import connection
# ...
cursor = connection.cursor()
out_arg1 = ""
args = [in_arg1, in_arg2, out_arg1]
result = cursor.callproc('some_procedure', args)
print(args[2], result[2])
cursor.close()
# ...
MySQL procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `some_procedure`(IN `in_arg1` VARCHAR(255) CHARSET utf8, IN `in_arg2` VARCHAR(255) CHARSET utf8, OUT `out_arg1` VARCHAR(255) CHARSET utf8)
MODIFIES SQL DATA
BEGIN
proc:begin
set out_arg1="Result";
end;
END;
I've checked args and the result returned by cursor.callproc method, but no data changed.
Any ideas why this is happening?
Thanks in advance.
P.S. I've tried to call this procedure from MySQL console and everything is ok.
use this way
from django.db import connection
# ...
cursor = connection.cursor()
out_arg1 = ""
args = [in_arg1, in_arg2, out_arg1]
result = cursor.callproc('some_procedure', args)
cursor.execute('SELECT #some_procedure_2')
print(cursor.fetchall())
#print(args[2], result[2])
cursor.close()
# ...

Python write to MySQL - no error but no writing

I am trying to write into my localhost MySQL database.
I have created a database named "test", a table called "price_update" and a row called "model"
When I run the script below I get no errors, however, I also get nothing written to my database.
I am not sure where to start looking for the problem. the row is varchar(10) and collation utf9_general_ci.
import MySQLdb
conn = MySQLdb.connect(host="127.0.0.1",user="someUser",passwd="somePassword",db="test")
query = "INSERT INTO price_update (model) values ('12345')"
x = conn.cursor()
x.execute(query)
row = x.fetchall()
You have to commit the changes:
conn.commit()
Also, I'd make your query safer:
query = "INSERT INTO price_update (model) values (%s)"
...
x.execute(query, ('12345',))

Categories