Regarding multiple insertion of rows through single query.(oracle) - database

Is the mechanism used in multiple insertion of rows in the table through single query is same as that of inserting single row with a single query.If not what is the exact mechanism?

If you are fetching the data from an existing table, you can use INSERT INTO TABLE3 ( SELECT * FROM TABLE1 UNION SELECT * FROM TABLE2 ....) to fetch and insert the data in a single go.
SQL> SELECT * FROM SCOTT.EMP WHERE JOB = 'ANALYST1';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO GENDER
---------- ---------- --------- ---------- --------- ---------- ---------- ---------- --------
8909 LUTHAR ANALYST1 7698 22-JUL-99 1232 788 50 F
8999 AMAN ANALYST1 7698 22-JUL-99 8569 788 50 M
7788 SCOTT ANALYST1 7566 19-APR-87 3000 150 M
7902 2 ANALYST1 7566 03-DEC-81 3000 M
SQL> SELECT * FROM SCOTT.EMP WHERE JOB = 'MANAGER';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO GENDER
---------- ---------- --------- ---------- --------- ---------- ---------- ---------- ---------
7566 5 MANAGER 7839 02-APR-81 2975 150 F
7698 10000 MANAGER 7839 01-MAY-81 2850 150 F
7782 CLARK MANAGER 7839 09-JUN-81 2450 150 F
SQL> CREATE TABLE EMP1 AS ( SELECT * FROM SCOTT.EMP WHERE 1=2);
Table created.
SQL> SELECT * FROM EMP1;
no rows selected
SQL> INSERT INTO EMP1 ( SELECT * FROM SCOTT.EMP WHERE JOB = 'ANALYST1'
2 UNION
3 SELECT * FROM SCOTT.EMP WHERE JOB = 'MANAGER');
7 rows created.
SQL> SELECT * FROM EMP1;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO GENDER
---------- ---------- --------- ---------- --------- ---------- ---------- ---------- --------
7566 5 MANAGER 7839 02-APR-81 2975 150 F
7698 10000 MANAGER 7839 01-MAY-81 2850 150 F
7782 CLARK MANAGER 7839 09-JUN-81 2450 150 F
7788 SCOTT ANALYST1 7566 19-APR-87 3000 150 M
7902 2 ANALYST1 7566 03-DEC-81 3000 M
8909 LUTHAR ANALYST1 7698 22-JUL-99 1232 788 50 F
8999 AMAN ANALYST1 7698 22-JUL-99 8569 788 50 M
7 rows selected.

You can chain many SQL statements in a single Oracle query by separating each SQL command with a semicolon. For instance:
INSERT INTO table VALUES(1,2); INSERT INTO table VALUES(3,4);

Related

Dynamic tablename to %rowtype

In oracle is it possible to dynamically assign the table name with Rowtype anchor element.
If not is there any other way to achieve this scenario ?
I'm not sure what "scenario" it is, but - to me - looks like function that accepts table name as a parameter and returns ref cursor might be what you're looking for. Here's an example.
SQL> create or replace function f_test (par_table_name in varchar2)
2 return sys_refcursor
3 is
4 rc sys_refcursor;
5 begin
6 open rc for 'select * from ' || dbms_assert.sql_object_name(par_table_name);
7 return rc;
8 end;
9 /
Function created.
Testing: pass DEPT table name, and you'll get its contents:
SQL> select f_test('dept') from dual;
F_TEST('DEPT')
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
Now pass EMP table name:
SQL> select f_test('emp') from dual;
F_TEST('EMP')
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17.12.80 800 20
7499 ALLEN SALESMAN 7698 20.02.81 1600 300 30
7521 WARD SALESMAN 7698 22.02.81 1250 500 30
7566 JONES MANAGER 7839 02.04.81 2975 20
7654 MARTIN SALESMAN 7698 28.09.81 1250 1400 30
7698 BLAKE MANAGER 7839 01.05.81 2850 30
7782 CLARK MANAGER 7839 09.06.81 2450 10
7788 SCOTT ANALYST 7566 09.12.82 3000 20
7839 KING PRESIDENT 17.11.81 5000 10
7844 TURNER SALESMAN 7698 08.09.81 1500 30
7876 ADAMS CLERK 7788 12.01.83 1100 20
7900 JAMES CLERK 7698 03.12.81 950 30
7902 FORD ANALYST 7566 03.12.81 3000 20
7934 MILLER CLERK 7782 23.01.82 1300 10
14 rows selected.
SQL>

How to correct the history record

I want to update history data in oracle database.
emp table
ID SALE_COM UPDATEDATE SALES_DT
4173 40 09-APR-2016 20:04:07 null
4173 40 20-SEP-2016 20:04:11 null
4173 30 06-OCT-2016 20:04:07 null
4173 30 14-OCT-2016 20:04:07 null
4173 30 26-MAR-2017 20:50:41 null
emp_hist
EMP_ID FIN_Y_ID PRD_SEQ FIELD_VALUE FIN_DATE
2167 13 4 30 28/09/14 0:00
OUTPUT
4173 30 06-OCT-2016 20:04:07 28/09/14 0:00
I hesitate to answer this without the problem being more clearly defined, but here's my interpretation:
There are two tables: emp and emp_hist
The 2167 shown in emp_hist in the original post is incorrect and should actually be 4173
When EMP.SALES_COM is updated, you want to update EMP.SALES_DT from the value of EMP_HIST.FIN_DATE where EMP.ID = EMP_HIST.EMP_ID
Assuming EMP_HIST.EMP_ID is unique, you could create a trigger on EMP that does #3 above:
SQL> SELECT id, sale_com, TO_CHAR(updatedate, 'DD-MON-YYYY HH24:MI:SS') updatedate,
2 TO_CHAR(sales_dt, 'DD/MM/YY HH24:MI') sales_dt
3 FROM emp;
ID SALE_COM UPDATEDATE SALES_DT
---------- ---------- ----------------------------- --------------
4173 40 09-APR-2016 20:04:07
4173 40 20-SEP-2016 20:04:11
4173 30 06-OCT-2016 20:04:07
4173 30 14-OCT-2016 20:04:07
4173 30 26-MAR-2017 20:50:41
SQL> SELECT emp_id, FIN_Y_ID, PRD_SEQ, FIELD_VALUE, TO_CHAR(FIN_DATE, 'YY/MM/DD HH24:MI') fin_date
2 FROM emp_hist;
EMP_ID FIN_Y_ID PRD_SEQ FIELD_VALUE FIN_DATE
---------- ---------- ---------- ----------- --------------
4173 13 4 30 14/09/28 00:00
SQL> CREATE OR REPLACE TRIGGER emp_upd_sale_com BEFORE UPDATE ON emp FOR EACH ROW
2 BEGIN
3 SELECT fin_date
4 INTO :new.sales_dt
5 FROM emp_hist
6 WHERE emp_id = :old.id;
7 END;
Trigger EMP_UPD_SALE_COM compiled
SQL> UPDATE emp SET sale_com = 30
2 WHERE id = 4173 AND updatedate = TO_DATE('06-OCT-2016 20:04:07', 'DD-MON-YYYY HH24:MI:SS');
1 row updated.
SQL> SELECT id, sale_com, TO_CHAR(updatedate, 'DD-MON-YYYY HH24:MI:SS') updatedate,
2 TO_CHAR(sales_dt, 'DD/MM/YY HH24:MI') sales_dt
3 FROM emp;
ID SALE_COM UPDATEDATE SALES_DT
---------- ---------- ----------------------------- --------------
4173 40 09-APR-2016 20:04:07
4173 40 20-SEP-2016 20:04:11
4173 30 06-OCT-2016 20:04:07 28/09/14 00:00 <<<< Updated row
4173 30 14-OCT-2016 20:04:07
4173 30 26-MAR-2017 20:50:41

Select group that have certain distinct value

WIth the below table, i want to select the IDNO that has only one type 4001 which is IDNO 2001 so that I can determine and update the total_owe to '0.00'.
IDNO Type Money Total_owe
---- ----- -------- ---------
1001 300 900.00 1900.00
1001 300 200.00 1900.00
1001 300 800.00 1900.00
1001 4001 200.00 1900.00
2001 4001 100.00 0.00
2001 4001 100.00 0.00
3001 300 100.00 200.00
3001 300 100.00 200.00
How do I modify the below query so that it only select IDNO that have only one type '4001' ?
select * from table group by IDNO having count(distinct type) = 1
I don't see anything for color type or the value green but the below query should return what you want
select *
from YourTable
where IDNO in (select IDNO from YourTable group by IDNO having count(distinct Type) = 1)
and Type = 4001

Oracle based PIVOT with multiple columns group

Using the following tables,
Productivity:
PRODUCTIVITYID PDATE EMPLOYEEID ROOMID ROOMS_SOLD SCR
81 03/26/2016 7499 21 56 43
82 03/26/2016 7566 42 - -
102 03/26/2016 7499 22 434 22
101 03/26/2016 7566 21 43 53
ProductivityD:
PRODUCTIVITYID WORKHRS MEALPANELTY DESCRIPTION
2 50 4 -
21 6.4 1 -
102 6 - -
81 1.32 - -
101 3.6 - -
Rooms:
ID ROOM PROPERTCODE
22 102 6325
41 103 6325
42 104 6325
43 105 6325
EMP:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7566 JONES MANAGER 7839 04/02/1981 2975 - 20
7788 SCOTT ANALYST 7566 12/09/1982 3000 - 20
7902 FORD ANALYST 7566 12/03/1981 3000 - 20
7369 SMITH CLERK 7902 12/17/1980 800 - 20
7499 ALLEN SALESMAN 7698 02/20/1981 1600 300 30
The following query is generating below output but I need to group employees and sum workhrs and then pivot RM_ROOM and RM_SCR
WITH pivot_data AS (
SELECT eNAME,workhrs,room, 'RM' as RM,SCR from PRODUCTIVITY p,PRODUCTIVITYd d, emp e, ROOMS R
where p.PRODUCTIVITYID=d.PRODUCTIVITYID and e.empno=p.employeeid
AND R.ID=P.ROOMID
)
SELECT *
FROM pivot_data
PIVOT (
MIN(room) as room,min(scr) as SCR --<-- pivot_clause
FOR RM--<-- pivot_for_clause
IN ('RM') --<-- pivot_in_clause
)
Current Output:
ENAME WORKHRS 'RM'_ROOM 'RM'_SCR
JONES 3.6 101 53
ALLEN 6 102 22
ALLEN 1.32 101 43
Desired Output:
ENAME WORKHRS 'RM'_ROOM 'RM'_SCR 'RM'_ROOM 'RM'_SCR
JONES 3.6 101 53 - -
ALLEN 7.32 101 43 102 22
You are pivoting on a fixed value, the string literal 'RM', so you're really not doing anything useful in the pivot - the output is the same as you'd get from running the 'pivot_data' query on its own:
SELECT eNAME,workhrs,room, SCR from PRODUCTIVITY p,PRODUCTIVITYd d, emp e, ROOMS R
where p.PRODUCTIVITYID=d.PRODUCTIVITYID and e.empno=p.employeeid
AND R.ID=P.ROOMID;
ENAME WORKHRS ROOM SCR
----- ---------- ---------- ----------
JONES 3.6 101 53
ALLEN 1.32 101 43
ALLEN 6 102 22
You want the aggregate workhrs for each employee, and a pivot of the rooms they sold. If you change that query to get the analytic sum of workhrs and a ranking of the room/scr values (and using modern join syntax) you get:
select e.ename, r.room, p.scr,
sum(d.workhrs) over (partition by e.ename) as wrkhrs,
rank() over (partition by e.ename order by r.room, p.scr) as rnk
from productivity p
join productivityd d on d.productivityid = p.productivityid
join emp e on e.empno=p.employeeid
join rooms r on r.id = p.roomid;
ENAME ROOM SCR WRKHRS RNK
----- ---------- ---------- ---------- ----------
ALLEN 101 43 7.32 1
ALLEN 102 22 7.32 2
JONES 101 53 3.6 1
You can then pivot on that generated rnk number:
with pivot_data as (
select e.ename, r.room, p.scr,
sum(d.workhrs) over (partition by e.ename) as wrkhrs,
rank() over (partition by e.ename order by r.room, p.scr) as rnk
from productivity p
join productivityd d on d.productivityid = p.productivityid
join emp e on e.empno=p.employeeid
join rooms r on r.id = p.roomid
)
select *
from pivot_data
pivot (
min(room) as room, min(scr) as scr --<-- pivot_clause
for rnk --<-- pivot_for_clause
in (1, 2, 3) --<-- pivot_in_clause
);
ENAME WRKHRS 1_ROOM 1_SCR 2_ROOM 2_SCR 3_ROOM 3_SCR
----- ---------- ---------- ---------- ---------- ---------- ---------- ----------
ALLEN 7.32 101 43 102 22
JONES 3.6 101 53
You need to know the maximum number of rooms any employee may have - i.e. the highest rnk could ever be - and include all of those in the in clause. Which means you're likely to end up with empty columns, as in this example where there is no data for 3_room or 3_scr. You can't avoid that though, unless you get an XML result or generate the query dynamically.
What you are saying makes no sense. What do you mean by "pivot RM_ROOM"? So I have to guess. I am guessing you want to group employees and sum workhrs, and then pivot the result. The "Output" you show seems to be the output for pivot_data, your subquery.
Your answer will only have eNAME and for each of them, a count of hours worked. So you don't need to SELECT the room numbers in the pivot_data subquery. You only need eNAME and workhrs. Then it is a simple matter of using the PIVOT syntax:
WITH pivot_data AS (
SELECT eNAME, workhrs FROM PRODUCTIVITY p,PRODUCTIVITYd d, emp e, ROOMS R
where p.PRODUCTIVITYID=d.PRODUCTIVITYID and e.empno=p.employeeid
AND R.ID=P.ROOMID
)
SELECT *
FROM pivot_data
PIVOT (
SUM(workhrs)
FOR eNAME IN ('JONES', 'ALLEN')
)
/
Output:
'JONES' 'ALLEN'
---------- ----------
3.6 7.32

Oracle INSERT ALL with SELECT giving invalid specification error

I want to use the INSERT ALL statement to insert 2 rows into 2 different tables.
But if I want to insert values by myself, the below query works fine.
insert all
into REGIONS values (5,'Africa')
into JOBS values ('ZZZZ','Shop Sleeper',1000,1000)
select * from DUAL;
However if I want to duplicate a row with a different primary key value, the below statement gives me ORA-01747 error.
insert all
into REGIONS (select :REGION_ID,REGION_NAME from REGION where REGION_ID = 4)
into JOBS (select :JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY where JOB_ID = 'ST_CLERK')
select * from DUAL;
I dont know how to rectify the query. Please help.
insert all
into REGIONS (select :REGION_ID,REGION_NAME from REGION where REGION_ID = 4)
into JOBS (select :JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY where JOB_ID = 'ST_CLERK')
select * from DUAL;
The above INSERT ALL is incorrect syntactically. You must mention the VALUES keyword, and list the required columns you want to select from the table to insert the rows.
The correct syntax is:
INSERT ALL
INTO REGIONS VALUES
(
REGION_ID,
REGION_NAME
)
INTO JOBS VALUES
(
JOB_ID,
JOB_TITLE,
MIN_SALARY,
MAX_SALARY
)
SELECT REGION_ID,
REGION_NAME,
JOB_ID,
JOB_TITLE,
MIN_SALARY,
MAX_SALARY
FROM region, jobs
WHERE region.column=job.column --> Jon with the required key
AND ...; --> Put the required filter conditions
Test Case #1
With same columns in destination table.
SQL> CREATE TABLE tab1(a NUMBER, b varchar2(20));
Table created.
SQL> CREATE TABLE tab2(a NUMBER, b varchar2(20));
Table created.
SQL>
SQL> INSERT ALL
2 INTO tab1(A, b) VALUES(empno, ename)
3 INTO tab2(A, b)VALUES(empno, ename)
4 SELECT empno, ename FROM emp;
28 rows created.
SQL>
So, all rows are inserted into the tables tab1 and tab2 respectively. Let's see:
SQL> SELECT * FROM tab1;
A B
---------- --------------------
7369 SMITH
7499 ALLEN
7521 WARD
7566 JONES
7654 MARTIN
7698 BLAKE
7782 CLARK
7788 SCOTT
7839 KING
7844 TURNER
7876 ADAMS
7900 JAMES
7902 FORD
7934 MILLER
14 rows selected.
SQL> SELECT * FROM tab2;
A B
---------- --------------------
7369 SMITH
7499 ALLEN
7521 WARD
7566 JONES
7654 MARTIN
7698 BLAKE
7782 CLARK
7788 SCOTT
7839 KING
7844 TURNER
7876 ADAMS
7900 JAMES
7902 FORD
7934 MILLER
14 rows selected.
SQL>
Test Case #2
With different columns in destination table.
SQL> CREATE TABLE tab1(a NUMBER);
Table created.
SQL> CREATE TABLE tab2(b varchar2(20));
Table created.
SQL>
SQL> INSERT ALL
2 INTO tab1(A) VALUES(empno)
3 INTO tab2(b)VALUES(ename)
4 SELECT empno, ename FROM emp;
28 rows created.
Let's see:
SQL> SELECT * FROM tab1;
A
----------
7369
7499
7521
7566
7654
7698
7782
7788
7839
7844
7876
7900
7902
7934
14 rows selected.
SQL> SELECT * FROM tab2;
B
--------------------
SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER
14 rows selected.
SQL>
Test Case #3
With different columns in destination table and different columns in source table
SQL> CREATE TABLE tab1(A VARCHAR2(20));
Table created.
SQL> CREATE TABLE tab2(b NUMBER);
Table created.
SQL>
SQL> INSERT ALL
2 INTO tab1(A) VALUES(ename)
3 INTO tab2(b)VALUES(deptno)
4 SELECT e.ename ename, d.deptno deptno FROM emp e, dept d
5 where e.deptno = d.deptno;
28 rows created.
SQL>
Let's see:
SQL> SELECT * FROM tab1;
A
--------------------
SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER
14 rows selected.
SQL> SELECT * FROM tab2;
B
----------
20
30
30
20
30
30
10
20
10
30
20
30
20
10
14 rows selected.
SQL>
Try this...
INSERT ALL
INTO REGIONS(REGION_ID,REGION_NAME)
SELECT REGION_ID,REGION_NAME from REGION where REGION_ID = 4
INTO JOBS(JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY)
SELECT JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY where JOB_ID = 'ST_CLERK'
SELECT * FROM DUAL;

Resources