How to update One table column values with another table's column values? [duplicate] - oracle

This question already has answers here:
Update rows in one table with data from another table based on one column in each being equal
(5 answers)
Closed 9 years ago.
i have table called Student with columns uniquename, age,department,city,Homecountry and another table called Employee with columns uniquename, exp,qualification, Homecountry.
now i want to update Student table's department column with Employee table's qualification column values under the where condition Student.uniquename = Employee.uniquename and Student.Homecountry = Employee.Homecountry.
please help me to write the update statement.

This kind of query is called a correlated sub query. For your requirement, the query would be as below....
update students s
set s.department = (
select e.qualification
from employee e
where s.uniquename = e.uniquename
and s.Homecountry = e.Homecountry
);
updating this post based on your replies below.
Again, going forward, always post the create table and insert statements (and the expected results) to reproduce your case. If you don't see the expected results or if you see an erro when you execute the query, post the exact message instead of just saying "not working". Here is the results of my sqlplus session.
---create table and insert statements
create table student(
name varchar2(20),
age number,
department varchar2(3),
HomeCountry varchar2(10)
);
Table created.
create table employee5(
name varchar2(20),
exp number,
qualification varchar2(3),
homecountry varchar2(10)
);
Table created.
insert into student values ('Mohan',25,'EEE','India');
insert into student values ('Raja',27,'EEE','India');
insert into student values ('Ahamed',26,'ECE','UK');
insert into student values ('Gokul',25,'IT','USA');
commit;
insert into employee5 values ('Mohan',25,'ECE','India');
insert into employee5 values ('Raja',24,'IT','India');
insert into employee5 values ('Palani',26,'ECE','USA');
insert into employee5 values ('Sathesh',29,'CSE','CANADA');
insert into employee5 values ('Ahamed',28,'ECE','UK');
insert into employee5 values ('Gokul',29,'EEE','USA');
commit;
Before updating the data...
SQL> select * from student;
NAME AGE DEP HOMECOUNTR
-------------------- ---------- --- ----------
Mohan 25 EEE India
Raja 27 EEE India
Ahamed 26 ECE UK
Gokul 25 IT USA
SQL> select * from employee5;
NAME EXP QUA HOMECOUNTR
-------------------- ---------- --- ----------
Mohan 25 ECE India
Raja 24 IT India
Palani 26 ECE USA
Sathesh 29 CSE CANADA
Ahamed 28 ECE UK
Gokul 29 EEE USA
Update statement and results
1 update student s set s.age =
2 ( select e.exp
3 from employee5 e
4 where e.name = s.name
5 and e.homecountry = s.homecountry
6* )
SQL> /
4 rows updated.
SQL> select * from student;
NAME AGE DEP HOMECOUNTR
-------------------- ---------- --- ----------
Mohan 25 EEE India
Raja 24 EEE India
Ahamed 28 ECE UK
Gokul 29 IT USA
SQL> commit;
Commit complete.

update student s
set s.age = (select e.exp
from employee5 e
where e.name = s.name
and e.homecountry = s.homecountry
and rownum < 2
)
where s.age in (select age from employee5)
It wont show the message subquery returns more than one record

Related

PL/SQL insert record using max function

Create a PL/SQL block to insert a new record into the Department table. Fetch the maximum department id from the Department table and add 10 to it; take this value for department id; 'TESTING' is the value for department name and CHN-102 is the value for Location ID.
Note: Use '/' to terminate your query before compilation and evaluation
Table name : Department
Column name | Data type | Constraints
DEPARTMENT_ID | NUMBER(5) | PK
DEPARTMENT_NAME | VARCHAR2(25) | NOT NULL
LOCATION_ID | VARCHAR2(15)
Sample Output:
DEPARTMENT_ID DEPARTMENT_NAME LOCATION_ID
------------- --------------- -----------
XXXX TESTING CHN-102
The way you described it, it would look like this:
SQL> declare
2 l_department_id department.department_id%type;
3 l_department_name department.department_name%type := 'TESTING';
4 l_location_id department.location_id%type := 'CHN-102';
5 begin
6 select nvl(max(department_id), 10)
7 into l_department_id
8 from department;
9
10 insert into department (department_id, department_name, location_id)
11 values (l_department_id + 10, l_department_name, l_location_id);
12 end;
13 /
PL/SQL procedure successfully completed.
SQL> select * From department;
DEPARTMENT_ID DEPARTMENT_NAME LOCATION_I
------------- -------------------- ----------
20 TESTING CHN-102
SQL>
Note, though, that MAX + 10 is a wrong approach. If two (or more) users run the same procedure at the same time, only the first one who commits changes will be able to do that; other user(s) will violate the primary key constraint because that department_id already exists (as it was inserted moments ago by someone else). Use a sequence instead.

Creating temporary table without knowing the columns in oracle

How to create a temporary table in oracle without knowing the number and name of columns.
For example:
Select columnA,columnB,* into temp_table from tableA.
Here,tableA maynot be a simple tablename but maybe derived from many queries.
How can this be achieved?Is there any alternative to this?
In Oracle, you have to first create a table, then insert into it. Or, create it directly (as in my example).
Note that I've created a "normal" table; if it were temporary, you could have chosen between a global or private (depending on database version you use).
For this discussion, I guess that it is just fine:
SQL> create table temp_table as
2 select a.*
3 from (select d.deptno, d.dname, e.ename --> this SELECT is your "tableA"
4 from emp e join dept d
5 on e.deptno = d.deptno
6 where job = 'CLERK'
7 ) a;
Table created.
SQL> select * from temp_table;
DEPTNO DNAME ENAME
---------- -------------------- ----------
10 ACCOUNTING MILLER
20 RESEARCH SMITH
20 RESEARCH ADAMS
30 SALES JAMES
SQL>
Alternatively, create a view and work with it:
SQL> create or replace view v_temp as
2 select d.deptno, d.dname, e.ename
3 from emp e join dept d
4 on e.deptno = d.deptno
5 where job = 'CLERK'
6 ;
View created.
SQL> select * from v_temp;
DEPTNO DNAME ENAME
---------- -------------------- ----------
10 ACCOUNTING MILLER
20 RESEARCH SMITH
20 RESEARCH ADAMS
30 SALES JAMES
SQL>
This statement creates temp_table which contains all columns and data from tableA and two other empty columns, varchar and numeric.
create table temp_table as
select cast (null as varchar2(10)) columnA,
cast (null as number(6)) columnB,
tableA.*
from tableA
If you need only structure, no data, then add:
where 1 = 0
I am not sure why you want to have a temp table as you do not know columns, but you can think of dynamic SQL to create table depending on columns required during your process and then drop it again. From my point of view I think it is not a good design.
I can suggest to think on using collection with 'x' number of columns with datatype as VARCHAR2. During transaction you can populate and process according to you need and it will also remain for that session.

How to create a unique id for an existing table in PL SQL?

The situation is that, when I import a file into the database, one of the first thing I usually do is to assign an unique ID for each record.
I normally do below in TSQL
ALTER TABLE MyTable
ADD ID INT IDENTITY(1,1)
I am wondering if there is something similar in PL SQL?
All my search result come back with multiple steps.
Then I'd like to know what PL SQL programmer typically do to ID records after importing a file. Do they do that?
The main purpose for me to ID these records is to trace it back after manipulation/copying.
Again, I understand there is solution there, my further question is whether PL SQL programmer actually do that, or there is other alternative which making this step not necessary in PL SQL?
OK then, as you're on Oracle 11g, there's no identity column there so - back to multiple steps. Here's an example:
I'm creating a table that simulates your imported table:
SQL> create table tab_import as
2 select ename, job, sal
3 from emp
4 where deptno = 10;
Table created.
Add the ID column:
SQL> alter table tab_import add id number;
Table altered.
Create a sequence which will be used to populate the ID column:
SQL> create sequence seq_imp;
Sequence created.
Update current rows:
SQL> update tab_import set
2 id = seq_imp.nextval;
3 rows updated.
Create a trigger which will take care about future inserts (if any):
SQL> create or replace trigger trg_bi_imp
2 before insert on tab_import
3 for each row
4 begin
5 :new.id := seq_imp.nextval;
6 end;
7 /
Trigger created.
Check what's in the table at the moment:
SQL> select * from tab_import;
ENAME JOB SAL ID
---------- --------- ---------- ----------
CLARK MANAGER 2450 1
KING PRESIDENT 5000 2
MILLER CLERK 1300 3
Let's import some more rows:
SQL> insert into tab_import (ename, job, sal)
2 select ename, job, sal
3 from emp
4 where deptno = 20;
3 rows created.
The trigger had silently populated the ID column:
SQL> select * From tab_import;
ENAME JOB SAL ID
---------- --------- ---------- ----------
CLARK MANAGER 2450 1
KING PRESIDENT 5000 2
MILLER CLERK 1300 3
SMITH CLERK 800 4
JONES MANAGER 2975 5
FORD ANALYST 3000 6
6 rows selected.
SQL>
Shortly: you need to
alter table and add the ID column
create a sequence
create a trigger
The end.
The answer given by #Littlefoot would be my recommendation too - but still I thought I could mention the following variant which will work only if you do not intend to add more rows to the table later.
ALTER TABLE MyTable add id number(38,0);
update MyTable set id = rownum;
commit;
My test:
SQL> create table tst as select * from all_tables;
Table created.
SQL> alter table tst add id number(38,0);
Table altered.
SQL> update tst set id = rownum;
3815 rows updated.
SQL> alter table tst add constraint tstPk primary key (id);
Table altered.
SQL>
SQL> select id from tst where id < 15;
ID
----------
1
2
3
4
5
6
7
8
9
10
11
ID
----------
12
13
14
14 rows selected.
But as mentioned initially,- this only fixes numbering for the rows you have at the time of the update - your'e not going to get new id values for new rows anytime later - if you need that, go for the sequence solution.
You can add an id column to a table with a single statement (Oracle 11g, see dbfiddle):
alter table test_
add id raw( 16 ) default sys_guid() ;
Example:
-- create a table without an id column
create table test_ ( str )
as
select dbms_random.string( 'x', 16 )
from dual
connect by level <= 10 ;
select * from test_ ;
STR
ULWL9EXFG6CIO72Z
QOM0W1R9IJ2ZD3DW
YQWAP4HZNQ57C2UH
EETF2AXD4ZKNIBBF
W9SECJYDER793MQW
alter table test_
add id raw( 16 ) default sys_guid() ;
select * from test_ ;
STR ID
ULWL9EXFG6CIO72Z 0x782C6EBCAE2D7B9FE050A00A02005D65
QOM0W1R9IJ2ZD3DW 0x782C6EBCAE2E7B9FE050A00A02005D65
YQWAP4HZNQ57C2UH 0x782C6EBCAE2F7B9FE050A00A02005D65
EETF2AXD4ZKNIBBF 0x782C6EBCAE307B9FE050A00A02005D65
W9SECJYDER793MQW 0x782C6EBCAE317B9FE050A00A02005D65
Testing
-- Are the id values unique and not null? Yes.
alter table test_
add constraint pkey_test_ primary key ( id ) ;
-- When we insert more rows, will the id be generated? Yes.
begin
for i in 1 .. 100
loop
insert into test_ (str) values ( 'str' || to_char( i ) ) ;
end loop ;
end ;
/
select * from test_ order by id desc ;
-- last 10 rows of the result
STR ID
str100 0x782C806E16A5E998E050A00A02005D81
str99 0x782C806E16A4E998E050A00A02005D81
str98 0x782C806E16A3E998E050A00A02005D81
str97 0x782C806E16A2E998E050A00A02005D81
str96 0x782C806E16A1E998E050A00A02005D81
str95 0x782C806E16A0E998E050A00A02005D81
str94 0x782C806E169FE998E050A00A02005D81
str93 0x782C806E169EE998E050A00A02005D81
str92 0x782C806E169DE998E050A00A02005D81
str91 0x782C806E169CE998E050A00A02005D81
Regarding your other questions:
{1} Then I'd like to know what PL SQL programmer typically do to ID records after importing a file. Do they do that? The main purpose for me to ID these records is to trace it back after manipulation/copying.
-> As you know, the purpose of an id is: to identify a row. We don't "do anything to IDs". Thus, your usage of IDs seems legit.
{2} Again, I understand there is solution there, my further question is whether PL SQL programmer actually do that, or there is other alternative which making this step not necessary in PL SQL?
-> Not quite sure what you are asking here. Although there is a ROWID() pseudocolumn (see documentation), we should not use it to identify rows.
"You should not use ROWID as the primary key of a table. If you delete
and reinsert a row with the Import and Export utilities, for example,
then its rowid may change. If you delete a row, then Oracle may
reassign its rowid to a new row inserted later."

Calculate total time in oracle

i have same problem like here
how to calculate sum time with data type char in oracle
but little different. i have 2 table like this :
table employee
emp_id emp_name emp_birth_date
123456 sacha 18/07/1980
Using this query
create table employee (emp_id char(10), emp_name char(10), emp_birth_date date);
insert into employee values ('123456', 'sacha', (TO_DATE('18/07/1980', 'dd/mm/yyyy')));
and table dept
table dept
emp_id emp_reg_date emp_time_in emp_time_off
123456 25/12/2011 10:00:00 19:00:00
using this query
create table dept (emp_id char(10), emp_reg_date date, emp_time_in char(10), emp_time_off char(10));
insert into dept values ('123456', (TO_DATE('25/12/2011', 'dd/mm/yyyy')), '10:00:00', '19:00');
all data type is char except birth_date and reg_date
i can display emp_id, emp_name, emp_reg_date, emp_time_in, emp_time_off using this query select employee.emp_id, employee.emp_name, dept.emp_date_reg, dept.emp_time_in, dept.emp_time_off from employee, dept where employee.emp_id = dept.emp_id;
but how to calculate total time in table dept for emp_time_in and emp_time_off for a day and a month?
What an awful design; what made you create EMP_TIME_IN and EMP_TIME_OFF VARCHAR2 columns? Those should have been DATE ones. I suggest you change that.
Meanwhile, you'll have to concatenate EMP_REG_DATE and those IN and OFF columns in order to get DATE value; then, by subtracting two dates, you'd get number of DAYS and - using a little bit of mathematics - get hours, minutes, or whatever you want.
For example:
SQL> create table test
2 (empno number,
3 emp_reg_date date,
4 emp_time_in varchar2(10),
5 emp_time_off varchar2(10));
Table created.
SQL> insert into test values (1, date '2018-03-20', '10:00', '19:00');
1 row created.
SQL> insert into test values (1, date '2018-03-21', '11:30', '12:30');
1 row created.
SQL> insert into test values (2, date '2018-03-25', '13:00', '16:20');
1 row created.
Employee 1 worked 9 hours + 1 hour = 10 hours in total.
Employee 2 worked 3 hours 20 minutes.
SQL> with dates as
2 (select
3 empno,
4 to_date(to_char(emp_reg_date, 'dd.mm.yyyy') || emp_time_in , 'dd.mm.yyyy hh24:mi') date_in,
5 to_date(to_char(emp_reg_date, 'dd.mm.yyyy') || emp_time_off, 'dd.mm.yyyy hh24:mi') date_off
6 from test
7 ),
8 summary as
9 (select empno,
10 sum(date_off - date_in) diff_days
11 from dates
12 group by empno
13 )
14 select empno,
15 trunc(diff_days * 24) hours,
16 round((diff_days * 24 - trunc(diff_days * 24)) * 60) minutes
17 from summary;
EMPNO HOURS MINUTES
---------- ---------- ----------
1 10 0
2 3 20
SQL>
Note that there's practically no control over what you enter into VARCHAR2 columns TIME_IN and TIME_OUT; what prevents you from entering AX:FM or 99:45 or A-b-e_XF in there? All those are valid strings, but invalid times.
Once again: fix data model.

Combining two stored procedures into a single one using some joins

I am very new to Oracle; I have written two stored procedures where they have both different parameters. I would like to combine the queries in that two stored procedures into single query in a single stored procedure, and make sure it supports any criteria.
These are the stored procedures:
procedure usp_testsp1(RC1 OUT RCT1,
in_dep_Id IN number,
in_Org_id IN number,
in_emp_no IN number)
is
begin
select emp.Name as name,select emp.phone as phone,select emp.Race as
race
from employee emp
JOIN
Project prj ON
emp.ProjectId=prj.ProjectId
JOIN Project_Org Prorg
ON prj.ProjectId=Prorg.ProjectId
JOIN Organization Org1
ON Prorg.OrgId=Org1.OrgId
JOIN Organization Org2
ON emp.OrgId=Org2.OrgId
AND Org2.OrgType=0
WHERE (upper(emp.emp_No) in (in_emp_No ))
AND Prorg.OrgId=in_Org_id
AND Org2.OrgId=in_dep_Id
end;
procedure usp_testsp2(RC1 OUT RCT1,
in_dep_Id IN number,
in_Org_id IN number,
in_vendor_id IN raw,
in_vendor_startdate IN date,
in_vendor_enddate IN date)
is
begin
OPEN RC1 FOR
select emp.Name as name,select emp.phone as phone,select emp.Race as
race
from
from employee emp
JOIN
Project prj ON
emp.ProjectId=prj.ProjectId
JOIN Project_Org Prorg
ON prj.ProjectId=Prorg.ProjectId
JOIN Organization Org1
ON Prorg.OrgId=Org1.OrgId
JOIN Organization Org2
ON emp.OrgId=Org2.OrgId
AND Org2.OrgType=0
INNER JOIN vendor_Emp
ON emp.employeeid=vendor_emp.employeeid
INNER JOIN Vendor
ON Vendor.VendorId=Vendor_emp.VendorId
WHERE Prorg.OrgId=in_Org_id
AND Org2.OrgId=in_dep_Id
AND Vendor.VendorId=in_vendor_id
AND vendor.StartDate=in_vendor_startdate AND Vendor.EndDate=in_vendor_enddate
end;
My objective is to combine the queries within these two separate procedures into a single query such that if I combine all the parameters, I have in_emp_no, in_vendor_id, in_vendor_startdate, in_vendor_enddate apart from the common parameters any of the parameters can be null and I want to make sure that those things won't affect the rest of the query even though its not null
For ex i have only in_emp_no ='xxxx' and common inputs rest of the params like
in_vendor_id etc is null.
I would like to make my query to work even with single paramter to filter the result set
NOTEWithout using Dynamic SQL
Thanks
BJ
You can make columns in the query behave as optional, as far as your join's go, you may need to play with various combinations to make sure everything works.
Sample Table
create table sqltest (
empid number,
name varchar2(10),
orgid number,
depid number,
vendorid number);
insert into sqltest values(1,'BoB',1,1,21);
insert into sqltest values(2,'Chuck',1,1,21);
insert into sqltest values(3,'Mary',1,2,21);
insert into sqltest values(4,'Jane',1,2,22);
insert into sqltest values(5,'Rick',2,1,22);
insert into sqltest values(6,'Samir',2,6,23);
insert into sqltest values(7,'Kirk',3,6,23);
insert into sqltest values(8,'Alex',3,9,23);
commit;
Sample Proc
create or replace procedure calltest (
rc1 out SYS_REFCURSOR,
pempid number,
porgid number,
pdepid number,
pvendorid number)
is
begin
open rc1 for
select * from sqltest
where
(pempid IS NULL OR empid = pempid) and
(porgid IS NULL OR orgid = porgid) and
(pdepid IS NULL OR depid = pdepid) and
(pvendorid IS NULL OR vendorid = pvendorid);
end;
Sample Call
set autoprint on;
var vcur refcursor;
declare
begin
calltest(rc1=>:vcur,pempid=>NULL,porgid=>1,pdepid=>NULL,pvendorid=>NULL);
--calltest(rc1=>:vcur,pempid=>NULL,porgid=>1,pdepid=>2,pvendorid=>NULL);
--calltest(rc1=>:vcur,pempid=>NULL,porgid=>1,pdepid=>2,pvendorid=>22);
--calltest(rc1=>:vcur,pempid=>NULL,porgid=>NULL,pdepid=>NULL,pvendorid=>23);
end;
Sample Output 1
VCUR
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EMPID NAME ORGID DEPID VENDORID
--------------------------------------- ---------- --------------------------------------- --------------------------------------- ---------------------------------------
1 BoB 1 1 21
2 Chuck 1 1 21
3 Mary 1 2 21
4 Jane 1 2 22
Sample Output 2
VCUR
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EMPID NAME ORGID DEPID VENDORID
--------------------------------------- ---------- --------------------------------------- --------------------------------------- ---------------------------------------
3 Mary 1 2 21
4 Jane 1 2 22
Sample Output 3
VCUR
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EMPID NAME ORGID DEPID VENDORID
--------------------------------------- ---------- --------------------------------------- --------------------------------------- ---------------------------------------
4 Jane 1 2 22
Sample Output 4
VCUR
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EMPID NAME ORGID DEPID VENDORID
--------------------------------------- ---------- --------------------------------------- --------------------------------------- ---------------------------------------
6 Samir 2 6 23
7 Kirk 3 6 23
8 Alex 3 9 23

Resources