I have created trigger for checking value length. I want display my own message than length is more than specified. Trigger was created without error. But If I try create record with value more than specified I get only system error. How make so I see also my message? Thanks
CREATE TRIGGER check_region_name_length
ON Region
INSTEAD OF INSERT
AS
BEGIN
IF EXISTS
(
SELECT inserted.RegionName FROM inserted
WHERE LEN(inserted.RegionName)>10
)
BEGIN
RAISERROR('RegionName value is longer than specified', 10, 1);
ROLLBACK TRANSACTION;
RETURN;
END;
END
GO
Basic data integrity checks are performed well before a trigger fires, and if they fail, the trigger is never invoked at all.
As such, if you're trying to replace or augment an existing warning (i.e. if the column's length is defined as (10)), you're on a hiding to nothing trying to set a new error message from a trigger.
E.g.:
create table T (Val1 char(1) not null)
go
create trigger T_T on T instead of insert
as
insert into T (Val1)
select SUBSTRING(Val1,1,1) from inserted
go
insert into T (Val1) values ('ab')
Produces:
Msg 8152, Level 16, State 14, Line 1
String or binary data would be truncated.
The statement has been terminated.
Even though, had the trigger been allowed to fire, it would have performed a successful insert.
Related
I
need some code advice,
when printing out offers, our ERP Program generates an ID Number in the Table "Angebot" in the format AYYNNNNN, this mask is set in the administrative settings, but it also has an option to override this number and set a manual one, which causes lots of trouble, as people tend to break the id counter.
I'd like to create a trigger that sends a message when the id number is not in the correct format, so I have to check for that specific column to be correct.
The if statenent would check the following:
if (Angebotsnr NOT LIKE 'A'+RIGHT(DATEPART(yy,getdate())+'_____') then RAISEERROR
There is already an existing trigger in the database that checks for something else, so I only need to add the second check to ensure that it is right, but where would I put the if statement and how do I check it?
This is the code of the existing trigger:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[ANGEBOT_ITrig] ON [dbo].[Angebot] FOR INSERT AS
SET NOCOUNT ON
/* * KEINE EINFÜGUNG BEI FEHLEN EINES PASSENDEN SCHLÜSSELS IN 'ErlGrp' */
IF (SELECT COUNT(*) FROM inserted) !=
(SELECT COUNT(*) FROM ErlGrp, inserted WHERE (ErlGrp.ABTNR = inserted.ABTEILUNG))
BEGIN
RAISERROR ( 'Some error statement',0,0)
ROLLBACK TRANSACTION
END
The action would be the same, just with a different error message.
Can someone point me to the right direction.
Thanks.
I would handle this in the procedure that's doing the insert so it doesn't ever insert and fire off other triggers.
create proc myInsertProc (#ID char(8))
as
begin
--copied from you, but it's missing part of the right function
if (Angebotsnr NOT LIKE 'A'+RIGHT(DATEPART(yy,getdate())+'_____')
begin
raiserror('You provided a wrongly formatted ID',16,1) with log
return
end
...continue on with other code
end
This will raise the error, and write it to the SQL Server Error Log. You can remove with log if you don't want that. The return ends the batch. You can also wrap this in a try catch on insert if you'd.
I'd use this in the IF block personally.
if (Angebotsnr NOT LIKE 'A' + right(convert(varchar,DATEPART(year,getdate())),2) + '%' or len(Angebotsnr) != 8)
I built a trigger in SQL Server to execute a stored procedure when a new row is inserted into the table Balance Data, but the trigger doesn't get fired. I don't know what I am doing wrong or what is happening.
This is the script:
CREATE TRIGGER [dbo].[SP_Trigger]
ON [dbo].[BalanceData]
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
Exec Schenck.dbo.spCopyData
END
I assume that you are using Transact-SQL.
According to the documentation, FOR INSERT triggers are synonymous with AFTER INSERT triggers by default. This should fire after you have inserted your data into [dbo].[BalanceData].
I would firstly confirm that the data has been inserted successfully (i.e. no check constraint violations, etc) and then confirm what Schenck.dbo.spCopyData is doing. You have turned ROWCOUNT off in the trigger, so perhaps this has given you the illusion that nothing happened.
I have a database with three tables User(userID, Firstname, LastName), Movies(MovieID, MovieName), and UserMovies(MovieID, userID). I also have a trigger in the User table that I would like to have run After Insert that determines if the supplied userID is already existing. If the supplied userID exists in the table, how do I go about ignoring the insert that triggered the trigger and began manipulating the Movies table (my next INSERT command)? I tried using RETURN
if exists(select insert.userID FROM inserted)
return
but that's not working for me. Thank you.
If you want to restrict data insertion based on some condition, you should do it in the before trigger. Here, check to see if the user_id already exists. If it does, then you can restrict inserting that data in your table by rolling back the transaction.
Raise an exception in your trigger function.
RAISERROR ('Error Text', 11, 1);
I don't know of another way to "ignore" an insert in a trigger function. Since the function was triggered by an INSERT command, the INSERT should either happen or an error should occur.
Another way to do this would be to write a stored procedure that checks for your condition before attempting the INSERT.
I have a trigger type INSTEAD OF Insert, Update.
It looks something like below:
IF EXISTS(some select staement)
updade
set
where
ELSE IF (some other select staement)
insert
values
ELSE--(3)
RAISERROR ('msg',16,1)
RETURN; SET NOCOUNT ON;
The issue is that in 3rd - "else" option I would like to show only error message without any "row(s) affected" message.
SET NOCOUNT ON dosen't work for me. I've already tried different configurations, put this with and without return. I was putted it everywhere in my statement.
It doesn't work anywhere. I use SQL Server 2005 Can anybody help me please?
Rows affected massage should appear always. The only exception is else statement.
Use SET NOCOUNT ON; before a query and then use GO
SET NOCOUNT ON;
GO
In a simplified example:
create table T (
ID int not null
)
go
create trigger TT
on T
instead of insert
as
RAISERROR('No',16,1)
go
insert into T (ID)
select 1
We get the output:
Msg 50000, Level 16, State 1, Procedure TT, Line 5
No
(1 row(s) affected)
The only way to suppress that "1 row affected" message is to rollback the transaction (by including ROLLBACK after the error message). And that will generate this instead:
Msg 50000, Level 16, State 1, Procedure TT, Line 5
No
Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.
There's no way to suppress these messages further. The "1 row affected" message is being generated in the outer scope (the scope in which the INSERT statement is being run) rather than within the scope of the trigger, and is being generated because the trigger is running to completion - so far as the outer statement is concerned, it's been succesful.
The usual advice about NOCOUNT is to use it to suppress additional rowcounts being returned from within a trigger. If you're using it for that, it should be the first statement within the body of the trigger. IN your sample, you have it as the last statement, where it will have no effect anyway.
SeeSnapshot
create TRIGGER triggerdeletefordesignation
ON designation
instead of INSERT,DELETE,update
AS
BEGIN
print '"operation on this table is not allowed"'
rollback
END
GO
insert into designation values(6,'lead');
exec getDesg
and output:
"operation on this table is not allowed"
Msg 3609, Level 16, State 1, Line 12
The transaction ended in the trigger. The batch has been aborted.
and record not inserted into table
I have some code in an after insert trigger that may potentially fail. Such a failure isn't crucial and should not rollback the transaction. How can I trap the error inside the trigger and have the rest of the transaction execute normally?
The example below shows what I mean. The trigger intentionally creates an error condition with the result that the original insert ( "1" ) never inserts into the table. Try/Catch didn't seem to do the trick. A similar, older stack overflow question didn't yield an answer except for "prevent the error from occuring in the first place" - which isn't always possible/easy.
Any other ideas?
create table test
(
a int not null
);
go
create trigger testTrigger on test
after insert as
begin
insert into test select null;
end;
go
insert into test values ( 1 );
A trigger cannot fail and still have the transaction roll forward. You have a few options to ensure that the trigger does not fail.
1 - You can ensure that the after does not fail by duplicating the logic for checking the constraints and not attempting an operation which would violate the constraints:
i.e.
INSERT INTO test WHERE val IS NOT NULL
2 - You can defer the potentially failing action by using a queue design pattern where actions which may or may not fail are queued by enqueueing to a table where the enqueueing operation cannot possibly fail.
i.e.
INSERT INTO ACTION_QUEUE (action, parameters) VALUES ('INSERT INTO TEST', val)
Due to the way triggers are implemented in SQL Server, all constraint violations within the triggers doom the transactions.
This is the same as doing:
DROP TABLE test
CREATE TABLE test
(
a INT NOT NULL
)
GO
SET XACT_ABORT ON
GO
BEGIN TRANSACTION
BEGIN TRY
INSERT
INTO test
SELECT NULL
END TRY
BEGIN CATCH
INSERT
INTO test
SELECT 1
END CATCH
which results in a doomed transaction, except that there is no way to disable XACT_ABORT inside a trigger.
SQL Server also lacks autonomous transactions.
That's another reason why you should put all you logic into the stored procedures rather than triggers.
You can turn XACT_ABORT off inside the trigger (use caution)
You can have the trigger call a stored procedure. (I am now wrestling with the opposite problem: I want the transaction aborted, but because the logic is in an SP called from the trigger, and not the trigger itself, this isn't happening.)