I have a trigger "after insert/update/delete/". It is supposed to count Balance on Account table based on transactions in Transaction table. It is on Transaction table. I am getting Balance discrepancies rarely, so have decided to add some logging into it. It dumps inserted+deleted tables (they are combined into a table var) and tsql statement which fired it. Judging from my log, it looks like the trigger did not fire for some inserts into Transaction table. Can this happen ? Are there any TSQL statement which change table data without firing trigger (except truncate table etc)?
Here is the trigger :
CREATE TRIGGER [dbo].[trg_AccountBalance]
ON [dbo].[tbl_GLTransaction]
AFTER INSERT, UPDATE, DELETE
AS
set nocount on
begin try
declare #OldOptions int = ##OPTIONS
set xact_abort off
declare #IsDebug bit = 1
declare #CurrentDateTime datetime = getutcdate()
declare #TriggerMessage varchar(max), #TriggerId int
if #IsDebug = 1
begin
select #TriggerId = isnull(max(TriggerId), 0) + 1
from uManageDBLogs.dbo.tbl_TriggerLog
declare #dbcc_INPUTBUFFER table(EventType nvarchar(30), Parameters Int, EventInfo nvarchar(4000) )
declare #my_spid varchar(20) = CAST(##SPID as varchar(20))
insert #dbcc_INPUTBUFFER
exec('DBCC INPUTBUFFER ('+#my_spid+')')
select #TriggerMessage = replace(EventInfo, '''', '''''') from #dbcc_INPUTBUFFER
insert into uManageDBLogs.dbo.tbl_TriggerLog (TriggerId, "Message", CreateDate)
values (#TriggerId, #TriggerMessage, #CurrentDateTime)
end
declare #Oper int
select #Oper = 0
-- determine type of sql statement
if exists (select * from inserted) select #Oper = #Oper + 1
if exists (select * from deleted) select #Oper = #Oper + 2
if #IsDebug = 1
begin
select #TriggerMessage = '#Oper = ' + convert(varchar, #Oper)
insert into uManageDBLogs.dbo.tbl_TriggerLog (TriggerId, "Message", CreateDate)
values (#TriggerId, #TriggerMessage, #CurrentDateTime)
end
if #Oper = 0 return -- No data changed
declare #TomorrowDate date = dateadd(day, 1, convert(date, getdate()))
declare #CurrentDate date = convert(date, getdate())
-- transactions from both inserted and deleted tables
declare #tbl_Trans table (FirmId int, GLAccountId int,
AmountDebit money, AmountCredit money, "Status" char(1), TableType char(1))
declare #tbl_AccountCounters table (FirmId int, GLAccountId int, Balance money)
declare #IsChange bit = null
insert into #tbl_Trans (FirmId, GLAccountId, AmountDebit, AmountCredit, "Status", TableType)
select FirmId, GLAccountId, AmountDebit, AmountCredit, "Status", 'I'
from inserted
union
select FirmId, GLAccountId, AmountDebit, AmountCredit, "Status", 'D'
from deleted
if #IsDebug = 1
begin
select #TriggerMessage = (select * from #tbl_Trans for xml path ('tbl_Trans'))
insert into uManageDBLogs.dbo.tbl_TriggerLog (TriggerId, "Message", CreateDate)
values (#TriggerId, #TriggerMessage, #CurrentDateTime)
end
insert into #tbl_AccountCounters (FirmId, GLAccountId, Balance)
select FirmId, GLAccountId, 0
from #tbl_Trans
group by FirmId, GLAccountId
if #Oper = 1 or #Oper = 2 -- insert/delete
begin
update #tbl_AccountCounters
set Balance = cnt.TransSum
from #tbl_AccountCounters as ac join
(
select trans.FirmId, trans.GLAccountId,
isnull(sum((trans.AmountDebit - trans.AmountCredit) * iif(trans.TableType = 'I', 1, -1)), 0) as TransSum
from #tbl_Trans as trans
where trans.Status = 'A'
group by trans.FirmId, trans.GLAccountId
) as cnt on ac.FirmId = cnt.FirmId and ac.GLAccountId = cnt.GLAccountId
select #IsChange = 1
end
else
begin
if update(AmountDebit) or update(AmountCredit) or update(Status) or update(GLAccountId)
begin
update #tbl_AccountCounters
set Balance = cnt.TransBalance
from #tbl_AccountCounters as ac join
(select trans.FirmId, trans.GLAccountId, isnull(sum(trans.AmountDebit - trans.AmountCredit), 0) as TransBalance
from dbo.tbl_GLTransaction as trans
where trans."Status" = 'A' and exists (select 1 from #tbl_AccountCounters as ac
where ac.GLAccountId = trans.GLAccountId and ac.FirmId = trans.FirmId)
group by trans.FirmId, trans.GLAccountId) as cnt on
ac.FirmId = cnt.FirmId and ac.GLAccountId = cnt.GLAccountId
select #IsChange = 0
end
end
if #IsDebug = 1
begin
select #TriggerMessage = '#IsChange = ' + isnull(convert(varchar, #IsChange), 'null')
insert into uManageDBLogs.dbo.tbl_TriggerLog (TriggerId, "Message", CreateDate)
values (#TriggerId, #TriggerMessage, #CurrentDateTime)
select #TriggerMessage = (select * from #tbl_AccountCounters for xml path ('tbl_AccountCounters'))
insert into uManageDBLogs.dbo.tbl_TriggerLog (TriggerId, "Message", CreateDate)
values (#TriggerId, #TriggerMessage, #CurrentDateTime)
end
if #IsChange is not null
begin
update tbl_GLAccount
set tbl_GLAccount.Balance = iif(#IsChange = 1, cnt.Balance + acc.Balance, cnt.Balance),
tbl_GLAccount.LastUpdate = getutcdate(),
tbl_GLAccount.LastUpdatedBy = 1
from #tbl_AccountCounters as cnt join dbo.tbl_GLAccount as acc on
cnt.FirmId = acc.FirmId and cnt.GLAccountId = acc.GLAccountId
end
if (16384 & #OldOptions) = 16384 set xact_abort on
end try
begin catch
declare #ErrorLine varchar(max)
select #ErrorLine = uManageDb.dbo.udf_GetErrorInfo()
insert into uManageDb.dbo.tbl_TriggerError ("Name", "Message", CreateDate)
values ('AccountingDB..trg_AccountBalance', #ErrorLine, GETUTCDATE())
end catch
I think I've found it. I have this line:
select .. from inserted
union
select .. from deleted
and they inserted 5 trans for $300 and 4 trans $100. I've got 2 records (300 and 100) in my #tbl_Trans (it was in the log). That's probably was the bug. So log hellps and trigger run as it had to.
I'll replace union with union all.
Related
The stored procedure is running very slow in SQL Server 2016 as compared to SQL Server 2019. It's doing some common validation from a temporary staging table and inserting data in primary tables and mapping tables.
The mapping tables have clustered indexes on primary keys {Table1Id, Table2Id, Table3Id}. The procedure needs to process around 4 million rows. It finishes execution in 2 hours in SQL Server 2019, but takes probably 6-8 hours in SQL Server 2016 with the same data file.
Description of the stored proc -
There is a dbo.HouseholdTemp table with all rows to be processed its doing
Slice each row and insert one portion in dbo.Locations and another
potion in dbo.Individuals table if LocationGroupId or IndividualGroupId
does not exists or is empty.
Save the generated ID from those two tables and map them in dbo.Households table {LocationId, IndividualId}.
Select an existing MailingId from dbo.Mailings table with a JOIN query.
Insert another row in dbo.ListTypes table if the combination of Type and Code does not exists and get the ListTypes Id.
Insert a row in the dbo.HouseholdMailings table with MailingId,
LocationId, IndividualId , ListTypeId.
Execution plan is attached.
FYI, The SQL installation is on C drive where as the database files are on D drive. Please help!
Execution plan can be found here : https://www.brentozar.com/pastetheplan/?id=BybjNm5a8
CREATE PROCEDURE [dbo].[usp_ProcessHouseholdDatav2]
AS
BEGIN TRY
-- Declare variables
DECLARE #DataIngestionLogId int = 0;
DECLARE #HouseholdCount bigint = 0;
DECLARE #n int = 0;
DECLARE #householdrecords int = 0;
DECLARE #householdrecordsexistscount int = 0;
DECLARE #householdmailingsrecords int = 0;
DECLARE #householdmailingsrecordsexistscount int = 0;
DECLARE #listtyperecords int = 0;
DECLARE #tempid int = 0;
DECLARE #locationid int = 0;
DECLARE #individualid int = 0;
DECLARE #mailingid int = 0;
DECLARE #jobnumber nvarchar(6) = N'';
DECLARE #mergedpanelcode nvarchar(10) = N'';
DECLARE #locationgroupid nvarchar(10) = N'';
DECLARE #individualgroupid nvarchar(10) = N'';
DECLARE #listtype varchar(3) = '';
DECLARE #listcode varchar(4) = '';
DECLARE #findernumber nvarchar(50) = N'';
DECLARE #modelrank nvarchar(2) = N'';
DECLARE #listtypeid int = 0;
DECLARE #starttime datetime = GETDATE();
INSERT INTO dbo.DataIngestionLogs (FileName,
Message,
CreatedDate)
VALUES ('usp_ProcessHouseholdData', 'PROCESS STARTED ' + CAST(#HouseholdCount AS nvarchar(10)) + ' records to be processed', GETDATE());
SET #DataIngestionLogId = SCOPE_IDENTITY();
WHILE EXISTS (SELECT TOP 1 1 FROM dbo.HouseholdTemp ht WHERE ht.ProcessedDate IS NULL /*AND #n < 1000000*/ )
BEGIN
-- Retrieve Id, JobNumber and MergedPanelCode from HouseholdTemp table
SELECT TOP 1
#tempid = ht.Id,
#jobnumber = ht.JobNumber,
#mergedpanelcode = ht.MergedPanelCode,
#locationgroupid = ht.LocationGroupID,
#individualgroupid = ht.IndividualGroupID,
#listtype = ht.ListType,
#listcode = ht.ListCode,
#findernumber = ht.FinderNumber,
#modelrank = ht.ModelRank
FROM dbo.HouseholdTemp ht
WHERE ht.ProcessedDate IS NULL;
IF (#locationgroupid IS NULL OR #locationgroupid = '')
BEGIN
INSERT INTO dbo.Locations (LocationGroupId,
Address1,
Address2,
City,
State,
Zip10,
ZipCode,
DeliveryPointCode,
FIPSCounty,
CountyName,
AddressType,
PrimaryNumber,
PreDirectional,
StreetName,
StreetSuffix,
PostDirectional,
UnitDesignator,
UnitNumber,
PMBNumber,
CarrierRoute,
PenetrationCode,
MetroName,
CreatedDate,
ModifiedDate)
SELECT TOP 1
ht.LocationGroupID AS LocationGroupID,
ht.Address1 AS Address1,
ht.Address2 AS Address2,
ht.City AS City,
ht.State AS State,
ht.Zip10 AS Zip10,
ht.ZipCode AS ZipCode,
ht.DeliveryPointCode AS DeliveryPointCode,
ht.FIPSCounty AS FIPSCounty,
ht.CountyName AS CountyName,
ht.AddressType AS AddressType,
ht.PrimaryNumber AS PrimaryNumber,
ht.PreDirectional AS PreDirectional,
ht.StreetName AS StreetName,
ht.StreetSuffix AS StreetSuffix,
ht.PostDirectional AS PostDirectional,
ht.UnitDesignator AS UnitDesignator,
ht.UnitNumber AS UnitNumber,
ht.PMBNumber AS PMBNumber,
ht.CarrierRoute AS CarrierRoute,
ht.PenetrationCode AS PenetrationCode,
ht.MetroName AS MetroName,
GETDATE(),
GETDATE()
FROM dbo.HouseholdTemp ht
WHERE ht.Id = #tempid;
SET #locationid = SCOPE_IDENTITY();
END;
ELSE
BEGIN
-- Check if record exists with LocationGroupId in Locations table
IF (NOT EXISTS (SELECT TOP 1
1
FROM dbo.Locations l
WHERE l.LocationGroupId = RTRIM(LTRIM(#locationgroupid))))
BEGIN
-- PRINT 'Location does not exists with LocationGroupId : ' + #locationgroupid + '--> Insert in Locations table....'
INSERT INTO dbo.Locations (LocationGroupId,
Address1,
Address2,
City,
State,
Zip10,
ZipCode,
DeliveryPointCode,
FIPSCounty,
CountyName,
AddressType,
PrimaryNumber,
PreDirectional,
StreetName,
StreetSuffix,
PostDirectional,
UnitDesignator,
UnitNumber,
PMBNumber,
CarrierRoute,
PenetrationCode,
MetroName,
CreatedDate,
ModifiedDate)
SELECT TOP 1
ht.LocationGroupID AS LocationGroupID,
ht.Address1 AS Address1,
ht.Address2 AS Address2,
ht.City AS City,
ht.State AS State,
ht.Zip10 AS Zip10,
ht.ZipCode AS ZipCode,
ht.DeliveryPointCode AS DeliveryPointCode,
ht.FIPSCounty AS FIPSCounty,
ht.CountyName AS CountyName,
ht.AddressType AS AddressType,
ht.PrimaryNumber AS PrimaryNumber,
ht.PreDirectional AS PreDirectional,
ht.StreetName AS StreetName,
ht.StreetSuffix AS StreetSuffix,
ht.PostDirectional AS PostDirectional,
ht.UnitDesignator AS UnitDesignator,
ht.UnitNumber AS UnitNumber,
ht.PMBNumber AS PMBNumber,
ht.CarrierRoute AS CarrierRoute,
ht.PenetrationCode AS PenetrationCode,
ht.MetroName AS MetroName,
GETDATE(),
GETDATE()
FROM dbo.HouseholdTemp ht
WHERE ht.Id = #tempid;
SET #locationid = SCOPE_IDENTITY();
END;
ELSE
BEGIN
SELECT TOP 1
#locationid = Id
FROM dbo.Locations l
WHERE l.LocationGroupId = RTRIM(LTRIM((#locationgroupid)));
END;
END;
IF (#individualgroupid IS NULL OR #individualgroupid = '')
BEGIN
INSERT INTO dbo.Individuals (IndividualGroupId,
FirstName,
LastName,
DateOfBirth,
EmailAddress,
Gender,
MaritalStatus,
CreatedDate,
ModifiedDate)
SELECT ht.IndividualGroupID AS IndividualGroupId,
ht.FirstName AS FirstName,
ht.LastName AS LastName,
CAST(ht.DateOfBirth AS date) AS DateOfBirth,
ht.EmailAddress AS EmailAddress,
ht.Gender AS Gender,
ht.MaritalStatus AS MaritalStatus,
GETDATE(),
GETDATE()
FROM dbo.HouseholdTemp ht
WHERE ht.Id = #tempid;
SET #individualid = SCOPE_IDENTITY();
END;
ELSE
BEGIN
-- Check if record exists with IndividualGroupId in Individuals table
IF (NOT EXISTS (SELECT TOP 1
1
FROM dbo.Individuals i
WHERE i.IndividualGroupId = RTRIM(LTRIM((#individualgroupid)))))
BEGIN
INSERT INTO dbo.Individuals (IndividualGroupId,
FirstName,
LastName,
DateOfBirth,
EmailAddress,
Gender,
MaritalStatus,
CreatedDate,
ModifiedDate)
SELECT ht.IndividualGroupID AS IndividualGroupId,
ht.FirstName AS FirstName,
ht.LastName AS LastName,
CAST(ht.DateOfBirth AS date) AS DateOfBirth,
ht.EmailAddress AS EmailAddress,
ht.Gender AS Gender,
ht.MaritalStatus AS MaritalStatus,
GETDATE(),
GETDATE()
FROM dbo.HouseholdTemp ht
WHERE ht.Id = #tempid;
SET #individualid = SCOPE_IDENTITY();
END;
ELSE
BEGIN
SELECT TOP 1
#individualid = Id
FROM dbo.Individuals i
WHERE i.IndividualGroupId = RTRIM(LTRIM(#individualgroupid));
END;
END;
IF (#locationid > 0 AND #individualid > 0)
BEGIN
BEGIN TRY
INSERT INTO dbo.Households (LocationId,
IndividualId,
CreatedDate)
VALUES (#locationid, #individualid, GETDATE());
SET #householdrecords = #householdrecords + 1;
END TRY
BEGIN CATCH
END CATCH;
-- Get Mailing Id from JobNumber and MergedPanelCode
SELECT TOP 1
#mailingid = m.Id
FROM dbo.Mailings m
INNER JOIN dbo.Jobs j ON j.Id = m.JobId
INNER JOIN dbo.MergedPanels mp ON mp.Id = m.MergedPanelId
WHERE j.Number = #jobnumber
AND mp.Code = #mergedpanelcode;
IF (#mailingid > 0)
BEGIN
IF ((#listtype IS NOT NULL
OR #listtype != '')
AND (#listcode IS NOT NULL
OR #listcode != ''))
BEGIN
IF NOT EXISTS (SELECT TOP 1
1
FROM dbo.ListTypes lt
WHERE lt.Type = #listtype
AND lt.Code = #listcode)
BEGIN
INSERT INTO dbo.ListTypes (Type,
Code,
CreatedDate,
ModifiedDate)
VALUES (#listtype, #listcode, GETDATE(), GETDATE());
SET #listtypeid = SCOPE_IDENTITY();
SET #listtyperecords = #listtyperecords + 1;
END;
ELSE
BEGIN
SELECT TOP 1
#listtypeid = Id
FROM dbo.ListTypes lt
WHERE lt.Type = #listtype
AND lt.Code = #listcode;
END;
END;
IF (#listtypeid > 0)
BEGIN TRY
INSERT INTO dbo.HouseholdMailings (MailingId,
LocationId,
IndividualId,
ListTypeId,
FinderNumber,
ModelRank,
CreatedDate)
VALUES (#mailingid, #locationid, #individualid, #listtypeid, #findernumber, #modelrank, GETDATE());
SET #listtypeid = 0;
SET #householdmailingsrecords = #householdmailingsrecords + 1;
END TRY
BEGIN CATCH
END CATCH;
END;
ELSE
BEGIN
SET #householdmailingsrecordsexistscount = #householdmailingsrecordsexistscount + 1;
END;
END;
-- Update the ProcessedDate in HouseholdTemp table
UPDATE dbo.HouseholdTemp
SET ProcessedDate = GETDATE()
WHERE Id = #tempid;
SET #n = #n + 1;
SET #locationid = 0;
SET #individualid = 0;
SET #mailingid = 0;
END;
INSERT INTO dbo.DataIngestionLogs (FileName,
Message,
ParentId,
CreatedDate)
VALUES ('usp_ProcessHouseholdData', 'PROCESS COMPLETED ' + CAST(#n AS nvarchar(10)) + ' records processed.', #DataIngestionLogId, GETDATE());
END TRY
BEGIN CATCH
PRINT 'Error insert...';
INSERT INTO dbo.DataIngestionErrors
VALUES (SUSER_SNAME(), ERROR_NUMBER(), ERROR_STATE(), ERROR_SEVERITY(), ERROR_LINE(), ERROR_PROCEDURE(), ERROR_MESSAGE(), GETDATE(), #DataIngestionLogId);
END CATCH;
So I created a Stored Procedure in SQL that does 4 things
Create Order into Customer Order table
Create Order lines on Customer Order Line table
Update Auto number column by taking current value and adding 1
Update Purchase Order with Customer Order ID
Sends email to notify that an order has been created.
It works awesome if I execute each part separately or execute the whole Stored Procedure manually by sending command EXEC dbo.POIMPORT_UK #PO_NUM = 123456
But when I create a PO and it triggers the inserts, query 1,3,4,5 work but 2 doesn't for some reason. I can only get it to go if I fire off that procedure manually. Any thoughts?
USE [RIPTST]
GO
/****** Object: StoredProcedure [dbo].[POIMPORT_UK] Script Date: 8/20/2018 11:21:23 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER proc [dbo].[POIMPORT_UK]
#PO_NUM NVARCHAR(15)
AS
SET NOCOUNT ON
--For synchronization machine id placement
--Query 1
INSERT INTO CUSTOMER_ORDER(ID, CUSTOMER_ID, SITE_ID, SELL_RATE, BUY_RATE,
TERMS_NET_TYPE, TERMS_DISC_TYPE, FREIGHT_TERMS, BACK_ORDER, STATUS,
POSTING_CANDIDATE, MARKED_FOR_PURGE, CURRENCY_ID, CUSTOMER_PO_REF,
WAREHOUSE_ID, DESIRED_SHIP_DATE) SELECT (SELECT Next_number FROM
NEXT_NUMBER_GEN where rowid =
'72'),'ABECO','101RIPUS','1.0','1.0','A','A','P','N','F','N','N','(USD)
$',ID,'CROM',Getdate() FROM PURCHASE_ORDER WHERE ID = #PO_NUM
--Query 2
INSERT INTO CUST_ORDER_LINE
(CUST_ORDER_ID,LINE_NO,PART_ID,LINE_STATUS,ORDER_QTY,USER_ORDER_QTY,
SELLING_UM,UNIT_PRICE,SITE_ID,MISC_REFERENCE,PRODUCT_CODE,COMMODITY_CODE,
DRAWING_ID,DRAWING_REV_NO,MAT_GL_ACCT_ID,LAB_GL_ACCT_ID,BUR_GL_ACCT_ID,
SER_GL_ACCT_ID,GL_REVENUE_ACCT_ID,TOTAL_AMT_ORDERED,ENTERED_BY,WAREHOUSE_ID)
SELECT(select id from customer_order where CUSTOMER_PO_REF = #PO_NUM),
LINE_NO,PURC_ORDER_LINE.PART_ID,'A',ORDER_QTY,USER_ORDER_QTY,
PURCHASE_UM,PURC_ORDER_LINE.UNIT_PRICE,'101RIPUS',PART.DESCRIPTION,
PART.PRODUCT_CODE,PART.COMMODITY_CODE,PART.DRAWING_ID,PART.DRAWING_REV_NO,
PART_SITE.MAT_GL_ACCT_ID,PART_SITE.LAB_GL_ACCT_ID,PART_SITE.BUR_GL_ACCT_ID,
PART_SITE.SER_GL_ACCT_ID,
(SELECT REV_GL_ACCT_ID FROM PRODUCT WHERE CODE = PART.PRODUCT_CODE),
USER_ORDER_QTY*PURC_ORDER_LINE.UNIT_PRICE,'SYSADM',
PART_SITE.PRIMARY_WHS_ID From PURC_ORDER_LINE
Inner Join PART On PART.ID = PURC_ORDER_LINE.PART_ID
Inner Join PART_SITE On PART_SITE.PART_ID = PART.ID
WHERE PURC_ORDER_ID = #PO_NUM AND PART_SITE.sITE_ID = '101RIPUS'
--Query 3
Update NEXT_NUMBER_GEN Set Next_number = Next_number + 1 where rowid = '72'
--Query 4
Update PURCHASE_ORDER Set SALES_ORDER_ID = (select id from customer_order where CUSTOMER_PO_REF = #PO_NUM) where id = #PO_NUM
--Query 5
Declare #PO NVARCHAR(15) = #PO_NUM
Declare #CO NVARCHAR(15) = (select id from customer_order where CUSTOMER_PO_REF = #PO)
Declare #MYBODY VARCHAR(MAX) = 'Hello Test CSR,
A new internal order has been created for Ripley UK.
Test US Customer Order Number: ' + #CO +
'
Test UK Purchase Order Number: ' + #PO
EXEC msdb.dbo.sp_send_dbmail #profile_name='office365',
#recipients='test#test.com',
#subject='Test UK - Internal Order',
#body= #MYBODY
SET NOCOUNT OFF
Insert Trigger
USE [RIPTST]
GO
/****** Object: Trigger [dbo].[INSERT_PURCHASE_ORDER] Script Date: 8/20/2018 1:42:15 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER trigger [dbo].[INSERT_PURCHASE_ORDER] ON [dbo].[PURCHASE_ORDER] FOR INSERT AS
DECLARE
#nRcd INT,
#ID NVARCHAR(15),
#VENDOR_ID NVARCHAR(15),
#SITE_ID NVARCHAR(15),
#STATUS NCHAR,
#TOTAL_AMT_ORDERED DEC(15,2),
#TOTAL_AMT_RECVD DEC(15,2),
#SELL_RATE DEC(17,8),
#nCurrDigits INT,
#sEntityID NVARCHAR(15),
#ORDER_DATE DATETIME
SELECT #nRcd = 0
SET NOCOUNT ON
DECLARE PURCHASE_ORDER_INS CURSOR LOCAL FOR SELECT ID, VENDOR_ID, STATUS, TOTAL_AMT_ORDERED, TOTAL_AMT_RECVD, SELL_RATE, ORDER_DATE, SITE_ID FROM INSERTED
OPEN PURCHASE_ORDER_INS
FETCH PURCHASE_ORDER_INS INTO #ID, #VENDOR_ID, #STATUS, #TOTAL_AMT_ORDERED, #TOTAL_AMT_RECVD, #SELL_RATE, #ORDER_DATE, #SITE_ID
WHILE (#nRcd = 0 and ##FETCH_STATUS <> -1)
BEGIN
EXEC EXE_DETECT_EVENT 'P', #ID, NULL, NULL, 'I'
If #TOTAL_AMT_ORDERED + #TOTAL_AMT_RECVD != 0
SELECT #nRcd = 30881
If #nRcd = 0 And (#STATUS = 'R' Or #STATUS = 'F') And #TOTAL_AMT_ORDERED > #TOTAL_AMT_RECVD
BEGIN
select #nCurrDigits = c.i_curr_digits, #sEntityID = s.entity_id from CURRENCY c, ACCOUNTING_ENTITY ae, SITE s where s.id = #SITE_ID and ae.id = s.entity_id and ae.functional_currency_id = c.id
IF NOT EXISTS ( SELECT VENDOR_ID FROM VENDOR_ENTITY WHERE vendor_id = #VENDOR_ID and entity_id = #sEntityID )
INSERT INTO VENDOR_ENTITY ( VENDOR_ID, ENTITY_ID ) VALUES ( #VENDOR_ID, #sEntityID )
update VENDOR_ENTITY set
total_open_orders = total_open_orders + ROUND((#TOTAL_AMT_ORDERED - #TOTAL_AMT_RECVD) * #SELL_RATE, #nCurrDigits),
open_order_count = open_order_count + 1
where vendor_id = #VENDOR_ID and entity_id = #sEntityID
END
UPDATE VENDOR set last_order_date = #ORDER_DATE where id = #VENDOR_ID
FETCH PURCHASE_ORDER_INS INTO #ID, #VENDOR_ID, #STATUS, #TOTAL_AMT_ORDERED, #TOTAL_AMT_RECVD, #SELL_RATE, #ORDER_DATE, #SITE_ID
END
BEGIN
IF #VENDOR_ID = 'RIP01' AND #SITE_ID = '111RIPUK'
EXEC dbo.POIMPORT_UK #PO_NUM = #ID
END
DEALLOCATE PURCHASE_ORDER_INS
IF (#nRcd <> 0) RAISERROR('VMFG-%d error in trigger INSERT_PURCHASE_ORDER', 16, -1, #nRcd)
IF (#nRcd <> 0 Or ##ERROR <> 0) ROLLBACK TRANSACTION
I get an error
Subquery returned more than 1 value
when executing a stored procedure. I need to copy data from the database I am building to the live database. The code inserted the data into TestTextmessage table and updateed TextMessage table. The error occurred when try to insert into the TestMobileRecipient table that is the reason why the table is empty.
The table structure and code are below
Stored procedure
CREATE PROCEDURE [dbo].[TestSendITMessage]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #i int
DECLARE #idmessage int
DECLARE #numrows int
DECLARE #messagehold TABLE
(
idx SMALLINT PRIMARY KEY IDENTITY(1,1),
MessageId INT
)
DECLARE #InsertedID INT
INSERT INTO #messagehold
SELECT DISTINCT Id
FROM [MPFT_SendIT].dbo.TextMessage
WHERE DontSendBefore < GETDATE()
AND DateSent IS NULL
AND MessageSent = 0
SET #i = 1
SET #numrows = (SELECT COUNT(*) FROM #messagehold)
IF #numrows > 0
WHILE (#i <= (SELECT MAX(idx) FROM #messagehold))
BEGIN
SET #idmessage = (SELECT MessageId FROM #messagehold WHERE idx = #i)
--Do something with Id here
PRINT #idmessage
INSERT INTO [dbo].[TestTextMessage] ([Origin], [MessageBody], [MessageSent], [DateCreated], DontSendBefore)
SELECT
'LogIT', MessageBody, 0, GETDATE(), DontSendBefore
FROM
[MPFT_SendIT].dbo.TextMessage
WHERE Id = #idmessage
SET #InsertedID = SCOPE_IDENTITY();
INSERT INTO [dbo].[TestMobileRecipient] ([MessageId], MobileNumber])
VALUES (#InsertedID, (SELECT MobileNumber FROM MobileRecipient
WHERE MessageId = #idmessage))
UPDATE TextMessage
SET DateSent = GETDATE(),
MessageSent = 1
WHERE Id = #idmessage
SET #i = #i + 1
END
END
the error message is very clear. Your sub-query SELECT MobileNumber FROM MobileRecipient WHERE MessageId= #idmessage is returning more than 1 row
Change the insertion of table TestMobileRecipient to following
Insert into [dbo].[TestMobileRecipient]
(
[MessageId]
,[MobileNumber]
)
SELECT #InsertedID
, MobileNumber
FROM MobileRecipient
WHERE MessageId= #idmessage
You should update your this line
SET #idmessage = (SELECT MessageId FROM #messagehold WHERE idx = #i)
with
SET #idmessage = (SELECT top 1 MessageId FROM #messagehold WHERE idx = #i)
I know that a bigint should implicitly convert to a float but it does not seem to.
Table column to be updated:
[GBUsed] [float] NOT NULL,
Example of data in that column:
430.5
Logic: I'm summing 2 bigint columns together and dividing by 1024. An example of 1 of the row - I get: 1545
I the update the GBUsed column which is defined as float but it does not convert. I still get the 1545.
Stored procedure:
CREATE PROCEDURE [dbo].[RecalculateBandwidthUsage]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #RowCount int,
#Rc int,
#Message varchar(max),
#CurrentDateTime datetime
CREATE TABLE #Temp
(
SwitchID int,
PortIndex int,
SwitchIP varchar(50),
GBUsed bigint
)
SET #CurrentDateTime = GETDATE()
-- FOR TESTING:
BEGIN TRANSACTION
INSERT #Temp (SwitchID, PortIndex, SwitchIP, GBUsed)
SELECT
c.SwitchID, c.PortIndex,
s.SwitchIP,
SUM ((c.BandwidthIn + c.BandwidthOut) / 1024) AS GBUsed -- converting to gigabytes
FROM
dbo.BandwidthLogCalculatedTest6 c
INNER JOIN
Switch s ON (c.SwitchID = s.SwitchID)
WHERE
(c.StartDate < DATEADD(HOUR, -1, #CurrentDateTime)
AND c.EntryType = 'Second')
GROUP BY
c.SwitchID, c.PortIndex, s.SwitchIP
ORDER BY
c.PortIndex
SELECT
#Rc = ##ERROR,
#RowCount = ##ROWCOUNT
IF #Rc <> 0
BEGIN
SELECT #Message = 'Critical Error - procedure RecalculateBandwidthUsage - on select. Return code: ' + Cast(#Rc as varchar)
RAISERROR (#Message, 16, 1)
END
-- FOR TESTING:
SELECT 'Temp table '
SELECT *
FROM #temp
ORDER BY PortIndex
IF #RowCount > 0
BEGIN
-- FOR TESTING:
SELECT 'Before update '
SELECT b.SwitchIP, b.SwitchPort, b.GBUsed
FROM dbo.Bandwidth b
INNER JOIN #temp t ON (b.SwitchIP = t.SwitchIP AND b.SwitchPort = t.PortIndex )
ORDER BY b.SwitchPort
-- Update.
UPDATE dbo.Bandwidth
SET GBUsed = CONVERT(float, t.Gbused)
FROM #Temp t
WHERE (Bandwidth.SwitchIP = t.SwitchIP AND Bandwidth.SwitchPort = t.PortIndex)
SELECT #Rc = ##ERROR
IF #Rc <> 0
BEGIN
SELECT #Message = 'Critical Error - procedure RecalculateBandwidthUsage - on Bandwidth update. Return code: ' + Cast(#Rc as varchar)
RAISERROR (#Message, 16, 1)
END
-- FOR TESTING:
SELECT 'After update '
SELECT b.SwitchIP, b.SwitchPort, b.GBUsed
FROM dbo.Bandwidth b
INNER JOIN #temp t ON (b.SwitchIP = t.SwitchIP AND b.SwitchPort = t.PortIndex)
ORDER BY b.SwitchPort
END
ROLLBACK TRANSACTION
END
You are doing an integer division - so therefore, your result will also be an integer (or BIGINT).
You need to use this code in order to get fractional values:
SUM ((c.BandwidthIn + c.BandwidthOut) / 1024.0) AS GBUsed
Dividing by 1024.0 (instead of just 1024) will make sure to use fractional values
and thanks in advance
I have a very basic stored procedure that inserts a row into a table. It has been working flawlessly until today
Here is the script
(
#emp varchar(16),
#logdate date,
#logtime time,
#term char(20),
#SSID char(16)
)
AS
INSERT INTO AccessLog (EmployeeID, LogDate, LogTime, TerminalID, InOut, ChangedBy)
VALUES (#emp, #logdate, #logtime, #term, 3, #SSID)
When the string of 5118 is passed to it the insert will fail. There are several triggers that fire after this insert finishes.
Here's the strange part. You can pass it anyother number for the #emp variable and it works just fine, but pass it 5118, it fails.
The error I receive is below:
Msg 241, Level 16, State 1, Procedure UpdateTimeWorked, Line 27
Conversion failed when converting date and/or time from character
string.
Here is the procedure that is failing – the highlighted line is Line 27
TRIGGER [dbo].[UpdateTimeWorked] ON [dbo].[TimeLog]
FOR UPDATE
AS
SET NOCOUNT ON
DECLARE #ID int;
DECLARE #RCDIDIN int;
DECLARE #RCDIDOUT int;
DECLARE #ComboIn datetime;
DECLARE #ComboOut datetime;
SELECT #ID = ID FROM INSERTED;
SELECT #ComboIn = LoginCombo FROM INSERTED;
SELECT #ComboOut = LogoutCombo FROM INSERTED;
SELECT #RCDIDIN = RCDIDIN FROM INSERTED;
SELECT #RCDIDOUT = RCDIDOUT FROM INSERTED;
**IF ( UPDATE(LogoutCombo))**
BEGIN
IF (#RCDIDOUT != 0)
BEGIN
UPDATE TimeLog
SET LogOutRND = (select CAST(dbo.roundtime(LogOutRND,0.25) AS TIME))
WHERE ID = #ID
UPDATE TimeLog
SET LogOutComboRND = CAST(CAST(LogOutDate AS DATE) AS SMALLDATETIME) + CAST(LogOutRND AS TIME)
WHERE ID = #ID
UPDATE TimeLog
SET TimeWorked = dbo.gettime(DATEDIFF(ss,LogInComboRND,LogoutComboRND))
WHERE ID = #ID AND LogInEntered = 1 AND LogOutEntered = 1
UPDATE TimeLog
SET TimeWorked = (select CAST(dbo.roundtime(TimeWorked,0.25) AS TIME)), Rounded = 1
WHERE ID = #ID AND LogInEntered = 1 AND LogOutEntered = 1
END
END
IF ( UPDATE(LoginCombo))
BEGIN
IF (#RCDIDIN != 0)
BEGIN
UPDATE TimeLog
SET LogInRND = (select CAST(dbo.roundtime(LogInRND,0.25) AS TIME))
WHERE ID = #ID
UPDATE TimeLog
SET LogInComboRND = CAST(CAST(LogInDate AS DATE) AS SMALLDATETIME) + CAST(LogInRND AS TIME)
WHERE ID = #ID
UPDATE TimeLog
SET TimeWorked = dbo.gettime(DATEDIFF(ss,LogInComboRND,LogoutComboRND))
WHERE ID = #ID AND LogInEntered = 1 AND LogOutEntered = 1
UPDATE TimeLog
SET TimeWorked = (select CAST(dbo.roundtime(TimeWorked,0.25) AS TIME)), Rounded = 1
WHERE ID = #ID AND LogInEntered = 1 AND LogOutEntered = 1
END
END
GO
I am at a total blank to come up with why this is not working.
Anyone have any ideas?
Like I stated, pass it any other entry for the #emp and it will run fine. I can even pass it ‘5118’ and it will work, but not 5118.