Interrupt a trigger execution without a box message (tsql) - sql-server-2008

I am writing a trigger for controlling a column. The script works as I want but my problem is in the raiseerror. I want the trigger to work without showing the error message to the user.
Can anyone who knows what is the equivalent of raiseerror without showing the error message to the user?
I tried with rollback transaction which gve me another error message instead, and I tried with return which did not interrupt the execution of the trigger.
This is my trigger:
DECLARE #val varchar(9)
SELECT #val= [DC_Piece]
from INSERTED
where INSERTED [DC_Domaine]=0 and INSERTED.[DC_IdCol]=6
IF UPDATE([DC_Piece])
BEGIN
IF NOT EXISTS( select [DO_PIECE]
from DOCEN
where #val= [DO_Piece] and [DO_Domaine]=0 and [DO_Type]=6)
RAISERROR('STOP',11,1)
END
Please help me

You need to completely rewrite your trigger to take into account that it will be called once per statement (NOT per row!) and the Inserted and Deleted pseudo tables can contain multiple rows which you should consider.
So try something like this:
CREATE TRIGGER trg_abort_insert
ON dbo.YourTableNameHere
AFTER UPDATE
AS
-- check if any of the DC_Piece columns have been updated
IF EXISTS (SELECT *
FROM Inserted i
INNER JOIN Deleted d ON i.PrimaryKey = d.PrimaryKey -- link the two pseudo tables on primary key
WHERE i.DC_Piece <> d.DC_Piece -- DC_Piece has changed
AND i.DC_Domaine = 0
AND i.DC_IdCol = 6)
-- if your conditions are met --> just roll back the transaction
-- nothing will be stored, no message is shown to the user
ROLLBACK TRANSACTION
END

Related

The error occurs on another setup, not on mine: "Table is specified twice, both as a target for 'UPDATE' and as a separate source for data in MySQL"

My question is linked to the one below:
Table is specified twice, both as a target for 'UPDATE' and as a separate source for data in mysql
In my case, the trigger below works fine on my local setup (LAMPP on Ubuntu):
-- trigger to increment balance on posting of a new bill
DELIMITER
//
CREATE TRIGGER trig_increment_balance_new_bill AFTER INSERT ON
tbl_bill FOR EACH ROW
BEGIN
DECLARE
vBillAmount DOUBLE ;
SELECT NEW
.amount
INTO vBillAmount ;
UPDATE
tbl_client T
SET
balance = balance + vBillAmount
WHERE
id =(
SELECT
id
FROM
tbl_client C
WHERE NEW
.metreNo = C.metreNo
LIMIT 1
) ;
END ; //
DELIMITER
;
However, the error below occurs on my collaborator's setup (XAMPP on Windows) when they recreate the same code and test it.
SQLSTATE[HY000]: General error: 1093 Table 'T' is specified twice,
both as a target for 'UPDATE' and as a separate source for data
I thought it was related to strict mode, but I found strict mode is activated; 'STRICT_ALL_TABLES' in my case. Why would errors occur on his setup but not on mine? I know the solution provided in the link above may cure this error but the question is why the error is occurring selectively?
There's no need for the subquery, just put the criteria directly in the WHERE clause. You also don't need the vBillAmount variable.
CREATE TRIGGER trig_increment_balance_new_bill AFTER INSERT ON tbl_bill
FOR EACH ROW
UPDATE tbl_client c
SET c.balance = c.balance + NEW.amount
WHERE c.metreNo = NEW.metreNo
LIMT 1;

Transactions within MySql Stored Procedures

I am trying to use a transaction within a MySQL Stored Procedure.
Specifically, update a user table with amended data from a temporary record. from another table.
then once transferred, delete the temporary record.
I have created the code below, which when executed returns the string "transaction has succeeded".
However, nothing is actually updated and the temporary record is Not deleted.
Both SQL statements, when executed separately work Just fine, the first one does the update, the second does the delete.
Can anyone enlighten me as to what may be wrong?
BEGIN
-- set a default response
DECLARE response varchar(48) DEFAULT "the transaction has failed.";
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
-- set vars
SET response = "the transaction has failed, you may have already updated the account.";
select response;
END;
START TRANSACTION;
-- we are inserting data, using information from another table
update user, updateUserNamesAndNumbers
SET user.firstName = updateUserNamesAndNumbers.firstName,
user.lastName = updateUserNamesAndNumbers.lastName,
user.landline = updateUserNamesAndNumbers.landline,
user.mobile = updateUserNamesAndNumbers.mobile
WHERE
updateUserNamesAndNumbers.uuid = transferCode
AND
updateUserNamesAndNumbers.userId= user.user_id
;
-- finally delete the original tuple
DELETE from updateUserNamesAndNumbers
where uuid= transferCode ;
SET response="The transaction has succeeded";
COMMIT;
SELECT response;
END
Change the implicit join to an explicit join
update user join updateUserNamesAndNumbers on updateUserNamesAndNumbers.uuid = transferCode
I've Partially answered my own Question.
Thanks to P.Salmon, for Querying the transferCode variable.
It turns out I had defined the string as varchar(24), but the input was actually bigger than that.
So once I sorted that, the code worked, but only the first time.
I still need to have a really good think about this, as a second call to the same routine with the same transferCode input, where the temporary tuple had already been deleted by the first call, does not throw the MySQL Exception, as I thought it should. So "its Still Thinking Cap On Time"

SQL where syntax error with trigger

create trigger cal_retweet before insert on T
for each row begin
set NEW.retweet_change = NEW.retweet_count - retweet_count where id_str = NEW.id_str
end
SQL said there is syntax error near "where id_str = NEW.id_str"
My table looks like this. Where id_str is a unique identifier for a specific tweet. Since I am inserting 50 tweets from a single user every minute, there would be many same id_str. What I want to look at is the change of retweet_count every minute. tweeted_at is when the user tweeted, created_at is when this data is inserted into my database. I want to generate retweet_change for each new data inserted into the database compared to the same old tweet (into the column retweet_change). How should I write the trigger?
After reading some of your comments I changed my code to :
create trigger cal_retweet before update on T
for each row
begin
set NEW.retweet_change = NEW.retweet_count - OLD.retweet_count;
end;
There is still syntax error
There are several issues with this trigger.
You have some syntax errors. You need proper semicolons to delimit your statements.
You have a WHERE statement that is out of place (and actually not needed). You are acting on only a single row at a time, you don't have to match on the id_str.
In order to factor in a calculation using an existing value from the row, you need access to the OLD keyword. For that, you need a trigger that happens on UPDATE, not INSERT. On INSERT, the retweet_change is simply the same as retweet_count; you could alter your INSERT statement to fix that problem.
You may need to explicitly add a statement delimiter as per the comments below.
So all together, I think this trigger should look like:
DELIMITER //
CREATE TRIGGER cal_retweet BEFORE UPDATE ON T
FOR EACH ROW
BEGIN
SET NEW.retweet_change = NEW.retweet_count - OLD.retweet_count;
END;//
DELIMITER ;

TRY/CATCH not working when table goes missing

I can't seem to get this to work... The result is SQL Management Studio seems to hang, gives me the message
Msg 208, Level 16, State 1, Line 76 Invalid object name
If I try to close the code window, I get a warning that the transaction isn't committed, and asks if I would like to commit it. If I do, the truncate has happened, and the items are missing.
I'm trying to make sure the truncate does NOT happen or gets rolled back if the table in the "INSERT" statement is missing.
BEGIN TRY
BEGIN TRAN
TRUNCATE TABLE X
INSERT INTO TABLE X ([values...]) -- pseudo code; insert works fine if table is present
SELECT * FROM <potentially missing table>
COMMIT TRAN
END TRY
BEGIN CATCH
if (##TRANCOUNT > 0)
ROLLBACK
END CATCH
Based on the information provided it looks like it may be a problem with your syntax, but it is unclear without a CREATE TABLE statement and some working code. It could also be that you're not checking if the table exists before the SELECT. I just tested the below and it has the desired results.
BEGIN TRY
BEGIN TRAN
TRUNCATE TABLE [test_table]
INSERT INTO [test_table] VALUES ('...')
SELECT * FROM [test_table]
COMMIT
END TRY
BEGIN CATCH
IF (##TRANCOUNT > 0)
PRINT N'rolling back transaction' --for confirmation of the catch
ROLLBACK
END CATCH
Or to avoid the TRY/CATCH use IF EXISTS to check if the table exists before starting anything.
IF EXISTS (SELECT 1 FROM sys.tables WHERE name = 'test_table')
BEGIN
BEGIN TRAN
TRUNCATE TABLE [test_table]
INSERT INTO [test_table] VALUES ('...')
SELECT * FROM [test_table]
COMMIT
END
ELSE
BEGIN
-- do something else
PRINT N'The table does not exist'
END
Hope this helps!
2020-10-11:
I tried SET XACT_ABORT ON, prior to engaging a transaction.
Interestingly, when encountering a missing table (e.g. at SELECT stmt), the script STILL halts without dropping into the TRY/CATCH block.
Moreover, and actually worse, all prior SQL output is no longer available.
Notwithstanding, the transaction was rolled back, as there is no open Transaction, thereafter.
PROOF:
executing "select ##TRANCOUNT" returns 0
manually executing "ROLLBACK TRAN" states: "The ROLLBACK TRANSACTION
request has no corresponding BEGIN TRANSACTION."
I, therefore, decided to check for required tables, at script start/prior to engaging a Transaction, instead of using XACT_ABORT.

mysql returned an empty result set upon executing a trigger

i am trying to create a trigger but i do not know why I am getting this message. am i doing the right this or am I doing something wrong? when I try to run the trigger im getting a message like
# MySQL returned an empty result set (i.e. zero rows).
this is my trigger
DROP TRIGGER IF EXISTS admin.catch_insert//
CREATE TRIGGER admin.catch_insert BEFORE INSERT ON adminpanel.users
FOR EACH ROW
BEGIN
INSERT INTO admin.usertrigger(cmd, time, cmd_user, email, phone_number) VALUES("INSERT", NOW(), CURRENT_USER(), new.email, new.phone_number);
END
//
what causes this and is ther anything im doing wrongly??may someone please expalain to me what i can do or how i can go about it??
There is nothing wrong.
The message you got is the standard message returned after a successful INSERT statement. (It returns no rows to you, it just adds one in your table)