sql trigger cannot insert row using variable - sql-server

When i use this code it inserts row
create trigger [dbo].[InsertInvPayment] on dbo.LG_001_01_PAYTRANS
after update
as
begin
SET NOCOUNT ON;
declare #InvLogicalRef int;
declare #InvNumber varchar(50);
select #InvLogicalRef = inserted.FICHEREF from inserted
select #InvNumber = dbo.LG_001_01_INVOICE.DOCODE from dbo.LG_001_01_INVOICE where dbo.LG_001_01_INVOICE.LOGICALREF = #InvLogicalRef
insert into dbo.CRMINVPAYMENT(INVNUMBER) values('Hello')
end
if i change it like this
create trigger [dbo].[InsertInvPayment] on dbo.LG_001_01_PAYTRANS
after update
as
begin
SET NOCOUNT ON;
declare #InvLogicalRef int;
declare #InvNumber varchar(50);
select #InvLogicalRef = inserted.FICHEREF from inserted
select #InvNumber = dbo.LG_001_01_INVOICE.DOCODE from dbo.LG_001_01_INVOICE where dbo.LG_001_01_INVOICE.LOGICALREF = #InvLogicalRef
insert into dbo.CRMINVPAYMENT(INVNUMBER) values(#InvNumber)
end
it doesn't work. i couldn't find a mistake in the second

Seems like You are missing the source for select InvLogicalRef. It should be
select #InvLogicalRef = inserted.FICHEREF from inserted
Also with this trigger you are assuming that only one record will update at once. This will fail for bulk updates.

The line where you assign a value to #InvLogicalRef is incomplete.
As that variable doesn't contain a value, #InvNumber can't be assigned its value and you are therefore trying to insert a NULL string into CRMINVPAYMENT.
Make sure you select the value of #InvLogicalRef from the inserted table.

Related

Only run trigger if value is FALSE

After some trial and error, along with your help, I have come up with the following code for my trigger:
ALTER TRIGGER [dbo].[SnapChapas]
ON [dbo].[Tab_Inventarios_Chapas]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE(Ativo)
DECLARE #IDInventario as INT
SET #IDInventario = (SELECT ID FROM inserted)
INSERT
INTO Tab_Inventarios_Chapas_Snap_Banco
( ID_Tab_Chapas,
FormatoL,
Comprimento1,
Comprimento2,
Largura1,
Largura2,
Quantidade,
ID_Tab_Inventarios_Chapas
)
SELECT ID,
FormatoL,
Comprimento1,
Comprimento2,
Largura1,
Largura2,
Quantidade,
#IDInventario
FROM Tab_Chapas
The code above is working. My problem here is: I Have a column called "ACTIVE" in [dbo].[Tab_Inventarios_Chapas]. I need the trigger to only run if the updated value is FALSE.
P.S.: My Application only updates one line at a time; there’s no way to update more than one.
Thanks to #JeroenMostert, I could find an answer.
Here is my final code:
ALTER TRIGGER [dbo].[SnapChapas]
ON [dbo].[Tab_Inventarios_Chapas]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare #ativo as bit
Set #ativo = (select Ativo from inserted)
if UPDATE(Ativo) and #ativo='False'
declare #IDInventario as int
Set #IDInventario = (select ID from inserted)
insert into Tab_Inventarios_Chapas_Snap_Banco (ID_Tab_Chapas,FormatoL,Comprimento1,Comprimento2,Largura1,Largura2,Quantidade,ID_Tab_Inventarios_Chapas)
select ID,FormatoL,Comprimento1,Comprimento2,Largura1,Largura2,Quantidade,#IDInventario
from Tab_Chapas
END
Thank You!

SQL Server INSERT in an AFTER UPDATE Trigger

I'm new to SQL Server, and I'm trying to build a simple update trigger that writes a row to a staging table whenever the column ceu_amount is updated from zero to any number greater than zero.
From using PRINT statements, I know that the variables are containing the correct values to execute the INSERT statement, but no rows are being inserted.
Can you help?
CREATE TRIGGER [dbo].[TRG_Product_Function_Modified] ON [dbo].[Product_Function]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
--
-- Variable definitions
--
DECLARE #product_code_new as varchar(31)
DECLARE #product_code_old as varchar(31)
--
-- Check if the staging table needs to be updated.
--
SELECT #product_code_new = product_code FROM Inserted where ISNULL(ceu_amount,0) > 0;
SELECT #product_code_old = product_code FROM Deleted where ISNULL(ceu_amount,0) = 0;
IF #product_code_new IS NOT NULL
AND #product_code_old IS NOT NULL
INSERT INTO Product_Function_Staging VALUES (#product_code_new,CURRENT_TIMESTAMP);
END;
This part of code looks suspicious to me..
SELECT #product_code_new = product_code FROM Inserted where ISNULL(ceu_amount,0) > 0;
SELECT #product_code_old = product_code FROM Deleted where ISNULL(ceu_amount,0) = 0;
IF #product_code_new IS NOT NULL
AND #product_code_old IS NOT NULL
INSERT INTO Product_Function_Staging VALUES (#product_code_new,CURRENT_TIMESTAMP);
The above will work fine ,if there is only one row updated,what if there is more than one value..the product_code will default to last value
You can change the above part of code to below
Insert into Product_Function_Staging
select product_code ,CURRENT_TIMESTAMP from inserted where product_code is not null
You will get undetermined values for #product_code_new if there are more than one rows updated with ceu_amount>0; Similar for #product_code_old if more than one rows updated with ceu_amount NULL or equal 0.
Can you post some sample data?
I would not use variables like that in a trigger, since what causes the trigger could be an update to more than one row, at which point you would have multiple rows in your updated and deleted tables.
I think we can more safely and efficiently make this insert with one simple query, though I'm assuming you have a unique key to use:
CREATE TRIGGER [dbo].[TRG_Product_Function_Modified] ON [dbo].[Product_Function]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO Product_Function_Staging
SELECT i.product_code, CURRENT_TIMESTAMP
FROM inserted i
JOIN deleted d ON i.product_code = d.product_code -- assuming product_code is unique
WHERE i.ceu_amount > 0 -- new value > 0
AND ISNULL(d.ceu_amount, 0) = 0; -- old value null or 0
END;
I'm not sure where you need to check for nulls in your data, so I've made a best guess in the where clause.
Try using this
CREATE TRIGGER [dbo].[Customer_UPDATE]
ON [dbo].[Customers]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #CustomerId INT
DECLARE #Action VARCHAR(50)
SELECT #CustomerId = INSERTED.CustomerId
FROM INSERTED
IF UPDATE(Name)
BEGIN
SET #Action = 'Updated Name'
END
IF UPDATE(Country)
BEGIN
SET #Action = 'Updated Country'
END
INSERT INTO CustomerLogs
VALUES(#CustomerId, #Action)
END

Trigger After Update for a Specific Value

Is it possible to create a trigger on SQL Server that will execute when a column value is updated to a specific value. How can I do this?
Try with following
CREATE TRIGGER trgAfterUpdate ON [dbo].[Employee_Test]
FOR UPDATE
AS
declare #empid int;
declare #empname varchar(100);
declare #empsal decimal(10,2);
declare #audit_action varchar(100);
select #empid=i.Emp_ID from inserted i;
select #empname=i.Emp_Name from inserted i;
select #empsal=i.Emp_Sal from inserted i;
if update(Emp_Name)
set #audit_action='Updated Record -- After Update Trigger.';
if update(Emp_Sal)
set #audit_action='Updated Record -- After Update Trigger.';
insert into Employee_Test_Audit(Emp_ID,Emp_Name,Emp_Sal,Audit_Action,Audit_Timestamp)
values(#empid,#empname,#empsal,#audit_action,getdate());
PRINT 'AFTER UPDATE Trigger fired.'
GO
I write a simple trigger and hoping that it helps you.
CREATE TRIGGER [FUND].[TRU_FUND_FUND_PRICE] ON [FUND].[FUND_PRICE]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #PRICE_ID BIGINT
DECLARE #UNIT_PRICE DECIMAL(18,7)
DECLARE #UNIT_PRICE_BEFORE_UPDATE DECIMAL(18,7)
DECLARE #TOTAL_SHARE_BEFORE_UPDATE DECIMAL(18,7)
DECLARE #TOTAL_SHARE DECIMAL(18,7)
DECLARE #RECORD_STATUS_BEFORE_UPDATE CHAR(1)
DECLARE #RECORD_STATUS CHAR(1)
SELECT #UNIT_PRICE_BEFORE_UPDATE=UNIT_PRICE , #TOTAL_SHARE_BEFORE_UPDATE = TOTAL_SHARE, #RECORD_STATUS_BEFORE_UPDATE =RECORD_STATUS FROM DELETED
SELECT #PRICE_ID = PRICE_ID,#UNIT_PRICE=UNIT_PRICE,#TOTAL_SHARE=TOTAL_SHARE,#RECORD_STATUS=RECORD_STATUS FROM INSERTED
--You can compare to specific values instead of deleted data
IF #UNIT_PRICE=#UNIT_PRICE_BEFORE_UPDATE AND #TOTAL_SHARE =#TOTAL_SHARE_BEFORE_UPDATE AND #RECORD_STATUS_BEFORE_UPDATE = #RECORD_STATUS
BEGIN
RETURN
END
INSERT INTO FUND.FUND_PRICE_LOG (
[PRICE_ID],
[FUND_ID],
[PRICE_DATE],
[UNIT_PRICE],
[UPDATE_USER_CODE],
[UPDATE_PROG_CODE],
[UPDATE_DATE],
[OPERATION],
[RECORD_STATUS],
[TOTAL_SHARE],
[LIMIT_CHANGE_AMOUNT]
)
SELECT [PRICE_ID], [FUND_ID], [PRICE_DATE],
[UNIT_PRICE],
[UPDATE_USER_CODE],
[UPDATE_PROG_CODE],
GETDATE(),
'U',
[RECORD_STATUS],
[TOTAL_SHARE] ,
([TOTAL_SHARE] - #TOTAL_SHARE_BEFORE_UPDATE)
FROM INSERTED
END
GO

Can I get the last inserted row that a trigger created, inside of a stored procedure?

I have a stored procedure that updates a record. Our DBA created a trigger that updates that row and deactivates the record. It then creates an identical record, but with an active flag and it receives a new auto generated PK. So it goes something like this:
PK=1, Active=1, Data='test' --> PK=1, Active=0, Data='test' --> PK=2, Active=1, Data='test2'
But in my stored procedure, which calls the update, I need to get the last row that the trigger inserted.
Is it possible?
Here is my update code:
UPDATE [OASIS].[dbo].[TT_PEQHeader]
SET
[LastUpdateDate] = GETDATE()
,[LastUpdateBy] =#intUserPK
,[ID] = #vchID
,[Description] = #vchDescription
,[CompletionRate] = #dcCompletionRate
,[IndustryExperiance] = #intIndustryExperiance
WHERE PEQHeaderPK= #intPEQHeaderPK
SELECT * FROM vw_TT_PEQHeader WHERE PEQHeaderPK = #intPEQHeaderPK
I'm currently getting the record based on the PK sent to the SP. That's what I need to change.
Here's the trigger code:
USE [OASIS]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[Update_TT_PEQHeader]
ON [dbo].[TT_PEQHeader]
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT ON;
Declare #dPEQHeaderPK AS INT
Declare #dLastUpdateDate AS DATETIME
Declare #dLastUpdateBy AS INT
Declare #dID AS VARCHAR(25)
Declare #dDescription AS VARCHAR(50)
Declare #dVersion AS INT
Declare #dPreviousVersionPK AS INT
Declare #dActive AS BIT
Declare #dCompletionRate AS DECIMAL(18,2)
Declare #dIndustryExperiance AS INT
Declare #NewPEQHeaderPK AS INT
SELECT
#dPEQHeaderPK =a.PEQHeaderPK,
#dLastUpdateDate = a.LastUpdateDate,
#dLastUpdateBy = a.LastUpdateBy,
#dID = a.ID,
#dDescription = a.Description,
#dVersion = a.Version,
#dPreviousVersionPK = a.PreviousVersionPK,
#dActive = a.Active,
#dCompletionRate = a.CompletionRate,
#dIndustryExperiance = a.IndustryExperiance
FROM INSERTED a
INNER JOIN deleted ON a.PEQHeaderPK = deleted.PEQHeaderPK
/*Deativate the old record*/
Update TT_PEQHeader SET Active = 0 where PEQHeaderPK = #dPEQHeaderPK
IF(#dActive = 1)
BEGIN
/*Copy and paste a new PEQH record*/
INSERT INTO TT_PEQHeader
SELECT GETDATE(),#dLastUpdateBy,GETDATE(),#dLastUpdateBy,#dID,#dDescription,#dVersion + 1,#dPEQHeaderPK,1,#dCompletionRate,#dIndustryExperiance
SELECT #NewPEQHeaderPK = SCOPE_IDENTITY()
/*Copy and paste a new batch of PEQD records*/
INSERT INTO TT_PEQDetail
SELECT GETDATE(),#dLastUpdateBy,GETDATE(),#dLastUpdateBy,#NewPEQHeaderPK,QuestionID,QuestionText FROM TT_PEQDetail WHERE PEQHeaderFK = #dPEQHeaderPK
END
END

Efficiently return a value from a stored procedure

I have query which returns single value (i.e) count. I'm exceuting it using the stored procedure in the following way and using execute reader with dataset to get single value
CREATE PROCEDURE GetCnt
#EmpNo char(4)
AS
BEGIN
SET NOCOUNT ON;
Declare #Cnt int
SELECT #Cnt = count(*)
FROM employees
WHERE EMPLNO = #EmpNo
AND test = 'p'
BEGIN
SELECT #Cnt
END
END
is this effcient way
or Do I need to use the execute.scalar() and return value directly from the query instead of assigning to #cnt
can any one advise me
All ExecuteScalar does is get the first field from the first record.
Can't you just SELECT the count directly?
BEGIN
SET NOCOUNT ON
SELECT Count(*) FROM employees WHERE EMPLNO = #EmpNo AND test='p'
END
You do not need to create the variable. You just need the following:
CREATE PROCEDURE GetCnt
#EmpNo char(4)
AS
BEGIN
SET NOCOUNT ON;
SELECT count(1)
FROM employees
WHERE EMPLNO = #EmpNo
AND test = 'p'
END
Since this is only one value being returned from the stored procedure, you will likely want to use ExecuteScalar()

Resources