insert if not present in snowflake - sql

The idea of this code was to insert new rows into a table after determining which "load_id"(s) are not present.
MERGE INTO stg.my_table AS tgt
using stg.my_view AS src
ON tgt. load_id = src.load_id
WHEN NOT matched THEN
INSERT (id,
document_type,
state,
publication_date,
)
VALUES (src.id,
src.document_type,
src.state,
src.publication_date,
);
Is there a way to achieve the same result without having to use a MERGE statement? Isn't an INSERT enough?

Using INSERT INTO:
INSERT INTO stg.my_table -- column list here
SELECT src.*
FROM stg.my_view AS src
LEFT JOIN stg.my_table AS tgt
ON tgt.load_id = src.load_id
WHERE tgt.load_id IS NULL;
Also using EXISTS
INSERT INTO stg.my_table -- column list here
SELECT src.*
FROM stg.my_view AS src
WHERE NOT EXISTS (SELECT *
FROM stg.my_table AS tgt
WHERE tgt.load_id = src.load_id);
Extras:
Both patterns above are syntax that are executed as ANTI-JOIN.

Related

How to rebuild this query using joins

help me please to understand, how to remake this query using joins.
INSERT INTO mytable
(user_id, tag)
SELECT ?, ?
WHERE NOT EXISTS (SELECT user_id FROM mytable WHERE user_id=? AND tag=?)
I saw similar questions that use two different tables, but here i have one table.
I need to insert only if the same entry does not exist. mytable table does not have any UNIQUE constraints and i can't change scheme.
You can put your parameters into a common table expression that is reusable:
with data (user_id, tag) as (
values (?,?)
)
INSERT INTO mytable (user_id, tag)
SELECT d.user_id, d.tag
FROM data d
WHERE NOT EXISTS (SELECT *
FROM mytable t
cross join data d
WHERE t.user_id = d.user_id
AND t.tag = d.tag)
Note that this will not prevent concurrent insert of the same values. The only way to achieve that is to add a unique constraint (and then you can use on conflict do nothing)

How to copy records which do not exist in the target table

I create a temporary table which I fill with external data.
CREATE TEMP TABLE tmp AS SELECT * FROM saireco.employee LIMIT 0;
Next, I want to copy all records which exist in the temporary table to the target table.
INSERT INTO saireco.employee
SELECT *
FROM tmp t
LEFT JOIN saireco.employee e USING ("employeeID")
WHERE e."employeeID" IS NULL;
The results in an error
ERROR: INSERT has more expressions than target columns
LINE 2: SELECT *
The reason is that SELECT * not only results the columns from the temporary table, but also the columns from the target table resulting in more columns than the target table contains.
How can I only return the columns from the temporary table?
Your join combined with select * returns all columns of both tables, not only those from the tmp table.
One way to solve it, is to explicitly specify the target columns and those in the source:
insert into saireco.employee (col1, col2, col2)
select t.col1, t.col2, t.col3
from tmp t
LEFT JOIN saireco.employee e USING ("employeeID")
WHERE e."employeeID" IS NULL;
Or as both tables have the same structure (including the order of the columns), you can use select t.* to only get the columns of the tmp table:
insert into saireco.employee
select t.*
from tmp t
LEFT JOIN saireco.employee e USING ("employeeID")
WHERE e."employeeID" IS NULL;
Alternatively you can use a NOT EXISTS that doesn't increase the number of columns in the output:
insert into saireco.employee
select *
from tmp t
where not exists (select *
from saireco.employee e
where employeeID" t."employeeID");
But specifying the target columns and and specifying the output columns is good coding practice and should also be done in the second solution.
In general, you should use t.* to return the columns of the table t
INSERT INTO saireco.employee
SELECT t.*
FROM tmp t
LEFT JOIN saireco.employee e USING ("employeeID")
WHERE e."employeeID" IS NULL;
But if the primary key column in the employee table is IDENTITY , you must specify the column names explicitly because the IDENTITY column will not accept the insert , and the code will be better clear
Exp:
INSERT INTO saireco.employee
( employeeName , phone , .....)
SELECT t.employeeName, employee.phone ....
FROM tmp t
LEFT JOIN saireco.employee e USING ("employeeID")
WHERE e."employeeID" IS NULL;

Equivalent for Merge with output clause in SQL Server to Postgresql

I want to insert values based on below code to a temporary table in postgresql
declare #output table (AuditScratchID bigint, AuditID bigint);
merge table atb
using (select
s.ID
....
....
....
from #temporaryTableVariable s
inner join ....
...............
..............
) as s
on 1 = 2 -- Impossible Condition so they never match
when not matched then
insert (.....)
values (.....)
output s.ID, inserted.ID
into #output;
Just to mention, how can I correlate values into temporary table
I don't understand the use of MERGE to begin with.
This seems like a straightforward insert ... select. To see the inserted rows, use the returning clause
insert into atb (...)
select ... columns ...
from some_table
join other_table on ...
returning *

How to compare two tables,if no match insert those values to a table which doesn't have data?

I need to compare two tables Main_Table and OUT-Table, OUT_Table contains data but Main_Table may not have all the data..so I need to compare these tables if no match then just insert these unmatched values to Main_Table. This is my query...
Insert into Main_Table MT (MT.SerialNo) values (Select SerialNo
from Main_Table MT where not exists (select SerialNo from OUT_Table OT
where OT.SerialNo = MT.SerialNo))
This is selecting the values from out_Table which are not in Main_Table but not Inserting the values into main_table. I'am using Oracle database, Java(JSP). Please help me out to do this.
Insert into Main_Table MT (MT.SerialNo)
values ( Select SerialNo
from Main_Table MT
where not exists ( select SerialNo
from OUT_Table OT
where OT.SerialNo = MT.SerialNo
)
)
The INSERT INTO..SELECT FROM syntax that you've used here isn't correct, the values keyword is not required here. Should be just
Insert into Main_Table MT (MT.SerialNo)
( Select SerialNo
from Main_Table MT
where not exists ( select SerialNo
from OUT_Table OT
where OT.SerialNo = MT.SerialNo
)
)
Here's an example that Oracle documentation provides.

MERGE - When not matched INSERT's exception

i have a PL/SQL procedure using MERGE :
MERGE INTO
table_dest d
USING
(SELECT * FROM my_Table) s
ON
(s.id = d.id)
when matched then UPDATE set d.col1 = s.col1
when not matched then INSERT (id, col1) values (s.id, s.col1);
now lets say the query s returns mutiple rows with same id wich will returns an ORA-00001: unique constrain error
what i want to do is to send the duplicated columns to another table my_Table_recyledbin to get a successful INSERT, can i use EXCEPTION WHEN DUP_VAL_ON_INDEX ? if yes how to use it with the MERGE statement?
Thanks in advance
Why not handle the archiving of duplicate rows to the recycle bin table in a separate statement?
Firstly, do your merge (aggregating the duplicate rows to avoid the unique constraint error). I've assumed a MAX aggregate function on col1, but you can use whatever suits your needs -- you have not specified how to decide which row to use when there are duplicates.
MERGE INTO
table_dest d
USING
(SELECT a.id, MAX(a.col1) as col1
FROM my_Table a
GROUP BY a.id) s
ON
(s.id = d.id)
WHEN MATCHED THEN UPDATE SET d.col1 = s.col1
WHEN NOT MATCHED THEN INSERT (id, col1) VALUES (s.id, s.col1);
Then, deal with the duplicate rows. I'm assuming that your recycle bin table does allow duplicate ids to be inserted:
INSERT INTO my_Table_recyledbin r (id, col1)
SELECT s.id, s.col1
FROM my_Table s
WHERE EXISTS (SELECT 1
FROM my_Table t
WHERE t.id = s.id
AND t.ROWID != s.ROWID)
Hopefully, that should fulfil your needs.
Can't you just use an error-logging clause? I.E., add this line at the end of your MERGE statement:
LOG ERRORS INTO my_Table_recycledbin