DATEFROMPARTS and CONVERT failing but only when inside an SP

  • Phil Parkin wrote:

    Can we assume that you have a QA/Test environment which is intended to be a close-to exact copy of Prod? If so, does the problem happen there too?

    If not, I'd start digging into instance-level settings and comparing them. I've seen scripts before which can grab lots of this stuff for you, though I don't have one to hand.

    Was just about to suggest something like that myself Phil.

    Glenn has his DMV Diagnostic Scripts and Excel sheets which will pull in that kind of information for you Thom.  There's also things like AirForge which can company server side settings side by side.

    Unable to repro the error using the sample function and proc on any server I have unless I add in a blank string which is to be expected.

  • Phil Parkin wrote:

    Can we assume that you have a QA/Test environment which is intended to be a close-to exact copy of Prod? If so, does the problem happen there too?

    If not, I'd start digging into instance-level settings and comparing them. I've seen scripts before which can grab lots of this stuff for you, though I don't have one to hand.

    I wish I did... I have a UAT environment, however, it is not close to exact in data terms. No where near it.

    I've been trying everything to repro this so far today, I literally can't no matter what I try.

    I know the error happens in this function because it's the only thing that uses DATEFROMPARTS (note that this is the "fixed" version, where DATEFROMPARTS is commented out, it fails when the comments on TRY_CONVERT and DATEFROMPARTS are reversed):

    ALTER FUNCTION [dbo].[RACVehicleSearch] (@Branch int,
    @PolicyRef varchar(10))
    RETURNS table
    AS RETURN

    SELECT RTVA.B@,
    RTVA.PolRef@,
    RTVA.Prn,
    RTVA.Reg AS RegNo,
    RTVA.Make,
    RTVA.Model,
    CONVERT(date, RTVA.Bdowndateon) AS BreakdownOn,
    CONVERT(date, RTVA.Bdowndateoff) AS BreakdownOff,
    0 AS Horses,
    RTVA.Fuel,
    RTVA.cc,
    --DATEFROMPARTS(RTVA.Yrreg,1,1) AS Certdate
    TRY_CONVERT(date,CONCAT(RTVA.Yrreg,'01','01')) AS CertDate
    FROM OpenGI.dbo.ic_BD_RTVA RTVA
    WHERE RTVA.B@ = @Branch
    AND RTVA.PolRef@ = @PolicyRef
    UNION ALL
    SELECT WHVA.B@,
    WHVA.PolRef@,
    WHVA.Prn,
    WHVA.Reg,
    WHVA.Make,
    WHVA.Model,
    CONVERT(date, WHVA.Bdowndateon) AS BreakdownOn,
    CONVERT(date, WHVA.Bdowndateoff) AS BreakdownOff,
    0 AS Horses,
    WHVA.Fuel,
    WHVA.cc,
    --DATEFROMPARTS(WHVA.Yrreg,1,1) AS Certdate
    TRY_CONVERT(date,CONCAT(WHVA.Yrreg,'01','01')) AS CertDate
    FROM OpenGI.dbo.ic_BD_WHVA WHVA
    WHERE WHVA.B@ = @Branch
    AND WHVA.PolRef@ = @PolicyRef
    UNION ALL
    SELECT HBV.B@,
    HBV.PolRef@,
    HBV.Prn,
    HBV.Regno,
    HBV.Make,
    HBV.Model,
    CONVERT(date,HBV.Bdowndateon) AS BreakdownOn,
    CONVERT(date,HBV.Bdowndateoff) AS BreakdownOff,
    HBV.Horses,
    NULL AS Fuel,
    NULL AS Cc,
    --DATEFROMPARTS(HBV.Yearreg,1,1) AS Certdate
    TRY_CONVERT(date,CONCAT(HBV.Yearreg,'01','01')) AS CertDate
    FROM OpenGI.dbo.ic_BD_HBV HBV
    WHERE HBV.B@ = @Branch
    AND HBV.PolRef@ = @PolicyRef
    UNION ALL
    SELECT CGV1.B@,
    CGV1.PolRef@,
    CGV1.Prn,
    CGV1.Reg,
    CGV1.Make,
    CGV1.Model,
    CONVERT(date, CGV1.Bdowndateon) AS BreakdownOn,
    CONVERT(date, CGV1.Bdowndateoff) AS BreakdownOff,
    0 AS Horses,
    NULL AS Fuel,
    CGV1.Cc,
    --DATEFROMPARTS(CGV1.Yearreg,1,1) AS Certdate
    TRY_CONVERT(date,CONCAT(CGV1.Yearreg,'01','01')) AS CertDate
    FROM OpenGI.dbo.ic_BD_CGV1 CGV1
    WHERE CGV1.B@ = @Branch
    AND CGV1.PolRef@ = @PolicyRef
    UNION ALL
    SELECT HTBD.B@,
    HTBD.PolRef@,
    HTBD.Prn,
    HTBD.Reg,
    HTBD.Make,
    HTBD.Model,
    CONVERT(date, HTBD.Date_on) AS BreakdownOn,
    CONVERT(date, HTBD.Date_off) AS BreakdownOff,
    0 AS Horses,
    NULL AS Fuel,
    NULL AS Cc,
    NULL AS Certdate
    FROM OpenGI.dbo.ic_BD_HTBD HTBD
    WHERE HTBD.B@ = @Branch
    AND HTBD.PolRef@ = @PolicyRef
    UNION ALL
    SELECT HPT.B@,
    HPT.PolRef@,
    HPT.Prn,
    HPT.Reg,
    HPT.Make,
    HPT.Model,
    CONVERT(date, HPT.Bdowndateon) AS BreakdownOn,
    CONVERT(date, HPT.Bdowndateoff) AS BreakdownOff,
    0 AS Horses,
    NULL AS Fuel,
    NULL AS Cc,
    NULL AS Certdate
    FROM OpenGI.dbo.ic_BD_HPT HPT
    WHERE HPT.B@ = @Branch
    AND HPT.PolRef@ = @PolicyRef;

    I know that if I run the SQL in the SP that that function is called in, it runs fine too:

    --ALTER PROC [dbo].[RACOnCoverBDX_sp] @ReportDate date AS
    BEGIN

    DECLARE @ReportDate date;
    SET @ReportDate = '20200205';

    WITH CTE AS(
    SELECT ROW_NUMBER() OVER (PARTITION BY BTX.PolRef@
    ORDER BY BTX.Dt_raised,
    BTX.Suffix@,
    Veh.BreakdownOn) AS RN,
    BPY.PolRef@,
    CASE
    WHEN BTX.Trantype = 'Renewal' AND BTX.Dt_raised < '20210201' THEN 'A'
    WHEN BTX.Trantype = 'Renewal' THEN 'R'
    WHEN BTX.Dt_raised = Veh.BreakdownOn THEN 'A'
    WHEN BTX.Dt_raised = Veh.BreakdownOff THEN 'D'
    WHEN BTX.Trantype = 'Cancellation' THEN 'D'
    WHEN BTX.Dt_raised = BPY.Term_date THEN 'D'
    WHEN BTX.Dt_raised >= Veh.BreakdownOn AND (BTX.Dt_raised < Veh.BreakdownOff OR Veh.BreakdownOff IS NULL) THEN 'U'
    WHEN BTX.Trantype = 'Endorsement' THEN 'U'
    --ELSE 'A'
    END AS TranFlag,
    Veh.RegNo,
    'GB' AS RegCountry,
    CASE BPY.Ptype WHEN 'CG' THEN 'THOM01'
    WHEN 'HT' THEN 'THOM02'
    WHEN 'HP' THEN 'THOM02'
    WHEN 'HB' THEN 'THOM03'
    WHEN 'WH' THEN 'THOM04'
    WHEN 'RT' THEN 'THOM05'
    END AS AgreementNo,
    NULL AS PartnerID,
    'TOM A' AS PartnerName,
    CONVERT(date,CASE
    WHEN BTX.Trantype = 'Renewal' THEN BTX.Dt_raised
    WHEN BTX.Dt_raised = Veh.BreakdownOn THEN BTX.Dt_raised
    ELSE BTXp.Dt_raised
    END) AS CoverStart,
    CONVERT(date,COALESCE(Veh.BreakdownOff, BPY.Term_date, DATEADD(DAY, -1, DATEADD(YEAR, 1, BTXp.Dt_raised)))) AS CoverEnd,
    CONCAT(BPY.PolRef@,RIGHT(CONCAT('000',Veh.PRN),3)) AS UniqueID,
    BPY.PolRef@ AS LinkedId,
    NULL AS RetailPrice,
    NULL AS Comission,
    NULL AS NetPrice,
    NULL AS IPT,
    Veh.Make,
    Veh.Model,
    NULL AS Type,
    CONVERT(date,Veh.Certdate) AS RegDate,
    NULL AS VIN,
    NULL AS Mileage,
    NULL AS Transmission,
    Veh.Fuel,
    Veh.Cc AS Engine,
    NULL AS Height,
    NULL AS [Length],
    NULL AS Width,
    NULL AS [Weight],
    NULL AS TyreSize,
    NULL AS Colour,
    BDPH.Title_ext,
    BDPH.Forename,
    BDPH.Surname,
    BCM.Char5 AS CompanyName,
    REPLACE(BCM.Addr1,',','') AS Addr1,
    REPLACE(BCM.Addr2,',','') AS Addr2,
    REPLACE(BCM.Addr3,',','') AS Addr3,
    REPLACE(BCM.Addr4,',','') AS Addr4,
    NULL AS Addr5,
    BCM.Pcode,
    'GB' AS Country,
    NULL AS AddressType,
    BCM.Tel,
    BCM.Tel3 AS Tel2,
    NULL AS ClientRef1,
    NULL AS ClientRef2,
    NULL AS ClientRef3,
    NULL AS ClientRef4,
    NULL AS ClientRef5
    FROM OpenGI.dbo.ic_yyclient BCM
    JOIN OpenGI.dbo.ic_brpolicy BPY ON BCM.B@ = BPY.B@
    AND BCM.Ref@ = BPY.Ref@
    JOIN OpenGI.dbo.ic_brcledger BTX ON BPY.B@ = BTX.B@
    AND BTX.PolRef@ = BPY.PolRef@
    LEFT JOIN OpenGI.dbo.ic_brcledger BTXc ON BTX.B@ = BTXc.B@
    AND BTX.PolRef@ = BTXc.PolRef@
    AND BTX.Suffix@ = BTXc.C_mast
    AND BTXc.C_ins IN ('RAC Horsebox Breakdown','RAC Rural Taxi Breakdown','RAC Clergy Breakdown','RAC Trailer Breakdown','RAC Wedding Hire Breakdown')
    CROSS APPLY dbo.RACVehicleSearch (BPY.B@, BPY.PolRef@) Veh
    OUTER APPLY dbo.RACTransactionFrameSearch (BPY.B@, BPY.PolRef@, BTX.Ref) Trn
    OUTER APPLY dbo.RACTransactionFrameSearch_History (BPY.B@, BPY.PolRef@, BTX.Ref) Trnh
    CROSS APPLY OpenGIDW.dbo.brcledgerYOA_fn(BTX.B@, BTX.PolRef@, BTX.Dt_raised) BTXp
    LEFT JOIN OpenGI.dbo.ic_BD_BDPH BDPH ON BPY.B@ = BDPH.B@
    AND BPY.PolRef@ = BDPH.PolRef@
    CROSS APPLY (SELECT COUNT(*) AS Vehicles
    FROM dbo.RACVehicleSearch (BPY.B@, BPY.PolRef@) VS
    WHERE Veh.BreakdownOn = BTX.Dt_raised
    OR Veh.BreakdownOff = BTX.Dt_raised) C
    WHERE BPY.B@ IN (0,8)
    AND BPY.Ptype IN ('RT','WH','HB','CG','HP','HT')
    --AND BPY.PolRef@ = 'TETX40WH01'
    AND BTX.Dt_raised >= Veh.BreakdownOn
    AND (BTX.Dt_raised <= Veh.BreakdownOff OR Veh.BreakdownOff IS NULL)
    AND Veh.RegNo IS NOT NULL
    AND (BTXc.Key@ IS NOT NULL
    OR (BTXc.Key@ IS NULL
    AND (BTX.Orig_debt = 0 OR @ReportDate IN (Veh.BreakdownOn,Veh.BreakdownOff))
    AND (Trn.BDowninsurer IN ('RAC Horsebox Breakdown','RAC Rural Taxi Breakdown','RAC Clergy Breakdown','RAC Trailer Breakdown','RAC Wedding Hire Breakdown')
    OR (Trn.Tranref IS NULL AND Trnh.BDowninsurer IN ('RAC Horsebox Breakdown','RAC Rural Taxi Breakdown','RAC Clergy Breakdown','RAC Trailer Breakdown','RAC Wedding Hire Breakdown')))))
    AND ((BTX.Dt_raised = @ReportDate AND BTX.Datecreated <= @ReportDate)
    OR (BTX.Dt_raised < @ReportDate AND BTX.Datecreated = @ReportDate))
    AND ((BTX.Trantype IN ('New Business', 'Transfrd NB', 'Renewal')
    AND Veh.BreakdownOn <= BTX.Dt_raised
    AND (Veh.BreakdownOff >= BTX.Dt_raised
    OR Veh.BreakdownOff IS NULL))
    OR (BTX.Trantype IN ('Endorsement')
    AND (Veh.BreakdownOn = BTX.Dt_raised
    OR Veh.BreakdownOff = BTX.Dt_raised))
    OR (BTX.Trantype IN ('Endorsement')
    AND C.Vehicles = 0
    AND BTX.Orig_debt = 0
    AND (Veh.BreakdownOn <= BTX.Dt_raised
    OR Veh.BreakdownOff >= BTX.Dt_raised))
    OR (BTX.Trantype IN ('Cancellation')
    AND Veh.BreakdownOn < BTX.Dt_raised
    AND (Veh.BreakdownOff >= BTX.Dt_raised
    OR Veh.BreakdownOff IS NULL)))
    )
    SELECT CTE.TranFlag,
    CTE.RegNo,
    CTE.RegCountry,
    CTE.AgreementNo,
    CTE.PartnerID,
    CTE.PartnerName,
    CTE.CoverStart,
    CTE.CoverEnd,
    CTE.UniqueID,
    CTE.LinkedId,
    CTE.RetailPrice,
    CTE.Comission,
    CTE.NetPrice,
    CTE.IPT,
    CTE.Make,
    CTE.Model,
    CTE.[Type],
    CTE.RegDate,
    CTE.VIN,
    CTE.Mileage,
    CTE.Transmission,
    CTE.Fuel,
    CTE.Engine,
    CTE.Height,
    CTE.[Length],
    CTE.Width,
    CTE.[Weight],
    CTE.TyreSize,
    CTE.Colour,
    CTE.Title_ext,
    CTE.Forename,
    CTE.Surname,
    CTE.CompanyName,
    CTE.Addr1,
    CTE.Addr2,
    CTE.Addr3,
    CTE.Addr4,
    CTE.Addr5,
    CTE.Pcode,
    CTE.Country,
    CTE.AddressType,
    CTE.Tel,
    CTE.Tel2,
    CTE.ClientRef1,
    CTE.ClientRef2,
    CTE.ClientRef3,
    CTE.ClientRef4,
    CTE.ClientRef5
    FROM CTE
    ORDER BY PolRef@,
    RN;
    END;

    But, as soon as I execute the above SP, EXEC dbo.RACOnCoverBDX_sp '20200205'; (obviously with the mentioned commented out functions reversed) I get the error below:

    Cannot construct data type date, some of the arguments have values which are not valid.

    Regardless of which DATEFROMPARTS I comment out, as long as one is there, the process fails when you EXEC the SP. Also, the dataset returned has no rows where RegDate (which comes from Certdate in the function) where the value is NULL , so there's no conversion failures when the TRY_CONVERT solution is used.

    I'm really at a loss, and I don't really know what else I can do. The EXEC statement above, and the above SQL are effectively identical, so it makes no sense that one fails and the other does not. it also makes no sense that this worked yesterday, and today does not... 🙁

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • I haven't reviewed them yet, but did wonder if, perhaps, the order in which the data engine is running the joins is different when I run the SQL and when it runs the SP, which is resulting in an odd row being found.

    My familiarity with Execution plans is "ok" at best, so those with keener eyes may see something.

    Actual Execution Plan, from when SQL inside SP is run: https://www.brentozar.com/pastetheplan/?id=HJhAyaYGL

    Estimated Execution Plan, from when SP is run (can't get actual due to error): https://www.brentozar.com/pastetheplan/?id=BkIEZatfL

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • Ok, that looks like I might be onto something. The SP has loads of scans, however, the SQL being run is all seeks. I jsut got the Actual Execution Plan for the fixed version (https://www.brentozar.com/pastetheplan/?id=rJedG6FfI) and that too has scans, not seeks.

    Any ideas why the SP uses scans, but the SQL seeks? That's something I really don't understand well.

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • upgrade quickly, then you can use querystore and plan guides

    MVDBA

  • MVDBA (Mike Vessey) wrote:

    upgrade quickly, then you can use querystore and plan guides

    Yeah, just wing it. I'm sure everything will be OK 🙂

    The absence of evidence is not evidence of absence.
    Martin Rees

    You can lead a horse to water, but a pencil must be lead.
    Stan Laurel

  • MVDBA (Mike Vessey) wrote:

    upgrade quickly, then you can use querystore and plan guides

    Upgrade (to 2019) is on the cards, but probably not till Q3 this year. Me working out the budget has been put on hold while other projects that people have given us far little notice for have taken priority.

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • Phil Parkin wrote:

    MVDBA (Mike Vessey) wrote:

    upgrade quickly, then you can use querystore and plan guides

    Yeah, just wing it. I'm sure everything will be OK 🙂

    that is what my IT director keeps telling me 🙁

    MVDBA

  • MVDBA (Mike Vessey) wrote:

    Phil Parkin wrote:

    MVDBA (Mike Vessey) wrote:

    upgrade quickly, then you can use querystore and plan guides

    Yeah, just wing it. I'm sure everything will be OK 🙂

    that is what my IT director keeps telling me 🙁

    Get it in writing, notarised, sealed and fingerprint in blood. Then you should be covered.

    The absence of evidence is not evidence of absence.
    Martin Rees

    You can lead a horse to water, but a pencil must be lead.
    Stan Laurel

  • Thom A wrote:

    I haven't reviewed them yet, but did wonder if, perhaps, the order in which the data engine is running the joins is different when I run the SQL and when it runs the SP, which is resulting in an odd row being found.

    My familiarity with Execution plans is "ok" at best, so those with keener eyes may see something.

    Actual Execution Plan, from when SQL inside SP is run: https://www.brentozar.com/pastetheplan/?id=HJhAyaYGL

    Estimated Execution Plan, from when SP is run (can't get actual due to error): https://www.brentozar.com/pastetheplan/?id=BkIEZatfL%5B/quote%5D

    I was going to mention this as an option - then look for any negative years.  Is it possible that should be excluded - but the optimizer is pushing the datefromparts to an early segment in the plan before that data is filtered out?

    Jeffrey Williams
    “We are all faced with a series of great opportunities brilliantly disguised as impossible situations.”

    ― Charles R. Swindoll

    How to post questions to get better answers faster
    Managing Transaction Logs

  • OK, yes, it was the order of the processing being different when EXEC was used and the SQL inside the SQL was being run. When the SQL was run, any rows from "bad" rows was being filtered out by joins or the WHERE before the function (RACVehicleSearch) was called. It seems that when EXEC was being used, those rows weren't being filtered, and there were 2 rows in the database where they had a value of 0 in yrreg. These are old rows, but the query was catching them and therefore failing.

    Fixed by wrapping Yrreg in a NULLIF. Now I just need to work out why it scans. Tbut that's a different qusetion.

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • I had a problem a few days ago where using TRY_CAST gave no nulls in the result, but using just CAST caused an error. It turned out that either my WHERE clause or one of the JOINs was filtering out the guilty rows, but only after the relevant calculation had been attempted. Could yours be a similar situation? It would explain why it fails even for previous days' successful runs.

Viewing 12 posts - 16 through 26 (of 26 total)

You must be logged in to reply to this topic. Login to reply