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.
Related
I have a somewhat complex query that I need to access for the IDs in order to delete from multiple tables, something along the lines of:
DELETE FROM Table1 WHERE ID IN ( -- Query here -- )
DELETE FROM Table2 WHERE ID IN ( -- Query here -- )
Would selecting the query into a temp table be more efficient than writing out the entire query twice, or is it just visually cleaner?
SELECT ( -- Query here -- ) INTO #Temp
DELETE FROM Table1 WHERE ID IN ( SELECT * FROM #Temp )
DELETE FROM Table2 WHERE ID IN ( SELECT * FROM #Temp )
Also, am open to other suggestions that I may have overlooked.
Thanks in advance
Completely agree with Jeroen Mostert. Try it and see. You could although try to use CTE for deletion or table variables and select distinct values of IDs there in case you have no distinct values of IDs in your query. And if you have a lot of data to delete, try to create additional indexes in temp table.
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.
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 am inserting records into the table and values are taken by using select query.
insert into my_table (....)
select a.name, b.age, c.id, d.address
from table1 a, table2 b, table3 c, table4 d
where a.age=23 and d.addredd like '%street%';
I would like to compare the rowcount of select query and rowcount of my_table (after insertion).
how to take rowcount of both without taking more processing time.
Thanks
For get total of inserted rows you can use SQL%ROWCOUNT.
DECLARE
BEGIN
insert into my_table (....)
select a.name, b.age, c.id, d.address
from table1 a, table2 b, table3 c, table4 d
where a.age=23 and d.addredd like '%street%';
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT);
END;
Edit:
Other way is create a function that return that value:
CREATE OR REPLACE FUNCTION get_count_inserted
RETURN NUMBER
IS
PRAGMA AUTONOMOUS_TRANSACTION;
RESULT NUMBER;
BEGIN
insert into my_table (....) -- Your query
select a.name, b.age, c.id, d.address
from table1 a, table2 b, table3 c, table4 d
where a.age=23 and d.addredd like '%street%';
RESULT := SQL%ROWCOUNT; --getting the count
COMMIT;
RETURN RESULT; --returning result
END;
Once function is created you can query it like this:
SELECT get_count_inserted FROM DUAL; --this will return total of rows inserted
how to take rowcount of both without taking more processing time.
The time to take the COUNT before and after the INSERT would be less than the time you took to post the question :-)
So, don't make things complicated, simply query for COUNT of ROWS before and after the INSERT into the table. No need to count the rows for select since the difference of number of rows before and after insert would be same as that of the select. If you still want to verify, you could take the count of select and check the difference, it would turn out to be same.
Unnecessarily introducing PL/SQL just to use SQLâ„…ROWCOUNT is not a good idea. Plain insert should be done in plain SQL.
How would I store the result of a select statement so I can reuse the results with an in clause for other queries? Here's some pseudo code:
declare
ids <type?>;
begin
ids := select id from table_with_ids;
select * from table1 where id in (ids);
select * from table2 where id in (ids);
end;
... or will the optimizer do this for me if I simply put the sub-query in both select statements?
EDIT: Here's more information about the structure of my tables.
Basically table1 is a standard table with the id being the primary key. While table2 has a 3-column primary key with id being one of those columns. In my case the id in table2 will appear in three rows.
You could use a SQL table object to store the result of the select and reuse it. It will consume more memory and will probably be efficient only if the first SELECT takes a lot of time.
CREATE TYPE tab_number IS TABLE OF NUMBER;
/
You would use it with a BULK COLLECT INTO clause:
DECLARE
ids tab_number;
BEGIN
SELECT id BULK COLLECT INTO ids FROM table_with_ids;
SELECT * /*into ??*/
FROM table1
WHERE id IN (SELECT column_value FROM TABLE(ids));
SELECT * /*into ??*/
FROM table2
WHERE id IN (SELECT column_value FROM TABLE(ids));
END;
In version 9i and before you would need to use CAST to query the table:
SELECT *
FROM table2
WHERE id IN (SELECT column_value FROM CAST (TABLE(ids) AS tab_number));
Alternatively, you could use a GLOBAL TEMPORARY TABLE to store the intermediate result set.