SQL Server trigger after insert to another database is not firing - sql-server

Previously I had a TRIGGER in Table46 to fire after an insert to send a message to another server using Service Broker, which was working fine:
CREATE TRIGGER trgSendItemData
ON [dbo].[Table46]
AFTER INSERT
AS
DECLARE #new_event XML;
SET #new_event = (
SELECT i.[046_ID] AS [id]
, NP.NoPart + ' ' + CONVERT(VARCHAR(3), T41.[041_No]) AS [name]
, DATEADD(MINUTE, -1 * i.[046_ExeTime], i.[046_DateTime]) AS [eventstart]
, i.[046_DateTime] AS [eventend]
, i.[046_IDRes] AS [resource_id]
, i.[046_ExeTime] AS [execution]
, ISNULL(MIN(T48.[048_MachTime]), 0) AS [same]
, ISNULL(MIN(T48_1.[048_MachTime]), 0) AS [all]
, i.[046_Pallet] AS [pallet]
FROM inserted AS i
INNER JOIN Table41 AS T41
ON i.[046_IDOp] = T41.[041_IDOp]
INNER JOIN NoParts AS NP
ON T41.[041_IDNoPart] = NP.Autonumber
INNER JOIN Table48 AS T48
ON i.[046_IDRes] = T48.[048_IDRes]
AND i.[046_IDOp] = T48.[048_IDOp]
INNER JOIN Table48 AS T48_1
ON i.[046_IDOp] = T48_1.[048_IDOp]
GROUP BY i.[046_ID], NP.NoPart, T41.[041_No], i.[046_MachTime],
i.[046_DateTime], i.[046_IDRes], i.[046_ExeTime], i.[046_Pallet];
FOR XML AUTO, ELEMENTS
);
DECLARE #ConvHandle UNIQUEIDENTIFIER;
BEGIN TRANSACTION
BEGIN DIALOG #ConvHandle
FROM SERVICE SenderService
TO SERVICE 'ReceiverService'
ON CONTRACT STContract
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION #ConvHandle
MESSAGE TYPE SenderMsg (#new_event);
COMMIT TRANSACTION;
GO
Now I need that same data in a table of another database but in the same server, so I wrote this one which is not working:
USE Database1
GO
CREATE TRIGGER trgSendEvent
ON [dbo].[Table46]
AFTER INSERT
AS BEGIN
SET NOCOUNT ON;
INSERT INTO [Database2].[dbo].[Events]
([id]
,[name]
,[eventstart]
,[eventend]
,[resource_id]
,[execution]
,[same]
,[all]
,[pallet])
SELECT i.[046_ID] AS [id]
, NP.NoPart + ' ' + CONVERT(VARCHAR(3), T41.[041_No]) AS [name]
, DATEADD(MINUTE, -1 * i.[046_ExeTime], i.[046_DateTime]) AS [eventstart]
, i.[046_DateTime] AS [eventend]
, i.[046_IDRes] AS [resource_id]
, i.[046_ExeTime] AS [execution]
, ISNULL(MIN(T48.[048_MachTime]), 0) AS [same]
, ISNULL(MIN(T48_1.[048_MachTime]), 0) AS [all]
, i.[046_Pallet] AS [pallet]
FROM inserted AS i
INNER JOIN Table41 AS T41
ON i.[046_IDOp] = T41.[041_IDOp]
INNER JOIN NoParts AS NP
ON T41.[041_IDNoPart] = NP.Autonumber
INNER JOIN Table48 AS T48
ON i.[046_IDRes] = T48.[048_IDRes]
AND i.[046_IDOp] = T48.[048_IDOp]
INNER JOIN Table48 AS T48_1
ON i.[046_IDOp] = T48_1.[048_IDOp]
GROUP BY i.[046_ID], NP.NoPart, T41.[041_No], i.[046_MachTime],
i.[046_DateTime], i.[046_IDRes], i.[046_ExeTime], i.[046_Pallet];
END;
GO
I know that it isn't working because if I manually run a query to insert a new row in Table46, the new row is added in Table46, but not in Database2.Events. This is what I get as output:
(1 row affected)
Should I get that twice instead?
Also, Table46 constantly receives data but when the trigger is created it stops receiving it.
I also tried running a query to enable the trigger in case it's disabled, but nothing changes.

Related

Update row with values from select on condition, else insert new row

I'm need to run a calculation for month every day. If the month period, exists already, I need to update it, else I need to create a new row for the new month.
Currently, I've written
declare #period varchar(4) = '0218'
DECLARE #Timestamp date = GetDate()
IF EXISTS(select * from #output where period=#period)
/* UPDATE #output SET --- same calculation as below ---*/
ELSE
SELECT
#period AS period,
SUM(timecard.tworkdol) AS dol_local,
SUM(timecard.tworkdol/currates.cdrate) AS dol_USD,
SUM(timecard.tworkhrs) AS hrs,
#Timestamp AS timestamp
FROM dbo.timecard AS timecard
INNER JOIN dbo.timekeep ON timecard.ttk = timekeep.tkinit
INNER JOIN dbo.matter with (nolock) on timecard.tmatter = matter.mmatter
LEFT JOIN dbo.currates with (nolock) on matter.mcurrency = currates.curcode
AND currates.trtype = 'A'
AND timecard.tworkdt BETWEEN currates.cddate1
AND currates.cddate2
WHERE timekeep.tkloc IN('06','07') AND
timecard.twoper = #period
SELECT * FROM #output;
How can simply update my row with the new data from my select.
Not sure what RDBMS are you using, but in SQL Server something like this would update the #output table with the results of the SELECT that you placed in the ELSE part:
UPDATE o
SET o.dol_local = SUM(timecard.tworkdol),
SET o.dol_USD = SUM(timecard.tworkdol/currates.cdrate),
SET o.hrs = SUM(timecard.tworkhrs),
set o.timestamp = #Timestamp
FROM #output o
INNER JOIN dbo.timecard AS timecard ON o.period = timecard.twoper
INNER JOIN dbo.timekeep ON timecard.ttk = timekeep.tkinit
INNER JOIN dbo.matter with (nolock) on timecard.tmatter = matter.mmatter
LEFT JOIN dbo.currates with (nolock) on matter.mcurrency = currates.curcode
AND currates.trtype = 'A'
AND timecard.tworkdt BETWEEN currates.cddate1
AND currates.cddate2
WHERE timekeep.tkloc IN('06','07') AND
timecard.twoper = #period
Also, I think you want to do an INSERT in the ELSE part, but you are doing just a SELECT, so I guess you should fix that too
The answer to this will vary by SQL dialect, but the two main approaches are:
1. Upsert (if your DBMS supports it), for example using a MERGE statement in SQL Server.
2. Base your SQL on an IF:
IF NOT EXISTS (criteria for dupes)
INSERT INTO (logic to insert)
ELSE
UPDATE (logic to update)

Error creating stored procedure in SQL Server with PIVOT operator

I am getting this error when I attempt to create a stored procedure:
SQL Server Database Error: Incorrect syntax near the keyword 'PROC'.
When I execute the SQL between the lines, everything works. However, when I attempt to execute the stored procedure, I get the error.
I'm new to stored procedures, so I am hoping that it is just a misplaced ; or GO.
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
IF EXISTS (SELECT object_id FROM AppGovernmentPrograms.Sys.Objects
WHERE type = 'P'
AND name = 'usp_AppGovernmentPrograms_rptObjectives')
BEGIN
DROP PROCEDURE dbo.usp_AppGovernmentPrograms_rptObjectives
END
GO
CREATE PROC [dbo].[usp_AppGovernmentPrograms_rptObjectives]
#ProgramYear INT,
#SummaryLevel VARCHAR(50)
AS
SET NOCOUNT ON;
WITH measuresPHS AS
(
SELECT
mi.definition_id, mi.metric_name
FROM
StgEpicClarityPHS.dbo.metric_info mi WITH (nolock)
WHERE
mi.definition_id IN (90020350, 90020300, 90020301, 90020302,
90020303, 90020304, 90020305, 90020306,
90020307, 90020308, 90020309, 90020310,
90020311, 90020351, 90020352, 90020353,
90020354, 90020355, 90020400)
)
SELECT
provCID, NPI, TIN, year_dt,
SUM([n90020350]) as "1.1n",
SUM([d90020350]) as "1.1d",
SUM([n90020300]) as "2.1n",
SUM([d90020300]) as "2.1d",
SUM([n90020301]) as "4.1n",
SUM([d90020301]) as "4.1d",
SUM([n90020302]) as "4.2n",
SUM([d90020302]) as "4.2d",
SUM([n90020303]) as "4.3n",
SUM([d90020303]) as "4.3d",
SUM([n90020304]) as "5.1n",
SUM([d90020304]) as "5.1d",
SUM([n90020305]) as "5.2n",
SUM([d90020305]) as "5.2d",
SUM([n90020306]) as "6.1n",
sum([d90020306]) as "6.1d"
, sum([n90020307]) as "6.2n"
, sum([d90020307]) as "6.2d"
, sum([n90020308]) as "6.3n"
, sum([d90020308]) as "6.3d"
, sum([n90020309]) as "7.1n"
, sum([d90020309]) as "7.1d"
, sum([n90020310]) as "7.2n"
, sum([d90020310]) as "7.2d"
, sum([n90020311]) as "7.3n"
, sum([d90020311]) as "7.3d"
, sum([n90020351]) as "8.1n"
, sum([d90020351]) as "8.1d"
, sum([n90020352]) as "8.2n"
, sum([d90020352]) as "8.2d"
, sum([n90020353]) as "8.3n"
, sum([d90020353]) as "8.3d"
, sum([n90020354]) as "8.4n"
, sum([d90020354]) as "8.4d"
, sum([n90020355]) as "8.5n"
, sum([d90020355]) as "8.5d"
, sum([n90020400]) as "IAn"
, sum([d90020400]) as "IAd"
From
(
Select
sfi.prov_target_id as provCID
, prov2.npi
, cmi.facility_group_id as TIN
, sum_data.year_dt
, 'n' + cast(sfi.definition_id as varchar(15)) as id1 -- use for numerator
, 'd' + cast(sfi.definition_id as varchar(15)) as id2 -- use for denominator
, sum_data.numerator_year
, sum_data.denominator_year
from StgEpicClarityPHS.dbo.sum_facts_info sfi with(nolock)
inner join StgEpicClarityPHS.dbo.sum_facts_info_2 sfi2 with(nolock) on sfi2.sum_facts_id = sfi.sum_facts_id
inner join measuresPHS m with(nolock) on m.definition_id = sfi.definition_id
inner join StgEpicClarityPHS.dbo.yearly_data sum_data with(nolock) on sum_data.sum_facts_id = sfi.sum_facts_id
left outer join StgEpicClarityPHS.dbo.cms_mu_info cmi with(nolock) on cmi.cms_mu_id = sfi2.tin_target_id
left outer join StgEpicClarityPHS.dbo.clarity_ser_2 prov2 with(nolock) on sfi.prov_target_id = prov2.prov_id
Where sfi.record_type_c = 1 -- standard summary, not a benchmark
and (sum_data.year_dt = cast(concat('01/01/',:ProgramYear) as datetime)) -- (always use the start date of the reporting period)
and (
(:SummaryLevel = 'NT' and sfi.compld_sum_level = '4^73') -- NPI/TIN (i.e. individual MIPS EC)
or
(:SummaryLevel = 'T' and sfi.compld_sum_level = '73') -- TIN (i.e. Group)
or
(:SummaryLevel = 'N' and sfi.compld_sum_level = '4') -- NPI only
)
) nd
pivot
( sum(NUMERATOR_YEAR)
for id1 in ([n90020350], [n90020300], [n90020301], [n90020302], [n90020303], [n90020304], [n90020305], [n90020306], [n90020307], [n90020308], [n90020309], [n90020310], [n90020311], [n90020351], [n90020352], [n90020353], [n90020354], [n90020355], [n90020400])
) as p1
pivot
( sum(DENOMINATOR_YEAR)
for id2 in ([d90020350], [d90020300], [d90020301], [d90020302], [d90020303], [d90020304], [d90020305], [d90020306], [d90020307], [d90020308], [d90020309], [d90020310], [d90020311], [d90020351], [d90020352], [d90020353], [d90020354], [d90020355], [d90020400])
) as p2
Group By provCID, NPI, TIN, year_dt
--------------------------------------------------------------------------------------------------------------------------------------
;
GO
Your problem may simply be that your query contains a colon at
cast(concat('01/01/',:ProgramYear) as datetime)
in your where clause. It should probably be a #ProgramYear
Also :SummaryLevel should be #SummaryLevel

SQL Server trigger and transaction issue

I have a stored procedure which runs and inserts into 10 separate tables. On the very first table I have an "After insert" trigger. However the stored procedure is wrapped in a transaction and is only committed once it has inserted into all 10 tables.
My question is would my trigger only fire once the stored procedure has been committed? Currently I am experiencing issues whereby the record is inserted via asp.net application fine, but the trigger has not fired (the trigger just captures what row was inserted)
ALTER TRIGGER [dbo].[trProductAllergenUpdate]
ON [dbo].[ProductAllergen]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO AUDIT_PRODUCT (ProductID, Portal_Table, Portal_Column, AuditDescription, UpdateDateTime, OldValue, NewValue)
SELECT
I.ProductID, 'ProductAllergen', 'AllergenStatusID',
'Allergen - ' + AT.AllergenType, Getdate(),
AS2.AllergenStatus, AS1.AllergenStatus
FROM
Inserted I
INNER JOIN
(SELECT PA2.*
FROM ProductAllergen PA2
INNER JOIN
(SELECT
ProductID, AllergenTypeID, MAX(productAllergenID) [ProductAllergenID]
FROM ProductAllergen
WHERE isLive = 0
GROUP BY ProductID, AllergenTypeID) X ON PA2.ProductAllergenID = X.ProductAllergenID
) OLD ON OLD.ProductID = I.ProductID
AND OLD.AllergenTypeID = I.AllergenTypeID
INNER JOIN
ProductAllergen NEW ON NEW.ProductID = OLD.ProductID
AND NEW.AllergenTypeID = OLD.AllergenTypeID
INNER JOIN
AllergenType AT ON I.AllergenTypeID = AT.AllergenTypeID
INNER JOIN
AllergenStatus AS1 ON NEW.AllergenStatusID = AS1.AllergenStatusID
INNER JOIN
AllergenStatus AS2 ON OLD.AllergenStatusID = AS2.AllergenStatusID
WHERE
New.isLive = 1
AND OLD.AllergenStatusID <> NEW.AllergenStatusID
END

Too Many Rows Were Affected error on updating a Transact SQL linked table

I am trying to update a linked table with this...
update openquery (LINKSERVERID, 'select tng_email from user_list where tng_id = 62873')
set tng_email = 'blah#blah.com';
... but I get the following error ...
OLE DB provider "MSDASQL" for linked server "LINKSERVERID" returned message "Key column information is insufficient or incorrect.
Too many rows were affected by update.".
FYI: tng_id is the primary key.
How do I fix?
I think you need to include the key in the select query, so try this:
update openquery(
LINKSERVERID, 'select tng_id, tng_email from user_list where tng_id = 62873'
) set tng_email = 'blah#blah.com';
I tried the answer above from jpw, but it didn't work for me.
I developed a trigger of which I also received the same error using the code below:
begin
if TRIGGER_NESTLEVEL() > 1
return
declare #JCid int = (select top 1 iJCMasterID from inserted)
begin
update L set uiJCTxCMLineNumber = NewLineNum
from (
select
rank() over (order by idJCTxLines) NewLineNum
, iJCMasterID
, uiJCTxCMLineNumber
, idJCTxLines
from _btblJCTxLines
where iJCMasterID = #JCid
) L
where iJCMasterID = #JCid
end
end
go
However, I resolved it by changing it to :
begin
if TRIGGER_NESTLEVEL() > 1
return
declare #JCid int = (select top 1 iJCMasterID from inserted)
begin
update L set uiJCTxCMLineNumber = NewLineNum
from (
select
rank() over (order by idJCTxLines) NewLineNum
, iJCMasterID
, uiJCTxCMLineNumber
, idJCTxLines
from _btblJCTxLines
where iJCMasterID = #JCid
) L
join inserted i on L.idJCTxLines = i.idJCTxLines
end
end
go
Hope this helps.
I solved this error by adding a unique index to the underlying table.

tsql - While Loop issue using temp table

Our DBA has changed a function to be a procedure, so I am amending some of my procedures to cater for this. I've come across a problem with this in one of my procedures where I have a while loop.
I populate my temp table from the new procedure (#DGContol), and then have the following while loop:
SELECT #MinRcd = MIN(RcdNum) FROM #PortfolioDisclosure
SELECT #MaxRcd = MAX(RcdNum) FROM #PortfolioDisclosure
SET #RcdNum = #MinRcd
WHILE #RcdNum <= #MaxRcd
BEGIN
-- Temporarily assign values to variables
SELECT
#PortfolioGroup = PortfolioCode
, #EndDateTime = MaxPositionDate_DetailedDisclosure
FROM #PortfolioDisclosure
WHERE RcdNum = #RcdNum
INSERT INTO #PositionsTable
SELECT
fi.ID_ISIN AS [Fund_ISIN]
, RTRIM(a.acct_id) AS [Internal_Portfolio_Code]
, a.acct_desc AS [Portfolio/Fund_Name]
, CONVERT(CHAR(11),p.as_of_tms,103) AS [Portfolio_Date]
, a.alt_curr_cde AS [Portfolio_Base_Ccy]
, i.iss_desc AS [Security_Description]
, RTRIM(i.pref_iss_id) AS [Security_ID SEDOL/Internal]
, RTRIM(ia.iss_id) AS [Security_ID ISIN]
, i.denom_curr_cde AS [Denomination_Ccy]
, SUM(p.valval_alt_cmb_amt) OVER (PARTITION BY RTRIM(a.acct_id))
AS [Total_Fund_Value]
, p.orig_quantity AS [Shares/Par_Value]
, p.valval_alt_cmb_amt AS [Market_Value]
, p.fld5_rte AS [Pct_of_NAV]
, SUM(CASE WHEN i.issue_cls1_cde = '010' THEN p.valval_alt_cmb_amt ELSE 0 END) OVER (PARTITION BY a.acct_id)
AS [Cash/Cash_Equivalents]
, i.inc_proj_cmb_rte AS [Coupon_Rate]
, CONVERT(CHAR(11),i.mat_exp_dte,103) AS [Maturity_Date]
FROM dw_position_dg AS p
INNER JOIN #DGControl AS dgc -- [M]onthly, [M]ost recent position
ON dgc.DataGrpCtlNum = p.data_grp_ctl_num
INNER JOIN dw_ivw_acct AS a WITH (NOLOCK)
ON a.acct_id = p.acct_id
INNER JOIN dw_issue_dg AS i WITH (NOLOCK)
ON i.instr_id = p.instr_id
LEFT OUTER JOIN dw_issue_alt_id AS ia WITH (NOLOCK)
ON ia.instr_id = i.instr_id
AND ia.id_ctxt_typ = 'ISIN'
INNER JOIN #PortfolioDisclosure AS fi
ON fi.PortfolioCode = p.acct_id
and fi.MaxPositionDate_DetailedDisclosure >= p.as_of_tms
WHERE RTRIM(a.acct_id) NOT IN ( SELECT xref.internal_value FROM dbo.DP_CrossReference as xref
WHERE xref.Codeset_type_id = 10401
AND xref.Originator_id = 'DataVendorPortfolioExclusion')
-- Clear down variable values
SET #PortfolioGroup = NULL
--SET #StartDateTime = NULL
SET #EndDateTime = NULL
-- Move to next record
SET #RcdNum = #RcdNum + 1
END -- END WHILE LOOP
However this returns lots of duplicate records. If I replace the temp table #DGControl with the original function then I get the correct number of records.
I don't really know what the issue would be or how I could re code this while loop so that using the table #DGControl I get the correct number of records. Can anyone help?
Have you compared the output of SELECT * FROM OldFunction(args..) with EXEC NewStoredProcedure args...? If so, does the data returned look the same or has the duplication crept in when the DBA refactored the function to a proc.
If so you may need to de dupe the output from the sp first then run it through your remaining code. In short, if you are using the same arguments for both but they give you different results then you'll need to go back to the DBA.
You aren't using either of your local variables (#PortfolioGroup, #EndDateTime) in this code. It is just inserting the same record set N number of times. Also, I think you can write this as a single select query without using temp tables or while loops and it will make it less confusing.
Thank you for your feedback. i worked out the issue. My code looks like the following now:
BEGIN
SELECT #MinRcd = MIN(RcdNum) FROM #PortfolioDisclosure
SELECT #MaxRcd = MAX(RcdNum) FROM #PortfolioDisclosure
SET #RcdNum = #MinRcd
WHILE #RcdNum <= #MaxRcd
BEGIN
-- Temporarily assign values to variables
SELECT
#PortfolioGroup = PortfolioCode
, #EndDateTime = MaxPositionDate_DetailedDisclosure
FROM #PortfolioDisclosure
WHERE RcdNum = #RcdNum
-- Insert DGControl record into table based on the MaxPositionDate_DetailedDisclosure from Portfolio Disclosure function
INSERT INTO #DGControl
EXEC InfoPortal..usp_Generic_DGControl '', '', #PortfolioGroup, '1', #EndDateTime, #EndDateTime, #PeriodType, 'M', 'POSITION' -- [M]onthly, [M]ost recent position
-- Insert into #PositionsTable
INSERT INTO #PositionsTable
SELECT
fi.ID_ISIN AS [Fund_ISIN]
, RTRIM(a.acct_id) AS [Internal_Portfolio_Code]
, a.acct_desc AS [Portfolio/Fund_Name]
, CONVERT(CHAR(11),p.as_of_tms,103) AS [Portfolio_Date]
, a.alt_curr_cde AS [Portfolio_Base_Ccy]
, i.iss_desc AS [Security_Description]
, RTRIM(i.pref_iss_id) AS [Security_ID SEDOL/Internal]
, RTRIM(ia.iss_id) AS [Security_ID ISIN]
, i.denom_curr_cde AS [Denomination_Ccy]
, SUM(p.valval_alt_cmb_amt) OVER (PARTITION BY RTRIM(a.acct_id))
AS [Total_Fund_Value]
, p.orig_quantity AS [Shares/Par_Value]
, p.valval_alt_cmb_amt AS [Market_Value]
, p.fld5_rte AS [Pct_of_NAV]
, SUM(CASE WHEN i.issue_cls1_cde = '010' THEN p.valval_alt_cmb_amt ELSE 0 END) OVER (PARTITION BY a.acct_id)
AS [Cash/Cash_Equivalents]
, i.inc_proj_cmb_rte AS [Coupon_Rate]
, CONVERT(CHAR(11),i.mat_exp_dte,103) AS [Maturity_Date]
FROM dw_position_dg AS p
INNER JOIN #DGControl AS dgc
ON dgc.DataGrpCtlNum = p.data_grp_ctl_num
INNER JOIN dw_ivw_acct AS a WITH (NOLOCK)
ON a.acct_id = p.acct_id
INNER JOIN dw_issue_dg AS i WITH (NOLOCK)
ON i.instr_id = p.instr_id
LEFT OUTER JOIN dw_issue_alt_id AS ia WITH (NOLOCK)
ON ia.instr_id = i.instr_id
AND ia.id_ctxt_typ = 'ISIN'
INNER JOIN #PortfolioDisclosure AS fi
ON fi.PortfolioCode = p.acct_id
-- Clear down variable values
SET #PortfolioGroup = NULL
--SET #StartDateTime = NULL
SET #EndDateTime = NULL
-- Clear down #DGControl table to allow new record to be inserted
DELETE FROM #DGControl
-- Move to next record
SET #RcdNum = #RcdNum + 1
END -- END WHILE LOOP
Adding the execution of the stored proc usp_Generic_DGControl at the beginning and then clearing it down after each loop stopped the duplication of the records.

Resources