TypeError in postgres Upsert - postgresql

I want to do an upset in postgres (insert or update)
If a user_id does not exist in the table, I want to insert a line with user_id=user_id, first_date=date, last_date=date. But if the user already exists, I want to update only the last_date with date.
I was getting an error so I tried to simplify the insert with:
pd.read_sql("INSERT INTO table (user_id, first_date, last_date)
VALUES ( "+str(user_id)+", '"+date+"','"+date+"')
ON CONFLICT (user_id)
DO NOTHING", conn)
But I'm getting this error "TypeError: 'NoneType' object is not iterable"
And I can't understand what is wrong...
I'm using Jupyter and Postgres v11

read_sql expects a query returning data. Your INSERT doesn't.
You might use the execute function the documentation:
from pandas.io import sql
sql.execute('INSERT INTO table_name VALUES(?, ?, ?)', engine,
params=[('id', 1, 12.2, True)])
or you could add a RETURNING clause to the query. See the excellent postgresql documentation.

Related

Can you use SQL Views in Geoserver to insert a new database record into a PostGis Datastore?

I have tried to make an entry into a PostGIS Store in Geoserver using a SQL View in Geoserver with the following statement:
INSERT INTO marker_shp(gid, id, geom)
VALUES ((SELECT max(gid) FROM marker_shp)+1, (SELECT max(id) FROM marker_shp)+1, ST_GeomFromText('POINT (499724.5561430572 5268410.813606716)', 32633))
I got the following error message:
ERROR: Syntax error at »INTO« Position: 23
However, the same Query works fine if I use the same SQL Statement in pgAdmin.
If someone could help me out here I would be very thankful.
All the best:
Thomas :)
The syntax should be
INSERT INTO marker_shp(gid, id, geom)
SELECT max(gid) , max(id)+1 F, ST_GeomFromText('POINT (499724.5561430572 5268410.813606716)', 32633))
FROM marker_shp

Get last id before transaction commit using postgres in Golang

I have 2 insert queries.
In the second insert query, I need the first insert returned id.
I am doing those queries as a transaction, because they depend each other.
So, is it possible to get the last insert id before committing transaction in postgres in Golang.
Postgres supports the returning keyword to select the inserted id:
INSERT INTO YourTable (col1, col2) VALUES ('Value1', 'Value2') RETURNING id;

How to emulate "ON CONFLICT" PostgreSQL statement using JPQL

I need to convert PostgreSQL native queries to JPQL. How the following two SQL statements can be translated:
INSERT INTO my_table (id, some_data) VALUES (?1,?2) ON CONFLICT (id) DO NOTHING;
INSERT INTO other_table (id, other_data) VALUES (?1, ?2) ON CONFLICT DO UPDATE SET other_data = ?2
PostgreSQL ensures that each of the two statements will be executed atomically and will never fail due to conflict. How to archive the same functionality with JPA (EclipseLink)?

Insert with Array in Values with On Conflict

I can't seem to get this postgresql execute to work.
INSERT INTO table (x, y)
VALUES ('somestring', '{0.123, -0.123}')
ON CONFLICT DO NOTHING RETURNING id;
I get the error:
ProgrammingError: (psycopg2.ProgrammingError) syntax error at or near "ON"
I've tried a variety of things, and I'm not very well versed in postgresql or sql in general. I'm on version 9.5.1 of Postgresql.
I'm also using SQLAlchemy (Python Lib). Is there a way to check what version of Postgresql my SQLAlchemy is using?
You have to specify what may cause the conflict.
Example from the docs:
INSERT INTO distributors (did, dname) VALUES (7, 'Redline GmbH')
ON CONFLICT (did) DO NOTHING;
edit: I am referring to the (did) part

Getting the primary key after row insertion using redshift

I'm using postgresql 8.0.2 with amazon redshift and I'm trying to set up a INSERT command that also returns the PRIMARY KEY.
I was originally trying to do the following:
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute('INSERT INTO orders (my_id, my_amount) \
VALUES (%s, %s) RETURNING row_id;', (some_id, some_amount))
conn.commit()
However, the RETURNING command only works on postgresql 8.2 and above.
I saw that currval might be a possible way to get this to work, but I read that it requires a sequence object.
I'm trying to insert the following schema
CREATE SEQUENCE order_seq;
CREATE TABLE IF NOT EXISTS orders
(
order_id INTEGER IDENTITY(1,1) PRIMARY KEY DISTKEY,
)
Then do:
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute('INSERT INTO orders (my_id, my_amount) \
VALUES (%s, %s);', (some_id, some_amount))
conn.commit()
cur.execute('SELECT currval();')
row_id = cursor.fetchone()[0]
UPDATE: Sequence objects are not supported by redshift either. I feel like this is a pretty basic procedure but there is no easy way to get a reference to the current row.
Just define your column as:
order_id INTEGER PRIMARY KEY DISTKEY
And with your sequence created order_seq use this as insert command:
cur.execute('INSERT INTO orders (order_id, my_id, my_amount) \
VALUES (nextval(''order_seq''), %s, %s);', (some_id, some_amount))
Since you are using a sequence you have to add the field on the insert command to use the nextval properly.
And to retrieve current sequence value do as follow:
cur.execute('SELECT currval(''order_seq'')')
row_id = cursor.fetchone()[0]
I'm not familirized with the language you are using so you may have to change the syntaxe to scape the double quotes I use.
The syntaxe of nextval and currval is like: nextval('sequenceName') and currval('sequenceName')
So if it does not support sequences the only way I see that it could solve your issue is following this steps:
Open a transaction (so others wont get the same id)
fetch max id of your table like select max(order_id) from orders into a variable
use this value on the insert as it was the sequence.