Starting to learn ORACLE SQL and here is something i dont get.
I have EMPLOYEES table that look like this (hire_date values are nulls)
And another table called EMPHD with hire_date
How can i add HIRE_DATE values from EMPHD to EMPLOYEES table starting from the first row and all the way down?
If i use something like this
INSERT INTO EMPLOYEES (HIRE_DATE)
SELECT HIRE_DATE FROM EMPHD
obviously i end up with hire dates added at the end of the table with all other values as null.
Sry for my english and please help!
One option would be using merge. By using merge you can update hire_date column if ID values are matched. Otherwise only two columns' value might be inserted into employees table as new records but seems it's not the case due to all mutually matching 19 ID values :
merge into employees e
using (select id, hire_date from emphd) h
on ( e.id = h.id )
when matched then update set e.hire_date = h.hire_date
when not matched then insert( e.id, e.hire_date )
values( h.id, h.hire_date );
Demo 1
Alternatively, you can use update statement directly by equality among ID values of those tables :
update employees e
set e.hire_date = (select hire_date from emphd where id = e.id);
Demo 2
Related
I am creating an update trigger on a table called tax_table and inserting :new and :old values into update_audit_table.
How can I incorporate related fields (employee id from employee table) into update_audit_table in the same insert.
CREATE UPDAT_TAX_TRIG
AFTER UPDATE
ON tax_table
FOR EACH ROW
BEGIN
INSERT INTO update_audit_table(PREV_TAX_CODE, OLD_TAX_CODE)
VALUES(:NEW.PREV_TAX_CODE, OLD:PREV_TAX_CODE);
END;
update_audit_table:
employee_id,
employee_name,
prev_tax_code,
old_tax_code
employee table :
employee_id,
employee_name
I am trying to include fields from employee table into update_audit_table while inserting audit record.
As you have currently described the tables, it is impossible as there is no correlation that has been described between the tax_table and the employee table that would let you join the two.
However, if we assume that tax_table has an employee_id column then you can use that:
CREATE UPDAT_TAX_TRIG
AFTER UPDATE ON tax_table
FOR EACH ROW
BEGIN
INSERT INTO update_audit_table(
employee_id,
employee_name,
PREV_TAX_CODE,
OLD_TAX_CODE
) VALUES(
:NEW.employee_id,
(SELECT employee_name FROM employees WHERE employee_id = :NEW.employee_id),
:NEW.PREV_TAX_CODE,
:OLD.PREV_TAX_CODE
);
END;
/
If it does not then you need to work out how the tax_table relates to an employee.
I have Two tables that contain employees.
One table has all active employees (Current_Employees) and the other one has employees that have been joined in the last month (Greenhouse_Employees). Sometimes these employees overlap.
I have a unqiue ID (position_ID) that I want to do the following with in the abstract:
If Greenhouse_Employees unique ID exists in or matches to an ID in Current_Employees, ignore, if it does not: append it and its associated columns to the table
Not all of the columns match in either table, some do.
The code below almost works, but if there is a single inconsistency any any column I coalesce, it duplicates the row: (Some employees have inconsistent [loc] (locations) in the tables due to data entry error
SELECT
COALESCE(#CURRENT_EMPLOYEES.[employee_status], [GREENHOUSE_TABLE].[job_status]) AS employment_status
,COALESCE(#CURRENT_EMPLOYEES.[employee_id], 'N/A') AS employee_id
,COALESCE(#CURRENT_EMPLOYEES.[employee_name], CONCAT([GREENHOUSE_TABLE].[first_name],' ',[GREENHOUSE_TABLE].[last_name])) AS employee_name
,COALESCE(#CURRENT_EMPLOYEES.[hire_date], [GREENHOUSE_TABLE].[hire_date]) AS hire_date
,COALESCE(#CURRENT_EMPLOYEES.[salary], [GREENHOUSE_TABLE].[salary]) AS salary
,COALESCE(#CURRENT_EMPLOYEES.[bonus_percent], [GREENHOUSE_TABLE].[annual_bonus]) AS bonus_percent
,COALESCE(#CURRENT_EMPLOYEES.[commission_percent], '0') AS commission_percent
,COALESCE(#CURRENT_EMPLOYEES.[currency], 'N/A') AS currency
,COALESCE(#CURRENT_EMPLOYEES.[company_title], [GREENHOUSE_TABLE].[company_title]) AS company_title
,COALESCE(#CURRENT_EMPLOYEES.[company_department], [GREENHOUSE_TABLE].[company_department]) AS company_department
,COALESCE(#CURRENT_EMPLOYEES.[country], 'N/A') AS country
,COALESCE(#CURRENT_EMPLOYEES.[loc], 'N/A') AS loc
,COALESCE(#CURRENT_EMPLOYEES.[job_level], [GREENHOUSE_TABLE].[job_level]) AS job_level
,COALESCE(#CURRENT_EMPLOYEES.[kamsa_code], [GREENHOUSE_TABLE].[kamsa_code]) AS kamsa_code
,COALESCE(#CURRENT_EMPLOYEES.[position_id],[GREENHOUSE_TABLE].[position_id]) AS position_id
FROM #CURRENT_EMPLOYEES
FULL JOIN [Headcount].[dbo].[greenhouse_employees] AS GREENHOUSE_TABLE ON #CURRENT_EMPLOYEES.[position_id] = [GREENHOUSE_TABLE].[position_id]
ORDER BY #CURRENT_EMPLOYEES.[hire_date] ASC
I believe you need to You need to INSERT ... SELECT ... WHERE NOT EXISTS(...) or INSERT ... SELECT ... WHERE <Id> NOT IN (...). Something like:
INSERT #CURRENT_EMPLOYEES (employee_status, employee_id, ...)
SELECT employee_status, employee_id, ...
FROM Headcount.dbo.greenhouse_employees GE
WHERE NOT EXISTS (
SELECT *
FROM #CURRENT_EMPLOYEES CE
WHERE CE.employee_id = GE.employee_id
)
The other form is
INSERT #CURRENT_EMPLOYEES (employee_status, employee_id, ...)
SELECT employee_status, employee_id, ...
FROM Headcount.dbo.greenhouse_employees GE
WHERE GE.employee_id NOT IN (
SELECT CE.employee_id
FROM #CURRENT_EMPLOYEES CE
)
Both assume that employee_id is unique in greenhouse_employees.
I want to replicate an existing employees record for a new employee.
EG.
If my present employee details are:
EmpID: 100
EmpDept: Accounts
EmpEndDate: 12-12-2018
So when I am adding a new employee I dont want to manually write an insert statement, all I want is a procedure that can replicate all the other values present for the new employee.
One approach is to increment the max EmpID by 1 so as to maintain uniqueness of rows - with a CONNECT BY LOOP, if you want multiple rows.
INSERT INTO Employee (
EmpID
,EmpDept
,EmpEndDate
)
WITH m(max_id) AS (
SELECT MAX(EmpID)
FROM Employee
)
SELECT max_id + LEVEL
,EmpDept
,EmpEndDate
FROM Employee
CROSS JOIN m
WHERE EmpID = p_emp_id CONNECT BY LEVEL <= p_numof_rows;
Put this query in a procedure and pass p_emp_id and p_numof_rows as parameter to replicate as many rows as you want. Hopefully you have one row currently in the table for each p_emp_id you would pass.
If you always want a single row, just use max_id + 1 and remove CONNECT BY LEVEL <= p_numof_rows
Demo
Assuming you are using a sequence named Employees__EmpID__Seq to generate the unique employee IDs then:
INSERT INTO Employees ( EmpID, EmpDept, EmpEndDate )
SELECT Employees__EmpID__Seq.NEXTVAL,
EmpDept,
EmpEndDate
FROM Employees
WHERE EmpID = :id_of_the_employee_you_want_to_copy;
You can then run that statement and it will copy an existing record.
all I want is a procedure that can replicate all the other values present for the new employee.
If you really need to wrap it in a procedure:
CREATE PROCEDURE copy_employee(
i_empid IN Employees.EmpID%TYPE,
o_empid OUT Employees.EmpID%TYPE
)
IS
BEGIN
o_empid := Employees__EmpID__Seq.NEXTVAL;
INSERT INTO Employees ( EmpID, EmpDept, EmpEndDate )
SELECT o_empid,
EmpDept,
EmpEndDate
FROM Employees
WHERE EmpID = i_empid;
IF SQL%ROWCOUNT <> 1 THEN
o_empid := NULL;
END IF;
END;
/
SQLFiddle
you can also do it in PL/SQL,
DECLARE
v_emp_rec employee%ROWTYPE;
BEGIN
SELECT *
INTO v_emp_rec
FROM employee
WHERE emp_id = 'emp_id_to_replicate';
v_emp_rec.emp_id := '101';
v_emp_rec.first_name := 'Alfie';
INSERT INTO employee
VALUES
v_emp_rec;
v_emp_rec.emp_id := '102';
v_emp_rec.first_name := 'Alf';
INSERT INTO employee
VALUES
v_emp_rec;
END;
/
COMMIT;
Below is what I am trying to achieve. I have a procedure which receives employeeIds as optional arguments and stores them into a temp table (temp_table) like this
empId
-------
3432
3255
5235
2434
Now I need to run below query in 2 conditions:
1st condition: if argument is non blank then my query should be-
SELECT *
FROM DEPARTMENTS
INNER JOIN temp_table ON emp_no = empId
2nd condition: if argument is blank it will take all the rows from department table
SELECT *
FROM DEPARTMENTS
One option I can use is:
IF (#args <> '')
BEGIN
SELECT *
FROM DEPARTMENTS
INNER JOIN temp_table ON emp_no = empId
END
ELSE
BEGIN
SELECT *
FROM DEPARTMENTS
END
But I am looking for a better option where I don't need to write almost same query twice. Please help.
I recommend to stick to what you are already doing.
It is the cleanest and safest way performance wise.
Try this one
SELECT *
FROM DEPARTMENTS
WHERE (
#args <> ''
OR EXISTS (SELECT 1 FROM temp_table WHERE emp_no = empId)
)
I have a table X and and table Y. Table Y is history table. Whenever a record is inserted or updated or deleted in table X it will get inserted in history table Y. Now I am trying to update the history table with the missing records. For this I wrote a minus query to get the differences. I have to insert all these records into history table. I tried to use 'merge' and other forms of insert statements but not able to get exact output.
EX:
Table X
A B C
EMP NO EMP NAME EMP ADD
Table Y
A B C D E F
EMP NO EMP NAME EMP ADD st dt end dt indicator
While inserting I have to use three additional columns as values which have dates and indicator as table X does not have these columns. Please help me out to write an insert for this history table when there is a difference.
There are several different ways to do this. One is to use not exists:
insert into tabley (Y, A, B, C, EMPNO, EMPNAME, EMPADD)
select X, A, B, C, EMPNO, EMPNAME, EMPADD
from tablex x
where not exists (
select 1
from tabley
where tabley.y = x.X
)
Just make sure you define the same number of columns for the insert as you do for the select. Depending on where the other fields come from, you may be able to supply them as well -- depends on your sample data and expected results.
Btw, this assumes the x values in tablex are your unique identifiers. If not, you'll need to update the where criteria above.
You will need to create the data for the missing columns in table x (formatted for improved readability):
insert into tabley(empno
, empname
, empadd
, st_dt
, end_dt
, indicator)
select empno
, empname
, empadd
, to_date(some_date_you_create)
, to_date(another_date_or null)
, (whatever_starting_indicator_value_is_allowed)
from tablex x
where not exists (select 1
from tabley y
where x.empno = y.empno);
Essentially, you have to create the missing values with some arbitrary thing you decide on. This also assumes that empno is a distinct key value.