Decimal data type in table Length = 9,Precision = 10,Scale = 2,
actual value in #Bvisits = 8.00
declare #Bvisits decimal,#ActualVisit decimal,#Ptax decimal = 1.995;
select #Bvisits = BalanceVisit from PakacgeTb where PackageID = 25306;
set #ActualVisit = #Bvisits - #Ptax;
select #ActualVisit as VIP
result is 6.
But as i use it in real stored procedure it updates result as 4.67 instead of 6 why is the issue occurring even if i use 1.9 instead of 1.995 still same issue occurs.
Try like this :
declare #Bvisits decimal(10,3),#ActualVisit decimal(10,3),#Ptax decimal(10,3) = 1.995;
select #Bvisits = BalanceVisit from PakacgeTb where PackageID = 25306;
set #ActualVisit = #Bvisits - #Ptax;
select #ActualVisit as VIP
Related
Ok first, I'm storing Lat/Long location in a column of type geography in my SQL Server table.
I try to get stores in a specific bounding box using STContains method, the only way I found to use the geography point, was by concatening the Lat/Long with STR convertion:
DECLARE #boundingBox geography;
SET #boundingBox = geography::Parse('POLYGON((...))');
...
SELECT Store.Id, Store.Name, Store.Location.Lat, Store.Location.Long,
#boundingBox.STContains(
geography::Parse('POINT(' + STR(Store.Location.Lat, 20, 12) + ' '
+ STR(Store.Location.Long, 20, 12) + ')'))
It works, but it's ugly and asking if there's a cleaner way to write this.
I setup 2 test Polygons geo and geo2. One using Parse method and the other using STPolyFromText method.
declare #geo geography
= geography::STPolyFromText('POLYGON ((73.250684 34.198599, 73.250598 34.199324, 73.250343 34.200021, 73.249927 34.200663, 73.249369 34.201226, 73.248688 34.201688, 73.247912 34.202031, 73.247069 34.202243, 73.246193 34.202314, 73.245317 34.202243, 73.244474 34.202031, 73.243698 34.201688, 73.243017 34.201226, 73.242458 34.200663, 73.242043 34.200021, 73.241788 34.199324, 73.241701 34.198599, 73.241788 34.197874, 73.242043 34.197177, 73.242458 34.196535, 73.243017 34.195972, 73.243698 34.19551, 73.244474 34.195167, 73.245317 34.194956, 73.246193 34.194884, 73.247069 34.194956, 73.247912 34.195167, 73.248688 34.19551, 73.249369 34.195972, 73.249927 34.196535, 73.250343 34.197177, 73.250598 34.197874, 73.250684 34.198599, 73.250684 34.198599))', 4326)
declare #geo2 geography
= geography::Parse('POLYGON ((73.250684 34.198599, 73.250598 34.199324, 73.250343 34.200021, 73.249927 34.200663, 73.249369 34.201226, 73.248688 34.201688, 73.247912 34.202031, 73.247069 34.202243, 73.246193 34.202314, 73.245317 34.202243, 73.244474 34.202031, 73.243698 34.201688, 73.243017 34.201226, 73.242458 34.200663, 73.242043 34.200021, 73.241788 34.199324, 73.241701 34.198599, 73.241788 34.197874, 73.242043 34.197177, 73.242458 34.196535, 73.243017 34.195972, 73.243698 34.19551, 73.244474 34.195167, 73.245317 34.194956, 73.246193 34.194884, 73.247069 34.194956, 73.247912 34.195167, 73.248688 34.19551, 73.249369 34.195972, 73.249927 34.196535, 73.250343 34.197177, 73.250598 34.197874, 73.250684 34.198599, 73.250684 34.198599))')
declare #outsidePoint geography
= geography::STPointFromText('POINT(-122.34900 47.65100)', 4326),
#insidePoint geography
= geography::STPointFromText('POINT(73.2438096 34.1989505)', 4326)
select
geo = #geo,
geoString = #geo.ToString(),
IsValid = #geo.STIsValid(),
doesContainOutsidePoint = #geo.STContains(#outsidePoint),
doesIntersectOutsidePoint = #geo.STIntersects(#outsidePoint),
doesContainInsidePoint = #geo.STContains(#insidePoint),
doesIntersectInsidePoint = #geo.STIntersects(#insidePoint)
select
geo = #geo2,
geoString = #geo2.ToString(),
IsValid = #geo2.STIsValid(),
doesContainOutsidePoint = #geo2.STContains(#outsidePoint),
doesIntersectOutsidePoint = #geo2.STIntersects(#outsidePoint),
doesContainInsidePoint = #geo2.STContains(#insidePoint),
doesIntersectInsidePoint = #geo2.STIntersects(#insidePoint)
Both of them seem to work for me - with the following results:
I can query from my Polygon table in the DB using both the STContains and STIntersects methods of the geography type.
So if .STContains is returning 0 for you that means the Point is not inside the box. Maybe you could post a sample Polygon and Point where it is returning 0 but should return 1 that might help.
I am trying to convert my DB2 stored procedure to SQL Server and I'm not sure about this xmltable function
DECLARE #IN_AR_UTL_DATA_XML XML
DECLARE #WS_ACCOUNT_NO DECIMAL(13,0)
DECLARE #WS_BILL_NO INT
SET #IN_AR_UTL_DATA_XML = '<CUST_CHARGES>
<AC_NO>50001233</AC_NO>
<INVOICE_NO>63877</INVOICE_NO>
<INVOICELINES>
<INVOICELINE>
<INVOICE_ENTITY>V52259108</INVOICE_ENTITY>
<ENTITY_TYPE>W</ENTITY_TYPE>
<REVENUE_CLASS>7811</REVENUE_CLASS>
<SEQUENCE_NO>1</SEQUENCE_NO>
<IS_FIXED>false</IS_FIXED>
<IS_BACKOUT>true</IS_BACKOUT>
<DATE_ORIG_INVOICE>20190801</DATE_ORIG_INVOICE>
<CODE_INVOICE_ITM_TYPE>B</CODE_INVOICE_ITM_TYPE>
<INVOICE_ITEM_TIMESTMP>2018-09-
18T09:36:33.703214</INVOICE_ITEM_TIMESTMP>
<TOTAL_AMOUNT>300.44</TOTAL_AMOUNT>
<CHARGES>
<WATER_CHARGES>0</WATER_CHARGES>
<SEWER_CHARGES>300.44</SEWER_CHARGES>
<WATER_CHARGE>-222.3</WATER_CHARGE>
<SEWER_CHARGE>0</SEWER_CHARGE>
<WATER_REFUND>222.3</WATER_REFUND>
<SEWER_DISCOUNT>300.44</SEWER_DISCOUNT>
<CAP_DISCOUNT>0</CAP_DISCOUNT>
<SUR_CHARGE>0</SUR_CHARGE>
</CHARGES>
</INVOICELINE>
<INVOICELINE>
<INVOICEING_ENTITY>V52259109</INVOICEING_ENTITY>
<ENTITY_TYPE>W</ENTITY_TYPE>
<REVENUE_CLASS>611</REVENUE_CLASS>
<SEQUENCE_NO>2</SEQUENCE_NO>
<IS_FIXED>false</IS_FIXED>
<IS_BACKOUT>false</IS_BACKOUT>
<DATE_ORIG_INVOICE>20180918</DATE_ORIG_INVOICE>
<CODE_INVOICE_ITM_TYPE>C</CODE_INVOICE_ITM_TYPE>
<INVOICE_ITEM_TIMESTMP>2018-09-
18T09:36:34.238839</INVOICE_ITEM_TIMESTMP>
<TOTAL_AMOUNT>-938.21</TOTAL_AMOUNT>
<CHARGES>
<WATER_CHARGES>0</WATER_CHARGES>
<SEWER_CHARGES>-938.21</SEWER_CHARGES>
<WATER_CHARGE>694.2</WATER_CHARGE>
<SEWER_CHARGE>0</SEWER_CHARGE>
<WATER_REFUND>-694.2</WATER_REFUND>
<SEWER_DISCOUNT>-938.21</SEWER_DISCOUNT>
<CAP_DISCOUNT>0</CAP_DISCOUNT>
<SUR_CHARGE>0</SUR_CHARGE>
</CHARGES>
</INVOICELINE>
</INVOICELINES>
</CUST_CHARGES>'
Above is my sample XML code. Below is my DB2 statement that needs to be converted.
SELECT
WS_AC_NO = TABLE1.XmlCol1.value('AC_NO[1]' ,'DECIMAL(13,0)')
,WS_INVOICE_NO = TABLE1.XmlCol1.value('INVOICE_NO[1]','SMALLINT')
--,INVOICE_ENTITY = TABLE1.XmlCol1.value('#INVOICE_ENTITY','VARCHAR(9)') -- This is not working.
,INVOICE_ENTITY = TABLE2.XmlCol2.value('INVOICELINES[1]/INVOICELINE[1]/INVOICE_ENTITY[1]','VARCHAR(9)')
,ENTITY_TYPE = TABLE1.XmlCol1.value('INVOICELINES[1]/INVOICELINE[1]/ENTITY_TYPE[1]' ,'CHAR(1)')
,REVENUE_CLASS = TABLE1.XmlCol1.value('INVOICELINES[1]/INVOICELINE[1]/REVENUE_CLASS[1]' ,'SMALLINT')
,SEQUENCE_NO = TABLE1.XmlCol1.value('INVOICELINES[1]/INVOICELINE[1]/SEQUENCE_NO[1]' ,'SMALLINT')
,TOTAL_AMOUNT = TABLE1.XmlCol1.value('INVOICELINES[1]/INVOICELINE[1]/TOTAL_AMOUNT[1]' ,'DECIMAL(11,2)')
,CHARGE = TABLE1.XmlCol1.value('INVOICELINES[1]/INVOICELINE[1]/XmlCol[1]','DECIMAL(11,2)') -- I need all sub charge values
,'W' AS CHARGE_TYPE
,1 AS ORDER_SEQUENCE_NO
,DATE_ORIG_BILL = TABLE1.XmlCol1.value('INVOICELINES[1]/INVOICELINE[1]/DATE_ORIG_BILL[1]' ,'INT')
,CODE_BILL_ITM_TYPE = TABLE1.XmlCol1.value('INVOICELINES[1]/INVOICELINE[1]/CODE_BILL_ITM_TYPE[1]','VARCHAR(1)')
,BILL_ITEM_TIMESTMP = TABLE1.XmlCol1.value('INVOICELINES[1]/INVOICELINE[1]/BILL_ITEM_TIMESTMP[1]','DATETIME2(6)')
FROM #IN_AR_UTL_DATA_XML.nodes('/CUAT_CHARGES') TABLE1(XmlCol1)
CROSS APPLY #IN_AR_UTL_DATA_XML.nodes('/CUAT_CHARGES/INVOICELINES/INVOICELINE')
TABLE2(XmlCol2)
Can you please share SQL Server equivalent syntax for this? SQL Server version 2014 / 2016 is preferred. Thanks.
Perhaps something like:
DECLARE #IN_AR_UTL_DATA_XML XML
DECLARE #WS_ACCOUNT_NO DECIMAL(13,0)
DECLARE #WS_BILL_NO INT
SET #IN_AR_UTL_DATA_XML = '<CUST_CHARGES>
<AC_NO>50001233</AC_NO>
<INVOICE_NO>63877</INVOICE_NO>
<INVOICELINES>
<INVOICELINE>
<INVOICE_ENTITY>V52259108</INVOICE_ENTITY>
<ENTITY_TYPE>W</ENTITY_TYPE>
<REVENUE_CLASS>7811</REVENUE_CLASS>
<SEQUENCE_NO>1</SEQUENCE_NO>
<IS_FIXED>false</IS_FIXED>
<IS_BACKOUT>true</IS_BACKOUT>
<DATE_ORIG_INVOICE>20190801</DATE_ORIG_INVOICE>
<CODE_INVOICE_ITM_TYPE>B</CODE_INVOICE_ITM_TYPE>
<INVOICE_ITEM_TIMESTMP>2018-09-
18T09:36:33.703214</INVOICE_ITEM_TIMESTMP>
<TOTAL_AMOUNT>300.44</TOTAL_AMOUNT>
<CHARGES>
<WATER_CHARGES>0</WATER_CHARGES>
<SEWER_CHARGES>300.44</SEWER_CHARGES>
<WATER_CHARGE>-222.3</WATER_CHARGE>
<SEWER_CHARGE>0</SEWER_CHARGE>
<WATER_REFUND>222.3</WATER_REFUND>
<SEWER_DISCOUNT>300.44</SEWER_DISCOUNT>
<CAP_DISCOUNT>0</CAP_DISCOUNT>
<SUR_CHARGE>0</SUR_CHARGE>
</CHARGES>
</INVOICELINE>
<INVOICELINE>
<INVOICEING_ENTITY>V52259109</INVOICEING_ENTITY>
<ENTITY_TYPE>W</ENTITY_TYPE>
<REVENUE_CLASS>611</REVENUE_CLASS>
<SEQUENCE_NO>2</SEQUENCE_NO>
<IS_FIXED>false</IS_FIXED>
<IS_BACKOUT>false</IS_BACKOUT>
<DATE_ORIG_INVOICE>20180918</DATE_ORIG_INVOICE>
<CODE_INVOICE_ITM_TYPE>C</CODE_INVOICE_ITM_TYPE>
<INVOICE_ITEM_TIMESTMP>2018-09-
18T09:36:34.238839</INVOICE_ITEM_TIMESTMP>
<TOTAL_AMOUNT>-938.21</TOTAL_AMOUNT>
<CHARGES>
<WATER_CHARGES>0</WATER_CHARGES>
<SEWER_CHARGES>-938.21</SEWER_CHARGES>
<WATER_CHARGE>694.2</WATER_CHARGE>
<SEWER_CHARGE>0</SEWER_CHARGE>
<WATER_REFUND>-694.2</WATER_REFUND>
<SEWER_DISCOUNT>-938.21</SEWER_DISCOUNT>
<CAP_DISCOUNT>0</CAP_DISCOUNT>
<SUR_CHARGE>0</SUR_CHARGE>
</CHARGES>
</INVOICELINE>
</INVOICELINES>
</CUST_CHARGES>'
SELECT
WS_AC_NO = r.chargeNode.value('AC_NO[1]' ,'DECIMAL(13,0)')
,WS_INVOICE_NO = r.chargeNode.value('INVOICE_NO[1]','INT')
,INVOICE_ENTITY = i.lineNode.value('INVOICE_ENTITY[1]','VARCHAR(9)')
,ENTITY_TYPE = i.lineNode.value('ENTITY_TYPE[1]' ,'CHAR(1)')
,REVENUE_CLASS = i.lineNode.value('REVENUE_CLASS[1]' ,'INT')
,SEQUENCE_NO = i.lineNode.value('SEQUENCE_NO[1]' ,'INT')
,TOTAL_AMOUNT = i.lineNode.value('TOTAL_AMOUNT[1]' ,'DECIMAL(11,2)')
,WATER_CHARGES = i.lineNode.value('(CHARGES/WATER_CHARGE)[1]','DECIMAL(11,2)') -- I need all sub charge values
,'W' AS CHARGE_TYPE
,1 AS ORDER_SEQUENCE_NO
FROM #IN_AR_UTL_DATA_XML.nodes('/CUST_CHARGES') r(chargeNode)
CROSS APPLY chargeNode.nodes('INVOICELINES/INVOICELINE') i(lineNode)
I have 2 tables in my SQL Server database, for example [Camera] and [CameraData]. How to write a trigger which will change value in [CameraData] after row is inserted into [CameraData] due to delta in [Camera].
For example we have 2 cameras in [Camera]:
Camera 1 with {id} = 1 and {delta} = null
Camera 2 with {id} = 2 and {delta} = 3
So when we have automated insert into table [CameraData], f.e. :
Id_camera = 2, angle = 30, Changed = null
In that case we need to check either we have delta in [Camera] on camera 2 and if that's true we need to modify insert to:
Id_camera = 2, angle = 33 (angle + Camera.Delta), Changed = True
Update 1
According to comment [3] is the column in table [CameraData] where angle is placed
CREATE TRIGGER Delta_Angle
ON CameraData
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE CameraData
SET DeltaFlag = 1, [3] = inserted.[3] + i.DeltaAngle
FROM CameraData h
INNER JOIN Camera i ON h.ID_Camera = i.ID_Camera
WHERE i.DeltaAngle != ''
END
This is very much a stab in the dark, as your sample SQL isn't at all representative of the data your describe in your question, however, maybe something like:
CREATE TRIGGER Delta_Angle ON CameraData
AFTER INSERT AS
BEGIN
SET NOCOUNT ON;
UPDATE C
SET Angle = C.Angle + i.delta
FROM Camera
JOIN inserted i ON C.CameraID = i.CameraID;
END
Notice that I refer to inserted; your trigger wasn't. Also, I'm not sure about your clause i.DeltaAngle != ''. Considering that DeltaAngle appears to be an int, it can never have a value of '' (however, '' would be implicitly converted to the value 0).
If this doesn't help, I (again) suggest you read Sean's link and update your post accordingly.
I've come across a precision issue when calculating the ration between two units of measures.
The Ratio is stored in a SQL Server database in a UnitOfMeasureTable as: NumberOfDefaultUnits decimal(28,18)
In my linqPad example I have a class to demonstate what is going wrong.
private class Test
{
public decimal saleUom { get; set; }
public decimal piUom { get; set; }
public decimal RatioRight { get; set; }
public decimal RatioWrong { get; set; }
public decimal CalcledAlsoRight { get { return saleUom / piUom; } }
}
void Main()
{
var xx = from uom in UnitsOfMeasures.Where(d=> d.Id == 9)
let buyUom = uom.NumberOfDefaultUnits
let sellUom = UnitsOfMeasures.First(d=> d.Id == 13).NumberOfDefaultUnits
select new Test
{
saleUom = sellUom,
piUom = buyUom,
RatioRight = sellUom / (buyUom * 1m),
RatioWrong = sellUom / buyUom,
};
xx.First().Dump();
}
The results are:
saleUom 453.592370000000000000
piUom 1000000.000000000000000000
RatioRight 0.000453592370000000000
RatioWrong 0.0004535923
CalcledAlsoRight 0.00045359237
It took a while to figure out you have to multiply the divisor by 1m to get the correct result. It gets even weirder if you multiply the sellUom by 1m.
Then the result is:
RatioRight = (sellUom * 1m) / (buyUom)
RatioRight 0.000453
I'm guessing this is something to do with how SQL Server stores the Decimal(28,18) and how Linq converts the divide command.
Update: All values are Decimals
Update 2:
Looks like this is entirely a SQL rounding thing. Removing the .Net from the equation
select top 1 uom.NumberOfDefaultUnits
from UnitOfMeasures uom
where uom.Id = 13
select (select top 1 uom.NumberOfDefaultUnits
from UnitOfMeasures uom
where uom.Id = 13 )
/
(select top 1 uom.NumberOfDefaultUnits
from UnitOfMeasures uom
where uom.Id = 9)
The first query returns: 453.592370000000000000
The second: 0.0004535923
This is definitely due to how SQL Server handles precision & scale in calculations.
If you change #mikeymouses example to use a scale of 6 for #p1 you get consistent results:
DECLARE #p2 Decimal(28,6) = 1000000
DECLARE #p3 Decimal(28,18) = 453.59237
select #p3 / #p2
DECLARE #p1 Decimal(19,18) = 1 -- This is how Linq sends the * 1m
select #p3 / (#p2 *#p1)
select (#p3 *#p1) / #p2
Results:
0.0004535923700000000000
0.00045359237000
0.00045359237000000000
The precision and scale outcomes are documented on MSDN, but the key points are:
For Multiplication:
precision of result = p1 + p2 + 1
Scale of result = s1 + s2
For Division:
Precision of result = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Scale of result = max(6, s1 + p2 + 1)
Where p1 and p2 are the precision of the operands and s1, s2 are the scale of the operands.
It should be remembered that the result precision and scale have an absolute maximum of 38. When a result precision is greater than 38, the corresponding scale is reduced to prevent the integral part of a result from being truncated.
I think this is what is happening here.
It looks like this is just how SQL deals with these declared decimal sizes being divided by eachother
DECLARE #p2 Decimal(28,18) = 1000000
DECLARE #p3 Decimal(28,18) = 453.59237
select #p3 / #p2
DECLARE #p1 Decimal(19,18) = 1 -- This is how Linq sends the * 1m
select #p3 / (#p2 *#p1)
select (#p3 *#p1) / #p2
Results:
0.0004535923
0.000453
0.00045359
I need your help:
I want to get the SUM of the the Amount field, it contains decimal values but I get just the INTEGER part and I need the DECIMAL too:
DECLARE #TOTAL AS DECIMAL(13,2)
SET #Total = (SELECT SUM(Amount)
FROM t_DownPmtTrans
WHERE MortgageID = #MortgageID
AND DatePaid IS NULL
AND SchedPayment IS NOT NULL)
I have tried with a CURSOR but I get the same:
OPEN dpt_cursor
SET #Total= 0.0
FETCH NEXT FROM dpt_cursor INTO #DownPmtTransID, #Amount
WHILE ##FETCH_STATUS= 0
BEGIN
PRINT #Amount
SET #Total = (#Total + #Amount)
FETCH NEXT FROM dpt_cursor
INTO #DownPmtTransID, #Amount
END
RETURN #Total* (-1)
CLOSE dpt_cursor
DEALLOCATE dpt_cursor
Thanks!!
You need to set precision and scale rather than size
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter.scale(v=vs.100).aspx
var outputParameter = new SqlParameter
{
Direction = ParameterDirection.Output,
ParameterName = "your parameter name in your stored procedure",
SqlDbType = SqlDbType.Decimal,
Precision = 13,
Scale = 2
};
Declare an array of SQL parameters and add the parameter to it
var parameters = new SqlParameter[1];
parameters[0] = outputParameter
declare a command object
var command = new SqlCommand (); //don't forget everything else
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "stored procedure name"
command.Parameters.AddRange (parameters);
Execute your command
command.ExecuteNonQuery ();
now read the value from the parameters collection
var value = (decimal) command.Parameters[0].Value;
As per MSDN, if the expression is decimal, sum will return decimal(38, s). Make sure the datatype is of amount is decimal. Or try to convert it to decimal using cast or convert. This options may help you.
I can't replicate either, but in any event converting the column you're summing to the datatype of your variable should get you what you want. The only reason this wouldn't be the case is if "Amount" is an int...
DECLARE #TOTAL AS DECIMAL(13,2)
SET #Total = (SELECT SUM(Convert(DECIMAL(13,2),Amount))
FROM t_DownPmtTrans
WHERE MortgageID = #MortgageID
AND DatePaid IS NULL
AND SchedPayment IS NOT NULL)
Since the issue is outside of SQL I did a quick search and found this: http://forums.asp.net/t/33723.aspx/1
According to it this is a known issue. I looked around a little more and while this guy didn't say it helped I would suggest creating a SqlParameter object so you can set the precision property of the object and then pass that in your Add method.