PostgreSQL ERROR column does not exist refers to a column value - sql

I have a table projects in postgreSQL that looks like below
id. project_name. col3. col4
1111. test. ... ...
I want to insert a new row for a new id only if the id does not already exist. So I wrote below query
INSERT INTO projects(id, project_name)
VALUES("1234", "Test_Project")
ON CONFLICT (id)
DO NOTHING
But it throws me an error
Query 1 ERROR: ERROR: column "1234" does not exist
LINE 2: VALUES("1234", "Test_Project_...
Please suggest.
** EDIT**
The id column in the table is a uuid and not unique. There can be multiple rows with the same id. Based on GMBs suggestion, I tried below
INSERT INTO projects(id, project_name)
VALUES('1234', 'Test_Project')
ON CONFLICT (create unique index on projects(id))
DO NOTHING
I get below error with it
Query 1 ERROR: ERROR: syntax error at or near "create"
LINE 3: ON CONFLICT (create unique index on projects(id...
I am new to this so I am sure missing something obvious.

Use single quotes for literal strings. Double quotes stand for identifiers (such as column names or table names) - hence the error that you are getting:
INSERT INTO projects(id, project_name)
VALUES('1234', 'Test_Project')
ON CONFLICT (id)
DO NOTHING
That said, I would suspect that id is of integer datatype. If so, don't quote it at all:
INSERT INTO projects(id, project_name)
VALUES(1234, 'Test_Project')
ON CONFLICT (id)
DO NOTHING

Related

New to SQL - INCORRECT INTEGER. Laments terms, what does it mean?

Error: Incorrect integer value: 'Hammer Mill' for column 'supplier_name' at row 1
Error Code: ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
Context, I'm trying to build a database. I've been able to run the prior tables. I get to this one: -- BRANCH SUPPLIER
INSERT INTO branch_supplier VALUES(2, 'Hammer Mill', 'Paper'); and I get the errors mentioned above.
Seems self-explanatory to me, whatever the database you are using...
You are trying to insert a string value into an integer column and there are only two possible causes:
Either the table has been created with the wrong data types (or you are not respecting data types). I think this is your case as [supplier_name] as an int column sounds wrong to me
The "column order" is not the one you expect, if not specified it will be positional, meaning the first value goes into the first column... it's not wise for several reasons and I suggest you always use the below format for your insert
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value, ...);

Why I am getting Insert has more target columns than expressions

I have a simple table called source with 3 columns (source_id, name, tenant_id) and some data in it.
I a trying to insert a data into the table by checking its existence in the table. But I am getting this error ..any idea how to resolve
The Query -
INSERT INTO moa.source(source_id, name, tenant_id)
SELECT ((select max(source_id)+1 from moa.source), 'GE OWS - LHR', 1)
WHERE NOT EXISTS(SELECT 1 FROM moa.source where name = 'GE OWS - LHR');
The Error :
ERROR: INSERT has more target columns than expressions
LINE 1: INSERT INTO moa.source(source_id, name, tenant_id)
^
HINT: The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?
SQL state: 42
The Table:
Sorry..figured it out..there should be no paranthesis after Select

How to copy, change, and insert records in Postgres

In a PostgreSQL DB table, I need to copy a block of records from a prior month, change values in some of the columns, and append the updated records to the table. Details include:
The key id is configured with nextval to automatically create
unique key values
The target records have '200814' in group_tag
The new records need '200911' in group_tag
Several other fields need to be updated as shown in the SELECT
My script so far:
INSERT INTO hist.group_control(
id,
group_tag,
process_sequence,
state,
cbsa_code,
window_starts_on,
preceding_group,
preceding_origin,
preceding_window_starts_on
)
SELECT id,
'200911',
1,
state,
cbsa_code,
'2020-09-11',
'200814',
preceding_origin,
'2020-08-14'
FROM hist.group_control WHERE group_tag='200814';
This generates an error:
SQL Error [23505]: ERROR: duplicate key value violates unique constraint "group_control_pkey"
Detail: Key (id)=(12250) already exists.
Records with key values up to 13008 exist. I would have expected nextval to determine this and start the id value at 13009. I attempted to simply not include id in the statement thinking the nextval function would operate automatically, but that errored as well. Variations on the following have not worked due to the respective errors:
alter sequence group_control_id_seq restart with 13009;
SQL Error [42501]: ERROR: must be owner of relation group_control_id_seq
SELECT setval('group_control_id_seq', 13009, true);
SQL Error [42501]: ERROR: permission denied for sequence group_control_id_seq
Anyone know how to code the main statement to not generate the duplicate key or alternatively, how to tell nextval to start at a value of 13009
It appears your serial, bigserial, or generated by default. Any of these only assign the id column when it is not specified in the insert statement. If you specify the id column Postgres will not assign a key PK. Since you selected the id, Postgres attempted to use what you specified. Solution drop id from the insert statement.
INSERT INTO hist.group_control(
group_tag,
process_sequence,
state,
cbsa_code,
window_starts_on,
preceding_group,
preceding_origin,
preceding_window_starts_on
)
SELECT '200911',
1,
state,
cbsa_code,
'2020-09-11',
'200814',
preceding_origin,
'2020-08-14'
FROM hist.group_control WHERE group_tag='200814';

DB2 error: SQL subselect error not recognized

I think I just found an error in DB2 itself. When I run this code I expect it to throw an error when executing the delete statement (the subselect wrongly uses A_NAME instead of NAME). But: it acts as if there was no where clause and deletes all the rows in table NAMES!
CREATE TABLE NAMES (A_NAME VARCHAR(20));
CREATE TABLE OLDNAMES (NAME VARCHAR(20));
INSERT INTO NAMES VALUES ('ANNA'), ('ELLA'), ('JOHN'), ('EARL');
INSERT INTO OLDNAMES VALUES ('ELLA'), ('EARL');
-- this should throw an error message:
DELETE FROM NAMES WHERE A_NAME IN (SELECT A_NAME FROM OLDNAMES);
-- this should show ANNA & JOHN if the subselect
-- was correct, but shows nothing
SELECT * FROM NAMES;
-- cleanup
DROP TABLE NAMES;
DROP TABLE OLDNAMES;
I ran it on a DB2/LINUXX8664 10.5.9
Or is "not a bug, but a feature"?!
You are wrong. SQL has scoping rules for resolving column references in subqueries. If the column reference is not resolved in the inner query, then it looks to the outer query.
These are the rules of SQL, not specific to DB2.
That is SQL interprets your logic as:
DELETE FROM NAMES
WHERE NAMES.A_NAME IN (SELECT NAMES.A_NAME FROM OLDNAMES ON);
And this is valid -- if meaningless -- SQL.
This is why qualifying ALL column references is recommended. The better way to write this query is:
DELETE FROM NAMES
WHERE NAMES.A_NAME IN (SELECT ON.A_NAME FROM OLDNAMES ON);

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.
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).