2

I have a series of stored procedures that first does an ETL process, then load the results of some formulas into a new table. At the end of the process, I have a small section of code that compares the output table to the input table to make sure all the records are there. I've put this all into a SQL Agent job and scheduled it to run every morning.

If I manually run the SQL Server Agent job, everything works perfectly fine. However when I let the Agent execute the job as scheduled, the code that compares the table notifies me that a number of records aren't in the final table. Of the roughly 1 million records in the table, each day it say only about 2000 aren't in the final table. This number changes each day.

I doubt it's a permissions problem, since I have other Agent jobs that do not have this problem.

Any thoughts as to what might cause this behaviour?

Edit

This is the code that does the insertion of data. My data has three types, and two different versions. I could have built it all into one stored procedure, but due to the way the processes can change, it's split into an individual stored procedure for each type/version combination. At the end of each stored procedure, a temp table is built with the results of the stored procedure. This temp table is called ##ResultsT1Ver1 for example, and UpdateResultTable is called, with the Type and Version of the parent stored procedure passed in as parameters.

Note that when I run my stored procedure, I build an intermediary table before building the temp table. Looking up one record that was flagged as not making it to the result table shows that it IS in the intermediary table. So the issue I think lies somewhere in either the insert, or the storage of the temp table.

The individual stored procedures are over 300 lines each, it'll take longer to clean them up for posting here.

ALTER PROCEDURE [dbo].[UpdateResultTable] @Version varchar(2), @Type varchar(15)
AS
BEGIN

SET NOCOUNT ON;
DECLARE @SQL  NVARCHAR(4000);


IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND  TABLE_NAME = 'Results'))
BEGIN

    IF (EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID('dbo.Results') AND name = 'IDX_Results_Epinum'))
    BEGIN DROP INDEX [IDX_Results_Epinum] ON dbo.Results  END

END
ELSE
    CREATE TABLE dbo.Results  
    (
        ResultsId [int] IDENTITY(1,1) NOT NULL,
        ValType VARCHAR(10) NULL,
        Epinum  VARCHAR(50) NULL,
        N15 DECIMAL(25,13) NULL,
        G15 DECIMAL(25,13) NULL,
        N16 DECIMAL(25,13) NULL,
        G16 DECIMAL(25,13) NULL,
        EstablishmentId VARCHAR(9) NULL,
        ServiceDate datetime NULL,
        ExcludedRecord VARCHAR(11) NULL,
         CONSTRAINT [PK_Results] PRIMARY KEY CLUSTERED (ResultsId)
    );


SET @SQL = N'
IF EXISTS (SELECT n.Epinum FROM ##Results' + @Version + @Type + N' n INNER Join dbo.Results r on r.Epinum = n.Epinum WHERE n.N' + @VERSION + ' <> r.N' + @VERSION + ' OR n.G' + @VERSION + ' <> r.G' + @VERSION + ' 
                OR n.ValType <> r.ValType OR n.ExcludedRecord <> r.ExcludedRecord) 
    BEGIN 
        UPDATE D 
        SET D.N' + @VERSION + ' = S.N' + @VERSION + ',  
            D.G' + @VERSION + ' = S.G' + @VERSION + ', 
            D.ValType = S.ValType ,
            D.ExcludedRecord = S.ExcludedRecord
        FROM dbo.Results D 
        INNER JOIN ##Results' + @Version + @Type + N' S ON D.Epinum = S.Epinum 
    END 
    ELSE 
    BEGIN 
        INSERT INTO dbo.Results   
        SELECT 
            ValType, 
            Epinum,' 
SET @SQL = @SQL + CASE WHEN @Version = '15' THEN N'N15, G15, 0.0, 0.0, ' ELSE N'0.0,0.0,N16, G16, ' END
SET @SQL = @SQL + N'
            EstablishmentId ,
            ServiceDate,
            ExcludedRecord
        FROM ##Results' + @Version + @Type + N' S 
        WHERE NOT EXISTS (SELECT Epinum FROM dbo.Results D WHERE S.Epinum = D.Epinum) 
END'
--select @SQL
print @sql

declare @val int;
declare @printsql NVARCHAR(4000);
set @printsql = 'declare @val int; 
                select  @val = count(*) from ##Results' +@version + @type +'; print @val;'
exec sp_executesql @printsql; 


exec sp_executesql @SQL;


CREATE NONCLUSTERED INDEX [IDX_Results_Epinum] ON dbo.Results (Epinum ASC) INCLUDE (N15, G15, N16,G16) 
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = ON, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]

END
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Matt
  • 4,140
  • 9
  • 40
  • 64
  • You have other agent jobs that have insert permissions on tables or that at least insert records into similar tables within the same schema? – S3S Nov 08 '16 at 22:47
  • Are you loading from multiple locations? Is there a chance that one of them is failing? One option you could try is setup your own account as credential/proxy and configure the job step to run using your account. See if it works. – Nayak Nov 08 '16 at 22:49
  • @scsimon I have another job that copies data from the same sourcedb, but drops and rebuilds the final table. The job with issues has 6 sp's that all insert into the same table. – Matt Nov 08 '16 at 22:59
  • @Nayak no, I have a stand alone sp that handles the data extraction from the sourcedb. I think the issue is somehow in sp's that insert into the final table. Can't figure out where though, since the issue only arises when the job is run by the scheduler – Matt Nov 08 '16 at 23:01
  • could be a premissions issue? usually when you run a job in ssms you're using your credentials. – McNets Nov 08 '16 at 23:15
  • @mcNets I have another job that executes just fine though, and this job works for 99.5% of all records. There's about 1 million records it's taking from one table and inserting into a second table (with a bit in between) and it works for the majority of them. I don't think it's a permission problem. – Matt Nov 08 '16 at 23:24
  • @Matt could you show us your procedure or a simplified version? just in case somebody can see the problem. – McNets Nov 08 '16 at 23:32
  • You could log `@@RowCount` and a description after every significant operation. That would give you something to analyze after a run. – HABO Nov 08 '16 at 23:33
  • I'll update the post in a second. – Matt Nov 08 '16 at 23:48
  • If you identify the missing records, shouldn't that give you a clue to what the issue is? There really isn't any useful answer anyone can give you here because this is very system specific. Some things that come to mind: 1. Compare the entire agent logs between job executions (i.e. uses, timing of steps etc.). 2. Is it a timing issue? Is that the true difference: that the scheduled on is in the middle of the night and the manual one isn't? – Nick.Mc Nov 09 '16 at 00:14
  • have you opened a trace just to verify the @SQL sentence executed by the job? – McNets Nov 09 '16 at 00:14
  • Have you tried not using a temp table for debug purposes? Maybe your ##Result temp table comes out of scope somewhere. Or you can use the new data table to help you pinpoint the issue. – dpimente Nov 09 '16 at 00:18
  • I'm playing around with the temp table now. I had the job scheduled at 7am which I thought was out the way of everything else. I've moved it to 9am now. I'll check those things out Nick and see if I have any luck – Matt Nov 09 '16 at 00:20
  • How do I open a trace @mcNets – Matt Nov 09 '16 at 00:21
  • @Matt Sql Profiler – McNets Nov 09 '16 at 00:22
  • You could try using a non-global temp table (`#Resulst` instead of `##Results`). – cco Nov 09 '16 at 00:23
  • @Matt `print @sql` shows you the sentence when schedules the job? – McNets Nov 09 '16 at 00:26
  • 1:30 AM here, see you tomorrow – McNets Nov 09 '16 at 00:30
  • Cheers for the help mcNets. The print was a hangover from when testing. – Matt Nov 09 '16 at 00:41
  • @cco I changed it to the global in an attempt to fix this exact problem. I thought at the time that perhaps the table was being deleted by another of the stored procedures. – Matt Nov 09 '16 at 00:42

1 Answers1

0

So I managed to solve the problem by removing the universal upsert procedure that used temp tables. Instead, I wrote my data sets to proper tables, then after all procedures ran, combined the results of these individual tables into one, then delete the tables. Seems to be working fine now. Odd

Matt
  • 4,140
  • 9
  • 40
  • 64