SQL Server Function returns a null when its not supposed to?

5rgfhyps  于 2023-10-15  发布在  其他
关注(0)|答案(1)|浏览(96)

I currently have a warranty function (which is being used for an INSERT query) that determines whether a warranty is still valid. It compares warranty_remaining ( DATEDIFF between the date of purchase and today's date) with warranty_duration (3 years aka the warranty duration), if the warranty_remaining is less than or equal to the warranty duration then it should return the warranty_remaining as expected. Else, it will return a null indicating the warranty has expired.

However, there seems to be an error, as I get a NULL returned in the warranty row. After I run my INSERT query, every value is expected except for warranty. I suspect the issue lies in the way/format the warranty_remaining is being returned after the IF block. I say this because I've tried testing the if statement/calculations above the return statement ( RETURN @warranty_remaining; ) to check if its working as expected. (i.e., I changed the return statement to return 1000 instead of @ warranty_remaining . In the end, it did show 1000 in the warranty row. Which tells me it shouldn't be a logic / calculation error in the code).

Another possibility would be how the function is being called in the INSERT query but it seems pretty slim.

Notes:

  • Whenever I wanted to test changes to the function, I deleted always deleted the existing instance in the Programmability/Functions/Scalar-valued Functions beforehand
  • The datatype of warranty is int, hence it shouldn't be a datatype mismatch since the function has RETURNS INT
  • PK is product_id and I set Is Identity to Yes
  • Assume warranty is 3 years
  • If the function truly can't work then I guess it has to be carried out in the individual VALUES

Code for function:

USE YourDatabaseName; -- Replace 'YourDatabaseName' with the actual name of your database

-- Start a new batch
GO

CREATE FUNCTION dbo.CalculateWarranty 
    (@purchase_date DATE)
RETURNS INT
AS
BEGIN
    DECLARE @warranty_duration INT;
    DECLARE @warranty_remaining INT;

    -- Set the warranty duration to 3 years (in days)
    SET @warranty_duration = 1095;

    -- Calculate the remaining warranty duration in days
    SET @warranty_remaining = DATEDIFF(DAY, @purchase_date, GETDATE());

    -- If the remaining warranty is within 3 years, return the remaining duration; otherwise, return NULL
    IF @warranty_remaining <= @warranty_duration
        RETURN @warranty_remaining;

    -- Default return statement (return NULL if warranty is not within 3 years)
    RETURN NULL;        
END;

Code for INSERT query:

INSERT INTO product(supplier_id, category_id, serial_no,
    product_brand, product_name, purchase_price,
    purchase_date, warranty, description) 
VALUES (1, 1, 'PF-2HKJ16',
        'Lenovo', 'ThinkPad X1 Carbon 8 / i7-10510U', NULL, -- Enter purchase_price later,
        '2021-11-01',
        dbo.CalculateWarranty(CONVERT(DATE, GETDATE())), -- Call function called CaclulateWarranty
        'The ThinkPad X1 Carbon 8th generation with an Intel Core i7-10510U processor is a premium ultrabook laptop developed by Lenovo. It is designed to deliver exceptional performance, portability, and durability for professionals and business users.');
piztneat

piztneat1#

you can test the function only by calling it and adding some Dates

The flaw is that you have to handle NULL and you need to subtract the remainding time from the warranty duration

CREATE FUNCTION dbo.CalculateWarranty (
    @purchase_date DATE
)
RETURNS INT
AS
BEGIN
    DECLARE @warranty_duration INT;
    DECLARE @warranty_remaining INT;

    -- Set the warranty duration to 3 years (in days)
    SET @warranty_duration = 1095;
    IF @purchase_date Is NULL 
       return -1
      
    -- Calculate the remaining warranty duration in days
    SET @warranty_remaining = DATEDIFF(DAY, @purchase_date, GETDATE());

    -- If the remaining warranty is within 3 years, return the remaining duration; otherwise, return NULL
    IF @warranty_remaining <= @warranty_duration
        RETURN @warranty_duration - @warranty_remaining;

    -- Default return statement (return NULL if warranty is not within 3 years)
    RETURN NULL;        
END;
select dbo.CalculateWarranty(NULL);
(No column name)
-1
select dbo.CalculateWarranty(GETdate());
(No column name)
1095
select dbo.CalculateWarranty(DATEADD(day,-5,GETdate()));
(No column name)
1090

fiddle

To adress your problem, there are only 2 posibilies in your function to return NULL

You pass NULL as Value or you have a pirchase_day the is earlier than the 1095 days.

CREATE FUNCTION dbo.CalculateWarranty (
    @purchase_date DATE
)
RETURNS INT
AS
BEGIN
    DECLARE @warranty_duration INT;
    DECLARE @warranty_remaining INT;

    -- Set the warranty duration to 3 years (in days)
    SET @warranty_duration = 1095;

    -- Calculate the remaining warranty duration in days
    SET @warranty_remaining = DATEDIFF(DAY, @purchase_date, GETDATE());

    -- If the remaining warranty is within 3 years, return the remaining duration; otherwise, return NULL
    IF @warranty_remaining <= @warranty_duration
        RETURN @warranty_remaining;

    -- Default return statement (return NULL if warranty is not within 3 years)
    RETURN NULL;        
END;
select dbo.CalculateWarranty(DATEADD(DAY,-1098, getdate()));
(No column name)
null
SELECT dbo.CalculateWarranty(CONVERT(DATE, GETDATE()))
(No column name)
0
select dbo.CalculateWarranty(NULL);
(No column name)
null

fiddle

相关问题