Oracle trigger invalid - database

I'm new to SQL and I'm trying to create a trigger that would insert into an audit table.
create or replace trigger late_ship_insert
after insert on suborder
for each row
declare
employee int;
begin
select emp_id
into employee
from handles
where order_no = :new.order_no;
if :new.actual_ship_date > :new.req_ship_date then
insert into ship_audit
values (employee, :new.order_no, :new.suborder_no, :new.req_ship_date, :new.actual_ship_date);
end;
Error:
Warning: execution completed with warning
trigger late_ship_insert Compiled.
But once I try an insert statement it tell me the trigger is not working it to drop it.
Error starting at line 1 in command:
insert into suborder
values ( 8, 3, '10-jun-2012', '12-jul-2012', 'CVS', 3)
Error at Command Line:1 Column:12
Error report:
SQL Error: ORA-04098: trigger 'COMPANY.LATE_SHIP_INSERT' is invalid and failed re-validation
04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation"
*Cause: A trigger was attempted to be retrieved for execution and was
found to be invalid. This also means that compilation/authorization
failed for the trigger.
*Action: Options are to resolve the compilation/authorization errors,
disable the trigger, or drop the trigger.
Any idea what is causing this, any help would be greatly appreciated. Thanks!

The error that becomes apparent when you format your code is that your IF statement is missing the END IF
create or replace trigger late_ship_insert
after insert on suborder
for each row
declare
employee int;
begin
select emp_id
into employee
from handles
where order_no = :new.order_no;
if :new.actual_ship_date > :new.req_ship_date then
insert into ship_audit
values (employee, :new.order_no, :new.suborder_no, :new.req_ship_date, :new.actual_ship_date);
end if;
end;
As a general matter, you should always list the columns of the destination table in your INSERT statement rather than relying on the fact that your INSERT statement specifies a value for every column and specifies them in the proper order. That will make your code much more robust since it won't become invalid when someone adds additional columns to the table for example. That would look something like this (I'm guessing at the names of the columns in the ship_audit table)
create or replace trigger late_ship_insert
after insert on suborder
for each row
declare
employee int;
begin
select emp_id
into employee
from handles
where order_no = :new.order_no;
if :new.actual_ship_date > :new.req_ship_date then
insert into ship_audit( emp_id, order_no, suborder_no, req_ship_date, actual_ship_date )
values (employee, :new.order_no, :new.suborder_no, :new.req_ship_date, :new.actual_ship_date);
end if;
end;

Related

Incorrect syntax near the keyword “AS” when alter trigger

i created trigger called trgInsteadofdeleteEmp
and i just want to alter it, i wrote the following SQL code
alter trigger trgInsteadofdeleteEmp on Emp
instead of delete
as
begin
declare #id int , #name nvarchar(100)
select #id =id from deleted
select #name = name from deleted
insert into EmployeeAudit values (#id ,#name + 'tried to delete at' + GETDATE() as varchar(50))
end
and have the following output:
Msg 156, Level 15, State 1, Procedure trgInsteadofdeleteEmp, Line 8 Incorrect syntax near the keyword 'as'.
can someone point me in the direction of how to find the error
Thanks.
No, no, no, no, no.
Don't make the mistake of assuming that inserted and deleted have only one row. You are just putting errors in your code that are going to pop up at an unexpected time. I actually wish that SQL Server flagged this usage when creating the trigger.
Instead:
alter trigger trgInsteadofdeleteEmp on Emp
instead of delete
as
begin
insert into EmployeeAudit(id, name)
select id,
name + ' tried to delete at ' + convert(varchar(255), GETDATE(), 121) )
from deleted d;
end;
Your error is caused by the as. There seems to be a missing cast() function. But that is not the right fix. With date/times, use convert() or format() along with the desired format.
Other suggestions:
Always include the column names when doing an insert. In fact, an audit table really should have an identity id column, createdBy, and createdAt columns, all with default values.
Look at the strings that will be produced and be sure they are readable.
Use semicolons to end statements.
Don't rely on default formatting for date/time values.

There already exists an object in the database SQL Server

I have created a stored procedure that returns the id of last inserted row of a table based on one condition.
Condition is such that if the row being inserted already exists then it takes identity column of the row otherwise it inserts a new row into the table.
To do this, I have written the following code in a stored procedure
ALTER PROCEDURE [dbo].[Test_Procedure]
#description nvarchar(max)
AS
BEGIN
DECLARE #tempId int;
SELECT CommentId
INTO tempId
FROM TestTable
WHERE description = #description;
IF #tempId IS NULL
BEGIN
INSERT INTO TestTable
VALUES (#description);
SELECT scope_identity();
END
ELSE
BEGIN
SELECT #tempId FROM dual;
END
DROP TABLE tempId;
END
When I run the above stored procedure, first time it ran successfully and then on wards it started throwing the following error message
Msg 2714, Level 16, State 6, Procedure Test_Procedure, Line 15
There is already an object named 'tempId' in the database.
The bit I'm not understanding is tempId is used as a variable not as a table. I have seen people with the similar problem but in their case they used temporary tables
I really appreciate your help in resolving the above issue.
Try this syntax for setting your variable.
SELECT #tempId = CommentId from TestTable where description = #description;
Currently your 'select into' is creating a table 'tempId' on the database.

SQL Server, can't check if #temporary table exists, with if else statement

I'm creating a Trigger that handles a temp table (#attributeType). Since the trigger can be called more than once, I wanted to be sure and check if the temp table #attributeType is still there.
This is my code in the trigger body that checks for the temp table:
IF OBJECT_ID('tempdb..#attributeType') IS NOT NULL
BEGIN
DROP TABLE #attributeType
SELECT * INTO #attributeType
FROM attributeType
PRINT 'IN IF'+ CAST(OBJECT_ID('tempdb..#attributeType') AS NVARCHAR(80))
END
ELSE
BEGIN
SELECT * INTO #attributeType
FROM attributeType
PRINT 'IN ELSE'+ CAST(OBJECT_ID('tempdb..#attributeType') AS NVARCHAR(80))
END
When I test the code by selecting it with F5 I get this error message, stating that the #attributeType temp table exist:
Msg 2714, Level 16, State 1, Line 11
There is already an object named '#attributeType' in the database.
I know that in stored procedures the #tempTables will be deleted as soon as the sp ends, but still I can't understand why my code is wrong?
N.B.
When I comment out the ELSE block the code works.
Your test on OBJECT_ID('tempdb..#attributeType') works fine. You can test it by running it separately, without a drop and create in the same batch.
The problem is that SQL Server parses the entire batch before it runs it. If it knows that #attributeType exists it will give an error for:
SELECT * INTO #attributeType
Even if you drop the table in the previous row.
One solution is to drop the table in a different batch:
IF OBJECT_ID('tempdb..#attributeType') IS NOT NULL
DROP TABLE #attributeType
GO -- new batch
SELECT * INTO #attributeType ...
Another solution is to create the table in a different scope:
IF OBJECT_ID('tempdb..#attributeType') IS NOT NULL
DROP TABLE #attributeType
exec ('SELECT * INTO #attributeType ...')
If you don't need to perform any other operations in IF..ELSE statement, your code can be simplified to the following:
IF OBJECT_ID('tempdb..#attributeType') IS NOT NULL
BEGIN
DROP TABLE #attributeType
END
SELECT *
INTO #attributeType
FROM attributeType
In this case you avoid There is already an object named... error and you still have temporary table.

insert then and update then in sybase

I did a search over the net but I couldnt find my answer
in oracle , if we to specify for the trigere if its insert or update , we write like this :
create or replace trigger TRG_LOGS
after INSERT or update or delete
ON TABOE_LOGS
FOR EACH ROW
DECLARE
V_USERNAME VARCHAR2(100);
BEGIN
if inserting then
insert into long_log(NAME) VALUE (:new.NAME)
ELSE if UPDATING THEN
insert into long_log(NAME) VALUE (:OLD.NAME)
END;
END;
Is throwing an error on Incorrect syntax near the keyword 'insert'.
For Sybase, each action is a seperate trigger:
create trigger TRG_LOGS_INS on TABOE_LOGS
for INSERT
as
DECLARE #V_USERNAME varchar(100)
BEGIN
insert into long_log
select NAME from INSERTED
END
....
create trigger TRG_LOGS_UPD on TABOE_LOGS
for UPDATE
as
DECLARE #V_USERNAME varchar(100)
BEGIN
insert into long_log
select NAME from DELETED
END
Not sure if my syntax is exactly right, but should get you pointed in the right direction. The INSERTED table (similar to Oracles new) stores the new records on either an insert or update action. The DELETED table (similar to Oracles old) stores the old records on either an update or delete action.
More information and examples can be found in the Sybase T-SQL Users Guide: Triggers

Invalid column name "USER_SOURCE"

I have a stored procedure which is returning a result in an xml #Data output parameter
To assign data in xml code is
SELECT #data= (
SELECT DISTINCT
CONVERT(varchar(2),u.USER_SOURCE ) + '~' +
CONVERT(varchar(20), u.[USER_ID]) + '-' +
CONVERT(varchar(10), u.DEALER_ID) as USER_DEALER_ID
FROM #users u FOR XML RAW('users'))
When I exec the procedure in SQL Server Mgmt Studio, I can see the result OK.
This procedure is been called from another procedure, and that parent procedure is used in SSRS.
In SSRS I am getting error
Query execution failed for dataset 'DataSet1'. Invalid column name
'USER_SOURCE'. Invalid column name 'USER_ID'. Invalid column name
'DEALER_ID'.
Could you please help?
Thanks,
Chetan
Here's a script which I think reproduces a problem identical to yours:
CREATE PROCEDURE TestTmpTable
#value varchar(20)
AS
BEGIN
CREATE TABLE #test (id int IDENTITY, value varchar(20));
INSERT INTO #test (value) VALUES (#value)
SELECT * FROM #test;
DROP TABLE #test;
END
GO
CREATE TABLE #test (id int IDENTITY, value2 varchar(20));
EXEC TestTmpTable 'some text';
SELECT * FROM #test;
DROP TABLE #test;
GO
DROP PROCEDURE TestTmpTable
As you can see, there are two #test tables here, one is created in the stored procedure, the other one in the batch that invokes the stored procedure. They have different structures: one has a column named value, the other a column named value2. If you run the script, you'll see this error:
Msg 207, Level 16, State 1, Procedure TestTmpTable, Line 6
Invalid column name 'value'.
I can't point you to a relevant documentation article at the moment, but to me it is evident enough that some preliminary name checking is taking place immediately before the execution of the SP. At that stage, a discrepancy between the column names referenced in the stored procedure and those actually present in the already existing table is revealed, which renders the execution impossible.
If you change value2 to value, the script will work without any problem, and there will be two row sets in the output, one with the 'some text' value, the other empty. And of course the script will work if you remove all parts related to the external #test table.
So, check the places where your procedure is called to see if any other #users table can be existing by that moment, and if so, amend the issue according to your situation.

Resources