In the discussion about multiple row insert into the Oracle two approaches were demonstrated:
First:
insert into pager (PAG_ID,PAG_PARENT,PAG_NAME,PAG_ACTIVE)
select 8000,0,'Multi 8000',1 from dual
union all select 8001,0,'Multi 8001',1 from dual
Second:
INSERT ALL
INTO t (col1, col2, col3) VALUES ('val1_1', 'val1_2', 'val1_3')
INTO t (col1, col2, col3) VALUES ('val2_1', 'val2_2', 'val2_3')
INTO t (col1, col2, col3) VALUES ('val3_1', 'val3_2', 'val3_3')
.
.
.
SELECT 1 FROM DUAL;
Could anyone argue the preference of using one over another?
P.S. I didn't do any research myself (even explanation plan), so any information or opinion would be appreciated.
Thanks.
From performance's point of view, these queries are identical.
UNION ALL
won't hurt performance, sinceOracle
estimates theUNION
'ed query only when it needs it, it doesn't cache the results first.SELECT
syntax is more flexible in that sense that you can more easuly manupulate theSELECT
query if you want to change something.For instance, this query:
can be rewritten as
By replacing
2
with appropriate number, you can get any number of rows you want.In case of
INSERT ALL
, you would have to duplicate the destination table description, which is less readable if you need, say,40
rows.The statement utilizing the
UNION ALL
has theoretically a small performance disadvantage as it has to union the results of all statements before the insert can happen. TheINSERT ALL
doesn't have this disadvantage as the final result can already be processed line-by-line.But practically the optimizer inside Oracle should make the difference negligible and it is up to your preferences which way you choose.
In my own opinion the
INSERT ALL
is the better human-readable of the two while theUNION ALL
variant is the one taking less space when such an insert is automatically generated.I would suspect solution 1 is a bit of a hack that works and is probably less efficient than the designed alternative of Insert ALL.
Insert all is really designed for you to insert many rows into more than 1 table as a result of a select, eg:
If you want to load thousands of rows and they are not in the database already, I don't think this is the best way to do it - If your data is in a file, you want to look at External Tables or SQL Loader to efficiently insert the rows for you.
You should consider Array-Insert.
This is the way to minimize the Network-Traffic if some hundred inserts needs to be done in a batch.
The
INSERT ALL
method has a problem with inserting bigger number of rows into a table.I recently wanted to insert 1130 rows into a table with single SQL statement. When I tried to do this with
INSERT ALL
method I got the following error:When I used
INSERT INTO .. UNION ALL ..
approach everything went fine.Btw. I didn't know about the UNION ALL method before I found this discussion :)
If you have insert statements that are more than 1000 then put all the insert statements in a .sql file and open that in Toad or SQL Developer and then execute. All records will get inserted.