I have two identical schemas, on different databases connected via Database Link.
Schema_1: Source Schema. **Rows being inserted at rapid rate.**
Schema_2: Target Schema.
Rows being inserted into Schema_1 (source schema) at rapid rate.
I am running a SQL in Source Schema as follows:
Insert into Table_1#DB_LINK select * from Table_1
This statement takes several minutes.
Now I change the statement as follows ( using flashback query )
Insert into Table_1#DB_LINK select * Table_1 as of timestamp to_timestamp ( to_timestamp ( date ));
This query completes in few seconds.
Why such huge difference ?
In your flashback query you are selecting the rows which were inserted exactly on 05/01/2017 10:00:00. But in your non-flashback query you are selecting all the rows inserted in the table.
Simple demonstration:
SQL> create table t1(id number, name varchar2(20));
Table created.
SQL> insert into t1 values(1, 'joe');
1 row created.
SQL> insert into t1 values(2, 'jay');
1 row created.
SQL> commit;
Commit complete.
SQL> insert into t1 values(3, 'john');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t1;
ID NAME
---------- --------------------
1 joe
2 jay
3 john
SQL> select * from t1 as of timestamp to_timestamp('02-MAY-17 11:00','DD-MON-RR HH24:MI');
ID NAME
---------- --------------------
1 joe
My first query, select * from t1;, is identical to your non-flashback query which selects all the rows from the table.
And my second query, select * from t1 as of timestamp to_timestamp('02-MAY-17 11:00','DD-MON-RR HH24:MI'); is similar to your flashback query, which selects only one rows.
Of course inserting one row is faster than inserting three rows.
Related
I have a table (with one column called Id) and it has about 10 millions records. Some of these Ids are duplicate and I need to transfer unique Ids into another table (which will also have same one column). I am looking for a sql which can do it and quickest of performance.
10million won't be an issue for the database. Here's an example of that just on my laptop
SQL> create table t as
2 select mod(rownum,10000000) x
3 from
4 ( select 1 from dual connect by level <= 11000 ),
5 ( select 1 from dual connect by level <= 1100 );
Table created.
SQL>
SQL> select count(*) from t;
COUNT(*)
----------
12100000
SQL> set timing on
SQL> create table t1
2 as select distinct x from t;
Table created.
Elapsed: 00:00:03.96
SQL> select count(*) from t1;
COUNT(*)
----------
10000000
Elapsed: 00:00:00.23
So expect around 3-4 seconds to get the unique list.
I am trying to insert the same value into all rows except for a different value being imported from another table. I am doing it on oracle database
I have tried the following :
insert into table
(ID, version, other_id, value3,value4,value5,value6,value7,value8,value9)
VALUES
((select MAX(ID)+1 from table), '0', '5', '0', '1',
select name from table2,
select name from table2, '11', '14', '50');
all the values are the same except for the name from table2 will be different in each entry.
Any hint on how to insert all of them at once instead of having to do each one seprate?
You can do it, certainly, but not the way you put it (as you already know).
I'd suggest you NOT to use max + 1 because it just won't work properly, especially in a multi-user environment. Use a sequence instead.
Here's an example: insert into t1 values based on t2.
Sample tables:
SQL> DESC t1;
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER
VERSION NUMBER
JOB VARCHAR2(10)
SQL> DESC t2;
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER
JOB VARCHAR2(10)
SQL> SELECT * FROM t1;
no rows selected
SQL> SELECT * FROM t2;
ID JOB
---------- ----------
1 CLERK
2 MANAGER
SQL>
A sequence:
SQL> CREATE SEQUENCE seqt;
Sequence created.
Insert statement:
SQL> INSERT INTO t1 (id, version, job)
2 SELECT seqt.NEXTVAL, '0', t2.job FROM t2;
2 rows created.
Result:
SQL> SELECT * FROM t1;
ID VERSION JOB
---------- ---------- ----------
1 0 CLERK
2 0 MANAGER
SQL>
my first attempt would be to generate the insert statements using concatenate; and for ID, use max_id + rownumber;
how many rows does table2 have? if not millions, concatenate should be easy approach.
Note: This question is specifically for HSQLDB and Informix.
I want to insert new entry if not exists in the table and I know we can use exists query to insert based on existing entry.
Eg:
INSERT INTO test(column1)
(SELECT DISTINCT 3
FROM test
WHERE NOT EXISTS (SELECT * FROM test WHERE column1 =3));
Problem is: The EXISTS condition is used in combination with a subquery and is considered to be met, if the subquery returns at least one row. Then only we can use in a SELECT, INSERT, UPDATE, or DELETE statement.
This is the CREATE table statement:
CREATE TABLE test(column1 int)
This is the INSERT statement for HSQLDB. It uses the SQL Standard syntax and should work with Informix as well:
INSERT INTO test(column1)
SELECT * FROM (VALUES (3))
WHERE NOT EXISTS (SELECT * FROM test WHERE column1 =3)
This is the SELECT statement to show the rows in the table
SELECT * FROM test
This is the result of the SELECT
COLUMN1
-------
3
1 row(s) in 0 ms
As Informix does not support the VALUES table constructor, you need to create a separate table with only one row, similar to Oracle's DUAL table. You then use this table inside the SELECT.
INSERT INTO test(column1)
SELECT 3 FROM single_row_table
WHERE NOT EXISTS (SELECT * FROM test WHERE column1 =3)
I just want to know how many rows are inserted in a table by using SQL only.
For Example: consider 2 tables TT and TT1 and I want to insert into TT1 using TT table like this:
INSERT INTO TT1
SELECT *
FROM TT
WHERE 1=1;
after executing above statement I want to know how many rows are inserted? by using Oracle SQL only. Is there any way?
The PL/SQL expression SQL%ROWCOUNT may do what you want. You would need to phrase this as:
BEGIN
INSERT INTO TT1
SELECT *
FROM TT
WHERE 1=1;
DBMS_OUTPUT.PUT_LINE('Inserted ' || SQL%ROWCOUNT)
END;
In other words, it needs to go into a PL/SQL code block.
INSERT INTO TT1
SELECT *
FROM TT
WHERE 1=1;
The number of rows inserted are the number of rows returned by the SELECT statement. Which is nothing but the count of all the rows of table TT, since 1=1 is always TRUE, basically filtering nothing.
So, just do:
SELECT COUNT(*)
FROM TT;
Update Added an example
For example,
Let's say I have a table T which is empty:
SQL> create table t as select * from emp;
Table created.
I insert rows from EMP table to T:
SQL> insert into t select * from emp;
14 rows created.
I want to know how many rows were inserted, which is nothing but the rows returned by the SELECT statement.
SQL> select count(*) from emp;
COUNT(*)
----------
14
This is in pure SQL. i.e. you executed an insert, and now want to know how many rows actually inserted by the INSERT INTO..SELECT.
However, when you have a lot of insert statements happening programmatically i.e. in PL/SQL, then you will need SQL%ROWCOUNT for every INSERT.
If you are able to use PL/SQL you can do it like
declare
i number;
begin
INSERT INTO TT1 SELECT * FROM TT WHERE 1=1;
i := sql%rowcount;
end;
Otherwise as far as I know there is only way to do it is using SELECT COUNT, if there are records before this query just run SELECT COUNT twice, one before executing and one after query then just substract them.
Using Oracle 12c, I have, for example, 5 rows with values 1,2,3,4,5 in a PK column in one table TABLEA. I would like to insert into another table TABLEB the values but 3 times. So TABLE would have 15 rows with values 1,1,1,2,2,2,3,3,3,4,4,4,5,5,5 after the insert. How can I achieve this?
I'm trying to create a script that will insert values from TABLEA to TABLEB if they don't already exist there. Currently I am manually inserting into TABLEB each value from TABLEA 3 times.
You can use cross join. The query would look something like this:
insert into t(pk)
select pk
from table t2 cross join
(select 1 as n from dual union all select 2 from dual union all select 3 from dual
) n;