Trigger issue - Oracle SQL plus - sql

I have created a trigger to insert values into Payroll once an entry to Employees have been made. But when I insert values into Employees , no values are entered into Payroll from the trigger. Payroll remains empty when I insert values into Employees. Any ideas?
CREATE TABLE Employees(
empid FLOAT,
dept FLOAT,
empname varchar2(25),
salary FLOAT
);
CREATE TABLE Payroll(
empid FLOAT,
salary FLOAT
);
CREATE OR REPLACE TRIGGER NewEmployee
AFTER INSERT
ON Employees
FOR EACH ROW
BEGIN
INSERT INTO Payroll
VALUES(:Old.empid,:Old.salary);
END;
/
INSERT INTO Employees values (1,1,‘supply’,50000);
INSERT INTO Employees values (2,2,‘hard’,80000);
Select * from Employees;
Select * from payroll;

Your :Old.empid and :Old.salary should be :new.empid and :new.salary.
Also, it is slightly more efficient to use a BEFORE INSERT trigger when you can.

Related

How to resolve this problem " near "INSERT": syntax error" in SQLite?

I cannot find what wrong in my code, but it is showing "sqlite near "INSERT": syntax error".
my code is
/*CREATE TABLE Employee
(
Emp_ID varchar not NULL PRIMARY key, --0/""
Emp_Name Varchar,
Location varchar,
commission INT,
phone_no varchar,
country varchar
);
*/
INSERT into Employee VALUES ("1","rachit","MP","1700","1234567898","india")
INSERT into Employee VALUES ("2","Swapnil","UP","1524","3485030230","india")
INSERT into Employee VALUES ("3","Hardik","MH","1469","5684586954","india")
INSERT into Employee VALUES ("4","Sarthi","GOA","1985","4995406905","india")
INSERT into Employee VALUES ("5","Rupak","KT","1654","9040938640","india")
INSERT into Employee VALUES ("6","soham","UK","1598","9894945932","india")
INSERT into Employee VALUES ("7","palash","NCR","1789","8984647458","india")
You missed to add ; at the end of each insert statement.
The correct syntax would be
INSERT into Employee VALUES ("1","rachit","MP","1700","1234567898","india");
INSERT into Employee VALUES ("2","Swapnil","UP","1524","3485030230","india");

Order by not working in SQL analytical functions

create table Employee
(
Ename varchar (255),
empno integer primary key,
deptno integer ,
salary integer
);
`
insert into Employee values ('Gauhar khan',1000,10,5000);
insert into Employee values ('Gauri sharma',1001,10,6000);
insert into Employee values ('Gauresh verma',1002,10,7000);
insert into Employee values ('Raja ashokan',1003,20,8000);
insert into Employee values ('Divya Nair',1004,20,19000);
insert into Employee values ('Ashwin Thakare',1005,20,10000);
insert into Employee values ('Uttam Thapa',1006,30,7800);
insert into Employee values ('Krutagnya Thakker',1007,30,11000);
insert into Employee values ('Kritika manocha',1008,30,12000);
`
select * from Employee;
`
SELECT empno,
deptno,
salary,
SUM(salary) OVER(PARTITION BY deptno ORDER BY salary) AS dept_running_total
FROM Employee;
It returns the error :
Error: near line 1: near "(": syntax error
I have tried using only partition by clause as well still returned the same error. Please guide me in resolving the error. I tried running this over various online sql editors.
This works fine in SQL Server 2014. I can only assume this is not actually the query you are running
SqlFiddle

How to solve single-row subquery returns more than one row

I have an employee table and it contains salary table. I want to give %10 increase to all current employees. I tried to update all employees' salary dates to specific date but I encountered problem with single-row subquery.
My database like this:
CREATE TYPE TEMPORAL_VARCHAR AS OBJECT (
VALID_TIME_LOWER_BOUND DATE,
VALID_TIME_UPPER_BOUND DATE,
VALUE_PART VARCHAR2(50) );
CREATE TYPE TEMPORAL_NUMBER AS OBJECT (
VALID_TIME_LOWER_BOUND DATE,
VALID_TIME_UPPER_BOUND DATE,
VALUE_PART NUMBER );
CREATE TYPE NAME_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE ADDRESS_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE DEPARTMENT_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE MANAGER_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE SALARY_TYPE AS TABLE OF TEMPORAL_NUMBER;
CREATE TABLE EMPLOYEE (
SSN NUMBER primary key,
NAME NAME_TYPE,
ADDRESS ADDRESS_TYPE ,
BIRTH_DATE DATE,
MANAGER MANAGER_TYPE ,
DEPARTMENT DEPARTMENT_TYPE,
SALARY SALARY_TYPE
)
NESTED TABLE NAME STORE AS NAME_TABLE,
NESTED TABLE ADDRESS STORE AS ADDRESS_TABLE,
NESTED TABLE MANAGER STORE AS MANAGER_TABLE,
NESTED TABLE DEPARTMENT STORE AS DEPARTMENT_TABLE,
NESTED TABLE SALARY STORE AS SALARY_TABLE
;
How to solve this problem? I tried to do this
UPDATE TABLE(
SELECT E.SALARY
FROM EMPLOYEE E
) SAL
SET SAL.VALID_TIME_UPPER_BOUND = '11.16.2015'
WHERE SAL.VALID_TIME_UPPER_BOUND = TO_DATE('12.31.9999','MM.DD.YYYY');
1st it can be duplicate
2nd see sample here
3rd in your code you need bring the where condition into select
UPDATE TABLE(
SELECT E.SALARY
FROM EMPLOYEE E
WHERE ssn in (SELECT ssn FROM EMPLOYEE e
WHERE to_date('01.01.2015','mm.dd.yyyy') in (
SELECT VALID_TIME_UPPER_BOUND FROM TABLE(e.salary)
)
)
) SAL
SET SAL.VALID_TIME_UPPER_BOUND = to_date('01.01.9999','mm.dd.yyyy')
test data
INSERT INTO EMPLOYEE(SSN, salary) values (1, SALARY_TYPE ());
INSERT INTO EMPLOYEE(SSN, salary) values (2, SALARY_TYPE ());
INSERT INTO EMPLOYEE(SSN, salary) values (3, SALARY_TYPE ());
INSERT INTO TABLE(SELECT salary FROM EMPLOYEE
WHERE ssn = 1)
VALUES (to_date('01.01.2005','mm.dd.yyyy'), to_date('01.01.2015','mm.dd.yyyy'), 1);
INSERT INTO TABLE(SELECT salary FROM EMPLOYEE
WHERE ssn = 2)
VALUES (to_date('02.02.2005','mm.dd.yyyy'), to_date('02.02.2015','mm.dd.yyyy'), 2);
INSERT INTO TABLE(SELECT salary FROM EMPLOYEE
WHERE ssn = 3)
VALUES (to_date('03.03.2005','mm.dd.yyyy'), to_date('03.03.2015','mm.dd.yyyy'), 3);
p.s do you really need the complexity?
I solved my problem using iteration like this
BEGIN
FOR employees IN (SELECT SSN FROM EMPLOYEE)
LOOP
UPDATE TABLE(
SELECT E.SALARY
FROM EMPLOYEE E
WHERE E.SSN = employees.SSN
) SAL
SET SAL.VALID_TIME_UPPER_BOUND = '11.16.2015'
WHERE SAL.VALID_TIME_UPPER_BOUND = TO_DATE('12.31.9999','MM.DD.YYYY');
END LOOP;
END;

Oracle SQL: Invalid table name when creating a trigger

I created this 4 tables:
create table terminatedEmployees (
empid number primary key,
dept number,
empname varchar2(50),
salary number
);
create table employees (
empid number primary key,
dept number,
empname varchar2(50),
salary number
);
create table payroll (
empid number primary key,
salary number,
CONSTRAINT fk_payemploy
FOREIGN KEY (empid)
REFERENCES employees(empid)
);
create table salaryAudit (
empid number primary key,
oldsal number,
newsal number,
datechanged date,
changedby varchar2(25),
CONSTRAINT fk_salaryaudit
FOREIGN KEY (empid)
REFERENCES employees(empid)
);
and now I'm trying to create a trigger in order to update two of them when employees table is updated:
CREATE TRIGGER trigger_updated_employees
AFTER UPDATE ON employees
FOR EACH ROW
when (old.salary != new.salary)
BEGIN
UPDATE INTO salaryAudit (newsal, oldsal)
VALUES(:new.salary, :old.salary);
UPDATE INTO payroll (salary)
VALUES(:new.salary);
END;
But I'm getting the error:
2/5 PL/SQL: SQL Statement ignored
2/12 PL/SQL: ORA-00903: invalid table name
4/5 PL/SQL: SQL Statement ignored
4/12 PL/SQL: ORA-00903: invalid table name
The three tables I'm calling in the trigger are ok and other triggers I created work...
Try something like this:
CREATE TRIGGER TRIGGER_UPDATED_EMPLOYEES
AFTER UPDATE ON EMPLOYEES
FOR EACH ROW
WHEN (OLD.SALARY <> NEW.SALARY)
BEGIN
MERGE INTO PAYROLL p
USING (SELECT :NEW.EMPID AS EMPID FROM DUAL) d
ON (p.EMPID = d.EMPID)
WHEN NOT MATCHED THEN
INSERT (EMPID, SALARY)
VALUES (:NEW.EMPID, :NEW.SALARY)
WHEN MATCHED THEN
UPDATE
SET SALARY = :NEW.SALARY;
MERGE INTO SALARYAUDIT a
USING (SELECT :NEW.EMPID AS EMPID FROM DUAL) d
ON (a.EMPID = d.EMPID)
WHEN NOT MATCHED THEN
INSERT (EMPID, OLDSAL, NEWSAL, DATECHANGED, CHANGEDBY)
VALUES (:NEW.EMPID, :OLD.SALARY, :NEW.SALARY, SYSDATE, 'SOME_USER')
WHEN MATCHED THEN
UPDATE
SET OLDSAL = :OLD.SALARY,
NEWSAL = :NEW.SALARY,
DATECHANGED = SYSDATE,
CHANGEDBY = 'SOME_USER';
END TRIGGER_UPDATED_EMPLOYEES;
Share and enjoy.
I got it working just correcting the UPDATE statements syntax and modifying the condition as #BobJarvis suggested, this is the final result:
CREATE TRIGGER trigger_updated_employees
AFTER UPDATE OF salary ON employees
FOR EACH ROW
when (old.salary <> new.salary)
BEGIN
UPDATE salaryAudit
SET (newsal, oldsal)
VALUES (:new.salary, :old.salary)
WHERE (salaryAudit.empid = old.empid);
UPDATE payroll
SET (salary)
VALUES (:new.salary)
WHERE (payroll.empid = old.empid);
END;
The concept is the same that #BobJarvis proposed but a lot simpler. Thanks

Values() constructor in SQL Server 2008 and triggers

I have two tables Employee and Emp_Audit.
On table Employee, I have an AFTER INSERT trigger, which fires when I insert rows into Employee. The function of trigger is to insert the rows into the Emp_Audit table that have been inserted into Employee.
The trigger works fine when I explicitly use 'insert values' for each record to be inserted in Employee as
INSERT INTO Employee_Test VALUES ('Anees',1000);
INSERT INTO Employee_Test VALUES ('Rick',1200);
INSERT INTO Employee_Test VALUES ('John',1100);
INSERT INTO Employee_Test VALUES ('Stephen',1300);
INSERT INTO Employee_Test VALUES ('Maria',1400);
Trigger inserts all these rows inti Emp_Audit -------------GOOD
But when I use values constructor as
insert into dbo.Employee_Test
values ('Kritika', 25000),
('Ritu', 15000),
('Maduri', 7000),
('Dinkar', 7000);
Only the first row ('Kritika', 25000) gets inserted into Emp_Audit
The whole query is as follows:
CREATE TABLE Employee_Test
(
Emp_ID INT Identity,
Emp_name Varchar(100),
Emp_Sal Decimal (10,2)
)
CREATE TABLE Employee_Test_Audit
(
Emp_ID int,
Emp_name varchar(100),
Emp_Sal decimal (10,2),
Audit_Action varchar(100),
Audit_Timestamp datetime
)
-----------------------Trigger------------------------------------
CREATE TRIGGER trgInsertAfter ON [dbo].[Employee_Test]
FOR INSERT
AS
declare #empid int;
declare #empname varchar(100);
declare #empsal decimal(10,2);
declare #audit_action nvarchar(200);
select #empid = inserted.Emp_ID
FROM inserted;
select #empname = inserted.Emp_name
from inserted;
select #empsal = inserted.Emp_Sal
from inserted;
set #audit_action = 'Record Inserted after Insert Trigger Fired';
INSERT INTO Employee_Test_Audit
VALUES(#empid, #empname, #empsal, #audit_action, GETDATE());
GO
print('Insert trigger FIRED')
insert into dbo.Employee_Test
values ('Kritika', 25000),
('Ritu', 15000),
('Maduri', 7000),
('Dinkar', 7000);
Yep, what you want is:
CREATE TRIGGER trgInsertAfter ON [dbo].[Employee_Test]
FOR INSERT
AS
INSERT INTO Employee_Test_Audit (Emp_ID, Emp_name, Emp_Sal, Audit_Action, Audit_Timestamp)
SELECT Emp_ID,Emp_name,Emp_Sal,
'Record Inserted after Insert Trigger Fired',GETDATE()
from inserted;
Because inserted can contain multiple rows (or no rows), you have to treat it as a table. I've never seen any different behaviour, but there's no guarantee (in your version) that all of the variables would have been assigned values from the same row even.
Also, you really should get into the habit of supplying a column list to the INSERT.
Try this one -
CREATE TRIGGER dbo.trgInsertAfter
ON [dbo].[Employee_Test]
FOR INSERT
AS BEGIN
INSERT INTO dbo.Employee_Test_Audit(Emp_ID, Emp_name, Emp_Sal, ..., ...)
SELECT
i.Emp_ID
, i.Emp_name
, i.Emp_Sal
, 'Record Inserted after Insert Trigger Fired'
, GETDATE()
FROM INSERTED i
END
The reason of why only one record inserted is when you assign value to the variable using select then it don't provide any error and set the value to any arbitrary value in the column.
and also using that method only insert one record. So correct trigger code should be
CREATE TRIGGER trgInsertAfter ON [dbo].[Employee_Test]
FOR INSERT
AS
INSERT INTO Employee_Test_Audit
SELECT Emp_ID,Emp_name,Emp_Sal,
'Record Inserted after Insert Trigger Fired',GETDATE()
from inserted;