Create table as Select, then Update statement with JOIN in Oracle - sql

I'm using Oracle HR database.
I was wondering why the following query isn't working:
create table ecopy
as select *
from employees;
create table dcopy
as select *
from departments;
UPDATE (select d.location_id, e.salary
from ecopy e inner join dcopy d
on e.department_id=d.department_id)
set salary = salary+1
where location_id = 1800
SQL Error: ORA-01779: cannot modify a column which maps to a non key->preserved table
While the this one, on the origin tables is doing it's job:
UPDATE (select d.location_id, e.salary
from employees e inner join departments d
on e.department_id=d.department_id)
set salary = salary+1
where location_id = 1800
Could anyone explain it to me?

Here is the explanation:
In your real life your relation supported by keys - reference constraint
employee.department_id(MANY) = departments.department_id(ONE)
In the case of UPDATE with JOIN, you can update only columns in your "MANY" table and only if they have real reference.
Your Create as select. . . tables definitely don't have these references, hence Oracle optimizer throws this error.
Here are some references
Reference 1
Reference 2

Related

How to tune query to fetch result faster | Oracle 19c |

I have a table which as huge records in table
My tables : employee and customer
Now the issue here is I have 2 billion records in employee table and 1 billion records in customer table
Employee columns
empid
empname
empage
empdcourse
Customer columns
custid
custdesc
custmessage
My query :
select emp_id from employee where empid not in ( select custid from customer);
Error : It throws me table space issue. Not allowed to increase table space
Is their any way I can tune my query or run in batch by batch so I get output
Any solution is much appreciated !!!
Need it on high priority
NOT EXISTS may be more efficient and less memory consuming in such case.
(The query suggests Customer and Employee share the same PK, does it mean you have an "super" table Person ?)
Try this:
with tmp as
(select /*+full(c)*/
custid
from customer c)
select /*+full(e)*/
e.emp_id
from employee e, tmp t
where e.empid = t.custid(+)
and t.custid is null;
The hint full will prevent the tablespace issue.
The OUTER JOIN is faster than the NOT IN.
You can improve it by adding the hint parallel, starting with a degree=2 or 4 like this:
with tmp as
(select /*+full(c) parallel(c,2)*/
custid
from customer c)
select /*+full(e) parallel(e,2)*/
e.emp_id
from employee e, tmp t
where e.empid = t.custid(+)
and t.custid is null;
You can add indexes for columns, for example, if they aren’t primary keys:
CREATE INDEX empid_index
ON employee(empid);
Also, you can update the query:
select e.empid from employee e where not exists (select 1 from customer c where c.custid = e.empid);

How to use UPDATE JOIN correctly?

I tried to update a table row as below:
update EMPLOYEE set Salary=Salary * 1.15 where Dno=1;
which works fine, but I wanted to learn how to use UPDATE JOIN. so I use the Department Name instead of DNo.
I wrote below code:
update EMPLOYEE set Salary=e.Salary * 1.15 from EMPLOYEE e join DEPARTMENT d on e.DNo=d.DNumber where d.DName='Headquarters';
But the result for above code is that the SQL Command updates all the rows in EMPLOYEE table.
Where did I do wrong?
In BigQuery, change this to a filter in the where clause:
update EMPLOYEE e
set Salary = Salary * 1.15
where exists (select 1
from DEPARTMENT d
where d.DNumber = e.DNo and
d.DName = 'Headquarters'
);
The above is standard SQL and should work in any database. If you want a FROM clause, then use:
update EMPLOYEE e
set Salary = e.Salary * 1.15
from DEPARTMENT d
where d.DNumber = e.DNo and
d.DName = 'Headquarters';
There are (at least) two different ways of implementing FROM in an update, the "SQL Server method" and the "Postgres" method. In the SQL Server method, the table being updated should be in the FROM clause. In the "Postgres method", the table cannot be in the FROM clause. BigQuery adheres to the "Postgres method".
The above actually works in both methods, though.
Try to use table alias name in update
update Emp
Set Salary = Emp.Salary * 1.15
From EMPLOYEE As Emp
join DEPARTMENT As dep On Emp.DNo = dep.DNumber
Where dep.DName = 'Headquarters';

How to update table using foreign key in sql

I am trying to update a table, but my query is not correct. I don't know where I am making a mistake. Here it is:
UPDATE employee
SET image = '123.jpg'
WHERE employee.emp_id=personal_data.emp_Id;
Where emp_Id is a primary key in personal_data table and a foreign key in employee table .
Try like this:
UPDATE E
SET E.image = '123.jpg'
FROM personal_data P
INNER JOIN employee E
ON E.emp_id = P.emp_id
You can use this query.
UPDATE employee
SET E.image = '123.jpg'
FROM employee,personal_data
where employee.emp_id = personal_data.emp_id

Query Multiple Columns Within a Table

I have a table of employees that are formatted as follows:
EMPLOYEE (FNAME,MINIT,LNAME,SSN(PK),BDATE,SUPERSSN(NULLABLE))
I need to query every employee and retrieve the following information:
FNAME(employee),LNAME(employee),SUPERSSN,(super)FNAME,(super)LNAME
UPDATED
After running this query:
SELECT A.FNAME,A.LNAME,A.SUPERSSN,B.FNAME,B.LNAME
FROM EMPLOYEE
A LEFT JOIN EMPLOYEE B
ON A.SUPERSSN = B.SSN;
The results were close, but when the superssn was null (CEO/Boss) it caused the remaining rows to populate as null also and did not populate with the actual supervisors ssn. I'm trying to use an IF statement to fix the problem with having a SuperSSN that is null, but I'm receiving the error: ORA-00905: missing keyword.
Below is the query that I ran that generated the error.
SELECT A.FNAME,A.LNAME,A.SUPERSSN,B.FNAME,B.LNAME
FROM EMPLOYEE A LEFT IF A.SUPERSSN <> 'NULL'
JOIN EMPLOYEE B ON A.SUPERSSN = B.SSN;
Select A.FName,
A.LNAme,
A.SuperSSN,
B.FName,
B.LName
from Employee A
Left Join Employee B
On A.SuperSSN = B.SSN

how to update table from an external table

I want to update a employee table based on my external table, but I got ORA-01427 error,
single-row subquery returns more than one row
employee(emp_id, emp_name, job_history, city_code)
ext_table(emp_name, job_history, city_name)
city(city_code, city_name)
data in my ext_table as following:
Sandy, waitress, los angeles
Sandy, restaurant manager, los angeles
John, store manager, phoenix
update employee em
set (em.emp_name, em.job_history, em.city_code) =
(select t.emp_name, t.job_history, t.city_code
from (select distinct(emp_name), job_history, c.city_code from
ext_table e, city c where e.city_name=c.city_name) t)
where em.emp_name=t.emp_name;
I am greatly appreciate for any help
This is what MERGE is for:
merge into employee
using
(
select e.emp_name, e.job_history, c.city_code
from ext_table e
join city c on e.city_name=c.city_name
) t on (t.emp_name = employee.emp_name)
when matched then update
set job_history = t.job_history,
city_code = t.city_code;
Note that it's useless to update emp_name as that is the column you use to join between ext_table and employee.
The above assumes that emp_name is unique in ext_table (and employee). If this is not the case you will need to find some "key" that uniquely identifies the employee in the external table.
Also: distinct is NOT a function.
select distinct (foo), bar is absolutely identical to select distinct foo, bar. It always operates on all columns. The difference between the two is the same as the difference between select (foo),bar and select foo, bar.
Another possible option is to convert external table to regular table and update. To convert external to regular table use SQL Developer. Steps: 1.Create empty table with the same structure as your external table. 2.Export data from external to reg. table. The process is similar to exporting data from file to Excel.
you can do it by using update query with join . check following code
UPDATE employee SET job_history = B.job_history , city_code =
C.city_code FROM EMPLOYEE as A INNER JOIN ext_table AS B ON
A.emp_name = B.emp_name INNER JOIN city AS C ON B.city_name =
C.city_name