Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ON CONFLICT DO UPDATE has missing FROM-clause

I have a simple table (id and name column, both unique), which I am importing a tab delimited CSV file.

I am running psql 9.5, and wanted to try out the new ON CONFLICT feature to update the name column if the ID already exists.

CREATE TEMP TABLE tmp_x AS SELECT * FROM repos LIMIT 0;
COPY tmp_x FROM '/Users/George/git-parser/repo_file' (format csv, delimiter E'\t');
INSERT INTO repos SELECT * FROM tmp_x
ON CONFLICT(name) DO UPDATE SET name = tmp_x.name;
DROP TABLE tmp_x;

I am getting this error:

SELECT 0
COPY 1
ERROR:  missing FROM-clause entry for table "tmp_x"
LINE 4: ON CONFLICT(name) DO UPDATE SET name = tmp_x.name;
                                               ^
Query failed
PostgreSQL said: missing FROM-clause entry for table "tmp_x"

Not too sure whats going wrong here.

like image 524
George L Avatar asked Feb 02 '16 17:02

George L


People also ask

What is needed for an INSERT on conflict update to work?

You must have INSERT privilege on a table in order to insert into it. If ON CONFLICT DO UPDATE is present, UPDATE privilege on the table is also required. If a column list is specified, you only need INSERT privilege on the listed columns.

What is INSERT on CONFLICT?

The INSERT ON CONFLICT statement allows you to update an existing row that contains a primary key when you execute the INSERT statement to insert a new row that contains the same primary key. This feature is also known as UPSERT or INSERT OVERWRITE. It is similar to the REPLACE INTO statement of MySQL.

How to use on CONFLICT in PostgreSQL?

The actual implementation within PostgreSQL uses the INSERT command with a special ON CONFLICT clause to specify what to do if the record already exists within the table. You can specify whether you want the record to be updated if it's found in the table already or silently skipped.

What is excluded in Postgres?

Introduction to PostgreSQL EXCLUDE. PostgreSQL excludes statements in PostgreSQL is used to compare any two rows from the specified column or expression by using the operator specified in PostgreSQL. At the time of excluding the column, the comparison operator will return the null or false value as output.

What is the on conflict clause?

The ON CONFLICT clause is a non-standard extension specific to SQLite that can appear in many other SQL commands. It is given its own section in this document because it is not part of standard SQL and therefore might not be familiar. The ON CONFLICT clause described here has been a part of SQLite since before version 3.0.0 (2004-06-18).

Does on conflict apply to foreign key?

The ON CONFLICT clause applies to UNIQUE, NOT NULL, CHECK, and PRIMARY KEYconstraints. The ON CONFLICT algorithm does not apply to FOREIGN KEY constraints. There are five conflict resolution algorithm choices: ROLLBACK, ABORT, FAIL, IGNORE, and REPLACE.

How PostgreSQL on Conflict Statement works?

PostgreSQL ON CONFLICT | How ON CONFLICT Statement Works? PostgreSQL on conflict is used to insert the data in the same row twice, which the constraint or column in PostgreSQL identifies values. If we want to insert data into the same column twice at the same time, we have to use on the conflict by using insert statement in PostgreSQL.

What is the difference between abort and replace conflict resolution?

If a NOT NULLconstraint violation occurs, the REPLACE conflict resolution replaces the NULL value with the default value for that column, or if the column has no default value, then the ABORT algorithm is used. If a CHECK constraintor foreign key constraintviolation occurs, the REPLACE conflict resolution algorithm works like ABORT.


1 Answers

If you look at the documentation of the ON CONFLICT clause, it says this about the "conflict action":

The SET and WHERE clauses in ON CONFLICT DO UPDATE have access to the existing row using the table's name (or an alias)

In your query, the target table is repos.

tmp_x, on the other hand, is the source of the data you are trying to insert, but the ON CONFLICT clause cannot "see" that - it is looking at a particular row that has been calculated and failed. Consider if you'd written something like this:

INSERT INTO repos SELECT max(foo_id) FROM tmp_x

Clearly, it wouldn't make sense for a row which failed to insert into repos to have access to any one row from tmp_x.

If there was no way of seeing the rejected data, the whole feature would be pretty useless, but if we read on:

... and to rows proposed for insertion using the special excluded table.

So instead, you need to access the magic table alias excluded, which contains the values which you tried to insert but got a conflict on, giving you this:

INSERT INTO repos SELECT * FROM tmp_x
ON CONFLICT(name) DO UPDATE SET name = excluded.name;

If it seems weird that an imaginary table name pops up for this purpose, consider that a similar thing happens when writing triggers, where you get OLD and NEW (depending on the kind of trigger you're writing).

like image 50
IMSoP Avatar answered Sep 28 '22 00:09

IMSoP