Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert if not exists Oracle

I need to be able to run an Oracle query which goes to insert a number of rows, but it also checks to see if a primary key exists and if it does, then it skips that insert. Something like:

INSERT ALL     IF NOT EXISTS( SELECT 1 WHERE fo.primary_key='bar' )     (         INSERT INTO              schema.myFoo fo ( primary_key, value1, value2 )         VALUES             ('bar','baz','bat')     ),          IF NOT EXISTS( SELECT 1 WHERE fo.primary_key='bar1' )     (         INSERT INTO              schema.myFoo fo ( primary_key, value1, value2 )         VALUES             ('bar1','baz1','bat1')     ) SELECT * FROM schema.myFoo; 

Is this at all possible with Oracle?

Bonus points if you can tell me how to do this in PostgreSQL or MySQL.

like image 292
cwallenpoole Avatar asked Nov 09 '09 18:11

cwallenpoole


People also ask

How do you insert if row does not exist in SQL?

There are three ways you can perform an “insert if not exists” query in MySQL: Using the INSERT IGNORE statement. Using the ON DUPLICATE KEY UPDATE clause. Or using the REPLACE statement.

How do you check if a record exists in a table Oracle?

Type a short Oracle program, using the following code as a guide: DECLARE record_exists INTEGER; BEGIN SELECT COUNT(*) INTO record_exists FROM your_table WHERE search_field = 'search value' AND ROWNUM = 1; IF record_exists = 1 THEN DBMS_OUTPUT. put_line('Record Exists') ELSE DBMS_OUTPUT.

Can we use insert statement in function in Oracle?

The INSERT command can also take the values directly from another table using 'SELECT' statement rather than giving the values for each column. Through 'SELECT' statement, we can insert as many rows as the base table contains. Syntax: BEGIN INSERT INTO <table_name>(<column1 >,<column2>,...

Can we use if exists in Oracle?

The Oracle EXISTS condition is used in combination with a subquery and is considered "to be met" if the subquery returns at least one row. It can be used in a SELECT, INSERT, UPDATE, or DELETE statement.


2 Answers

Coming late to the party, but...

With oracle 11.2.0.1 there is a semantic hint that can do this: IGNORE_ROW_ON_DUPKEY_INDEX

Example:

insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(customer_orders,pk_customer_orders) */   into customer_orders        (order_id, customer, product) values (    1234,     9876,  'K598')      ; 

UPDATE: Although this hint works (if you spell it correctly), there are better approaches which don't require Oracle 11R2:

First approach—direct translation of above semantic hint:

begin   insert into customer_orders          (order_id, customer, product)   values (    1234,     9876,  'K698')   ;   commit; exception   when DUP_VAL_ON_INDEX   then ROLLBACK; end; 

Second aproach—a lot faster than both above hints when there's a lot of contention:

begin     select count (*)     into   l_is_matching_row     from   customer_orders     where  order_id = 1234     ;      if (l_is_matching_row = 0)     then       insert into customer_orders              (order_id, customer, product)       values (    1234,     9876,  'K698')       ;       commit;     end if; exception   when DUP_VAL_ON_INDEX   then ROLLBACK; end; 
like image 139
Michael Deardeuff Avatar answered Sep 17 '22 07:09

Michael Deardeuff


The statement is called MERGE. Look it up, I'm too lazy.

Beware, though, that MERGE is not atomic, which could cause the following effect (thanks, Marius):

SESS1:

create table t1 (pk int primary key, i int); create table t11 (pk int primary key, i int); insert into t1 values(1, 1); insert into t11 values(2, 21); insert into t11 values(3, 31); commit; 

SESS2: insert into t1 values(2, 2);

SESS1:

MERGE INTO t1 d USING t11 s ON (d.pk = s.pk) WHEN NOT MATCHED THEN INSERT (d.pk, d.i) VALUES (s.pk, s.i); 

SESS2: commit;

SESS1: ORA-00001

like image 30
erikkallen Avatar answered Sep 19 '22 07:09

erikkallen