'SQL Server : unable to save decimal digits

I am facing a peculiar problem. I have a few tables in SQL Server where I have properly declared a few columns as decimal(18, 2).

Unfortunately, whenever, I save any value in these columns, either the values to the right of the value are not stored or are rounded off to the higher multiple and the value to the right of the decimal remains at 00.

I save these values through stored procedures where I have declared the decimal data type for such columns for the relevant parameters.

What could be the issue?

EDIT: posting the table script

CREATE TABLE [dbo].[ItemMaster]
(
    [ColIndex] [int] IDENTITY(1,1) NOT NULL,
    [ItemName] [nvarchar](150) NULL,
    [ItemBrand] [int] NULL,
    [ItemHSN] [nvarchar](50) NULL,
    [ItemSalePrice] [decimal](18, 2) NULL,
    [ItemCode] [nvarchar](50) NULL,
    [ItemBarcode] [nvarchar](max) NULL,
    [ItemQRCode] [nvarchar](max) NULL,
    [ItemUnit] [int] NULL,
    [ItemOpeningStock] [int] NULL,
    [ItemCreationDate] [datetime] NULL,
    [ItemEditDate] [datetime] NULL,
    [ItemCreationUserID] [int] NULL,
    [ItemEditUserID] [int] NULL,
    [ItemActiveStatus] [int] NULL,
    [PurCGST] [decimal](10, 3) NULL,
    [PurSGST] [decimal](10, 3) NULL,
    [PurIGST] [decimal](10, 3) NULL,
    [SaleCGST] [decimal](10, 3) NULL,
    [SaleSGST] [decimal](10, 3) NULL,
    [SaleIGST] [decimal](10, 3) NULL,
    [ItemCat] [int] NULL,
    [RandomString] [nvarchar](50) NULL,

    CONSTRAINT [PK_ItemMaster] 
        PRIMARY KEY CLUSTERED ([ColIndex] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

The stored procedure:

CREATE OR ALTER PROCEDURE [dbo].[EditItem]
    @ItemColID BIGINT,
    @ItemName NVARCHAR(150),
    @ItemBrandNum INT,
    @ItemHSN NVARCHAR (150),
    @SalePrice DECIMAL,
    @ItemCode NVARCHAR(150),
    @ItemBarcode NVARCHAR(500),
    @ItemQRCode NVARCHAR(500),
    @ItemUnitNum INT,
    @ItemOpeningStock INT,
    -- @ItemCreateDate DATETIME,
    @ItemEditDate DATETIME,
    -- @ItemCreateUserID INT,
    @ItemEditUserID INT,
    @ItemActiveStatus INT,

    -- @PurCGSTRate DECIMAL,
    -- @PurSGSTRate DECIMAL,
    -- @PurIGSTRate DECIMAL,

    @SaleCGSTRate DECIMAL,
    @SaleSGSTRate DECIMAL,
    @SaleIGSTRate DECIMAL,
    @ItemCat INT
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE ItemMaster 
    SET ItemName = @ItemName ,
        ItemBrand = @ItemBrandNum, 
        ItemHSN = @ItemHSN,
        ItemSalePrice = @SalePrice,
        ItemCode = @ItemCode,
 ItemBarcode =      @ItemBarcode ,
ItemQRCode =    @ItemQRCode ,
ItemUnit =  @ItemUnitNum ,
  ItemOpeningStock=   @ItemOpeningStock ,
  --  @ItemCreateDate 
   ItemEditDate = @ItemEditDate ,
   -- @ItemCreateUserID 
ItemEditUserID = @ItemEditUserID ,
   ItemActiveStatus =  @ItemActiveStatus,

--  purcgst=@PurCGSTRate ,
--pursgst=@PurSGSTRate ,
--purigst=@PurIGSTRate,

salecgst= @SaleCGSTRate ,
SaleSGST = @SaleSGSTRate ,
saleigst= @SaleIGSTRate, 
itemcat = @ItemCat

   WHERE ItemMaster .ColIndex = @ItemColID
END
GO     


Solution 1:[1]

Parameter of type DECIMAL is equal to DECIMAL(18,0):

@SaleCGSTRate DECIMAL,
@SaleSGSTRate DECIMAL,
@SaleIGSTRate DECIMAL,

This is WITHOUT any digits after the decimal point!!

You need to be explicit about your datatype - for the parameters as well !

So you need to use DECIMAL(18,2) as the datatype for your stored procedure parameters - THEN you will be able to store fractional decimal values just fine!

See the official MS documentation on DECIMAL in SQL Server for more details.

This is from the official docs (my highlights):

decimal[ (p[ ,s] )]

p (precision)
The maximum total number of decimal digits to be stored. This number includes both the left and the right sides of the decimal point. The precision must be a value from 1 through the maximum precision of 38. The default precision is 18.

s (scale)
The number of decimal digits that are stored to the right of the decimal point. This number is subtracted from p to determine the maximum number of digits to the left of the decimal point. Scale must be a value from 0 through p, and can only be specified if precision is specified. The default scale is 0 and so 0 <= s <= p. Maximum storage sizes vary, based on the precision.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 marc_s