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.
Related
I'm running select statements in a loop with a cursor to collect data from different tables;
Quick (NOT WORKING) example;
select DISTINCT(ordernr) from orders
INSERT INTO newtable (select Crs.ordernr as ordernr, value1 as value from table2 where table2.ordernr = Crs.ordernr );
INSERT INTO newtable (select Crs.ordernr as ordernr, value2 as value from table3 where tabel3.ordernr=Crs.ordernr ;
)
LOOP
END LOOP;
END;
What I could like is just one insert statement which insert just the biggest value of boths select statements.
I've tried to work with greatest function in my loop but i'm running stuck. Both datatypes are the same for value1 and value2
insert into newtable(select crs.ordernr as ordernr, greatest
(
select value1 as value from table1 where condition=1, select value2 as value from table2 where condition=1)
)
);
Is it possible with a select case or other way to return only one value based on conditions? For example the biggest value of value1 or value2?
You can use the greatest function and provide subqueries to it, but - follow the syntax, i.e. enclose each of them (select statements) into its own parenthesis.
Something like this:
SQL> select greatest ( (select max(sal) from emp where job = 'CLERK'),
2 (select max(sal) from emp where job = 'ANALYST')
3 ) greatest_salary
4 from dual;
GREATEST_SALARY
---------------
3450
SQL>
I have no idea what is this:
insert into newtable(select crs.ordernr as ordernr
-----------------------------
supposed to do; what is crs? Where's the from clause?
From Oracle 12, you can use:
INSERT INTO newtable (ordernr, value)
SELECT *
FROM (
SELECT Crs.ordernr as ordernr,
value1 as value
FROM table2
WHERE table2.ordernr = Crs.ordernr
UNION ALL
SELECT Crs.ordernr,
value2
FROM table3
WHERE table3.ordernr=Crs.ordernr
)
ORDER BY value DESC
FETCH FIRST ROW ONLY;
This will mean that if you extend the query to extract more columns and you want the highest of one column and the corresponding values of the other columns then the values will all come from that one row with the highest value.
db<>fiddle here
I am facing a hive problem.
I will get a 0 or 1 after from sql
"select count(*) from table1 where ..."
If the result is 1, then I will execute the sql
"Insert Into table2 partition(d) (select xxxx from table 1 where ...
group by t)"
Otherwise do nothing.
My question is how can I write these two sql together into one sql. I am only allowed to write a single long sql.
I tried to put the first sql into the where condition in sql2, but it throwed an error said it's not supported to operat on table1 in the subquery (couldn't remember clearly, something like this).
It sounds like a very easy question for experienced programmers, but I just started lerning hive for 2 days.
If select in insert overwrite table partition does not returns rows, nothing is being overwritten.
So, just calculate your count in the same dataset and filter by it, use analytics funtion if you want to aggregate data on different level before insert
Insert Into table2 partition(d)
select col1, col2, sum(col3), etc, etc, partition_col
from
(
select --some columns here,
--Assign the same count to all rows
count(case when your_boolean_condition then 1 else null end) over () as cnt
from table 1
) s
where cnt=1 --If this is not satisfied, no overwrite will happen
AND more_conditions
group by ...
Another approach possible is to use cross-join with your count:
insert Into table2 partition(d)
select xxxx ... ... ..., partition_column as d
from
(
select t.*, c.cnt
table1 t cross join (select count(*) cnt from table1 where condition) c
)s
where cnt=1 <and another_condition>
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.
I have a sql statement SELECT * FROM table1 WHERE ....; SELECT * FROM table2 WHERE ....
What I want is to get the results from the first select statement if it returns results, but if it doesn't, I want to ignore it and just get the results from the second select statement. Is there a way I can do this just using SQL?
I'm getting this returned to me as a datatable, using a dataadapter to fill the datatable from the above SQL statement. I can't change that part, or switch to filling a dataset (for reasons I won't get into, but it just can't be changed).
Assuming both queries return the same number and type of columns, one way to do this would be:
select * from table1 where ... /* query 1 conditions */
union all
select * from table2 where ... /* query 2 conditions */
and not exists
(select 1 from table1 where ... /* query 1 conditions */)
A couple options. You can check the count first:
If (select count(*) from table1 where...) > 0
begin
select * from table1 where...
end
else
begin
select * from table2 where...
end;
if both result sets are identical in structure, you can save the count check (and thus improve performance) by using a temp table:
create table #temp (col1 int, col2 varchar(10), ...);
insert #temp
select * from table1 where...;
if ##rowcount = 0
begin
insert #temp
select * from table2 where...
end;
select * from #temp;
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.