Decimal value rounded up in vb.net - sql-server

Everytime I execute UPDATE function with decimal values it captures rounded off integer values. Anyone knows what’s the datatype to use? I tried money and float still I’m getting rounded off value.
Here’s my .vb code
cmd.CommandText=“UPDATE [dbo].[transaction] SET Price=#Price WHERE ID=#ID”
cmd.Parameters.Add(“#Price”,SqlDbType,Decimal,18,2).Values=Textbox1.text
cmd.Parameters.Add(“#ID”,SqlDbType,Int).Values=Textbox2.text
SQL Server Datatype
ID(PK,Int,not null)
Price(decimal(18,2),null)
Input: 25.75
Result: 25
Desired Result: 25.75

You need to set Option Strict On - it would have pointed out that there is no overload of .Add which takes (String, SqlDbType, Integer, Integer).
You could use something like:
Dim dv = Decimal.Parse(Textbox1.Text)
cmd.Parameters.Add(New SqlParameter With {
.ParameterName = "#Price",
.SqlDbType = SqlDbType.Decimal,
.Precision = 18,
.Scale = 2,
.Value = dv})
(You should also set Option Strict On as the default for new VB projects.)

Related

Is conversion from string to decimal needed and if so how should it be done?

I am trying to write a code for correction of entries to my SQL Server database. I am a mechanical engineering student who has a programming class and I have never programmed before so I am not sure should I convert string to decimal and how. Last 2 rows contain 2 options I came up with. Second one is what I use for pure string, first one is a modification of formatting datetime.
This is my stored procedure:
ALTER PROCEDURE [dbo].[SP_RN_O_Ispravak]
#Br_RN_O bigint,
#Datum_O DateTime OUTPUT,
#Sifra_p int OUTPUT,
#Ime_P nvarchar (30) output,
#Prezime_P NVarChar(30) OUTPUT,
#Naziv_P nvarchar (50) output,
#Adresa_P nvarchar (50) OUTPUT,
#Telefon_P NVarChar(15) OUTPUT,
#Sifra_z int OUTPUT,
#Ime_Z nvarchar (30) output,
#Prezime_Z nvarchar (30) output,
#Sifra_kul nvarchar (3) OUTPUT,
#Naziv_Kul NVarChar(20) OUTPUT,
#Masa_O decimal (5,0) OUTPUT,
#Vlaga_O decimal (4,1) OUTPUT,
#Hek_Masa_O decimal (3,1) OUTPUT,
#Protein_O decimal (3,1) output,
#Cijena_O decimal (3,2) output
AS
SELECT #Br_RN_O=T_Otkup.Br_RN_O,
#Datum_O=T_Otkup.Datum_O,
#Sifra_p=T_Otkup.Sifra_p,
#Sifra_z=T_Otkup.Sifra_z,
#Sifra_kul=T_Otkup.Sifra_kul,
#Masa_O=T_Otkup.Masa_O,
#Vlaga_O=T_Otkup.Vlaga_O,
#Hek_Masa_O=T_Otkup.Hek_Masa_O,
#Protein_O=T_Otkup.Protein_O
FROM T_Otkup
WHERE (T_Otkup.Br_RN_O = #Br_RN_O)
SELECT #Prezime_P=Prezime_P
FROM T_Poljoprivrednik
WHERE Sifra_P=#Sifra_p
SELECT #Prezime_z=Prezime_Z
FROM T_Zaposlenik
WHERE Sifra_Z=#Sifra_z
SELECT #Naziv_kul=Naziv_Kul
FROM T_Kultura
WHERE Sifra_Kul=#Sifra_kul
RETURN
This procedure is supposed to pull the data from the database and place it in textboxes shown in the image.visual of whati'm trying to make
I managed to use the following code to convert decimal to string:
Dim cijenao As SqlParameter = New SqlParameter("#Cijena_O", Data.SqlDbType.Decimal, 3, 2)
cijenao.Direction = Data.ParameterDirection.Output
cijenao.Value = Cijena_O.Text
cmd.Parameters.Add(cijenao)
Masa_O.Text = Format(masao.Value, "#####").ToString
Vlaga_O.Text = Format(vlagao.Value, "###.#").ToString
Hek_Masa_O.Text = Format(hmasao.Value, "##.#").ToString
Protein_O.Text = Format(proto.Value, "##.#").ToString
However, it doesn't work for 2 decimal places like this:
Cijena_O.Text = Format(cijenao.Value, "#.##").ToString
I tried using the code posted by Mary, but it get the following message:
System.Data.SqlClient.SqlException: 'Procedure or function SP_RN_O_Ispravak has too many arguments specified.'
I've cleaned up this Sub, to properly scope the connection, and make sure the Connection and Command objects get disposed (via Using). It is always best to explicitly handle the data type conversions, such as using .ToString() on the .Value property of the parameters. Note I also parse the Long before assigning it to the input parameter (although you should Google the .TryParse() method and use that).
Protected Sub ISPRAVAK_NALOGA()
Using conn As New SqlConnection(<your connection string here>)
Using cmd As New SqlCommand("SP_RN_O_Ispravak", conn) With {.CommandType = CommandType.StoredProcedure}
With cmd
.Parameters.Add("#Br_RN_O", SqlDbType.BigInt).Value = Long.Parse(Br_RN_O.Text)
.Parameters.Add("#Masa_O", Data.SqlDbType.Decimal, 5, 0)
.Parameters("#Masa_O").Direction = ParameterDirection.Output
.Parameters.Add("#Vlaga_O", Data.SqlDbType.Decimal, 4, 1)
.Parameters("#Vlaga_O").Direction = ParameterDirection.Output
conn.Open()
.ExecuteNonQuery()
Masa_O.Text = .Parameters("#Masa_O").Value.ToString
Vlaga_O.Text = .Parameters("#Vlaga_O").Value.ToString
End With
End Using
End Using
End Sub
As to your code...
Check the available overloads for the Constructors for the Parameter class. https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlparameter?view=netframework-4.8#constructors There are none that match your code. Dim masao As SqlParameter = New SqlParameter("#Masa_O", Data.SqlDbType.Decimal, 5, 0) The final parameter of the constructor with 4 parameters is a string holding the name of the source column.
A Bigint in Sql Server maps to and Int64 in .net. (A Long in vb.net) This is a good reference for mapping datatypes from Sql Server to .net. https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-data-type-mappings.
Now my code...
Declare the variable outside the using blocks.
The TryParse is a very clever method that not only test a string but fills the variable with the converted string when it succeeds. Return is functionly equivalent, in this case, to the vb.net specific Exit Sub . Return is often used in other languages (think C#).
Keep your databse objects local so you can control their closing and disposing. A Using block will do this for you even if there is an error. You don't need to create new variable for the parameters. They can be referred to by name in the Parameters collection. Set the values of maso an vlaga inside the Using block before the command is disposed.
After the database objects are duly discharges, we can set the values in the User Interface. Reguarding the .ToString method; N0 (the 0 is a zero) will give you a string containing the number with no decimal protion. The N stands for Number and the 0 is the number of decimal places. It adds commas to make the number easier to read and it will round as appropriate. See https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings for more details.
Ideally the database code and the UI code would be separated but that is for another day.
Protected Sub ISPRAVAK_NALOGA()
Dim maso As Decimal
Dim vlaga As Decimal
Dim InputNumber As Long
If Not Long.TryParse(Br_RN_O.Text, InputNumber) Then
MessageBox.Show("Please enter a valid number.")
Return
End If
Using conn As New SqlConnection("Your connection string")
Using cmd As New SqlCommand("SP_RN_O_Ispravak", conn)
cmd.CommandType = CommandType.StoredProcedure
With cmd.Parameters
.Add("#Br_RN_O", SqlDbType.BigInt).Value = InputNumber
.Add("#Masa_O", Data.SqlDbType.Decimal)
.Add("#Vlaga_O", Data.SqlDbType.Decimal)
End With
cmd.Parameters("#Vlaga_O").Direction = ParameterDirection.Output
cmd.Parameters("#Masa_O").Direction = Data.ParameterDirection.Output
conn.Open()
cmd.ExecuteNonQuery()
maso = CDec(cmd.Parameters("#Masa_O").Value)
vlaga = CDec(cmd.Parameters("#Vlaga_O").Value)
End Using
End Using
Masa_O.Text = maso.ToString("N0")
Vlaga_O.Text = vlaga.ToString
End Sub
I am a bit unsure of what you intent.
But if you want to know if you need to convert a number into a string before assigning the value to a textbox, then the answer is yes. You do need to convert it.
But there are a few things that you can do to display decimal values in a more readable way. For example, you can set the textbox customFormat to #########0.00 or ######,##0.00

Stored procedure output parameters return empty

In my SQL Server 2014 I have a Stored procedure that returns 2 values in 2 variables as output:
#TotalNoRatio
#TotalRatio
Here are the results after execution:
#TotalNoRatio #TotalRatio
34510793 31857292
Return Value 0
Now I want those 2 values to be display in a Label on my form.
Here is the code:
cmd2.CommandType = CommandType.StoredProcedure
cmd2.Parameters.Add("#TotalNoRatio", SqlDbType.Decimal)
cmd2.Parameters.Add("#TotalRatio", SqlDbType.Decimal)
cmd2.ExecuteNonQuery()
Me.LTotal1.Text = cmd2.Parameters("#TotalNoRatio").Value
Me.LTotal2.Text = cmd2.Parameters("#TotalRatio").Value
Everything runs fine without errors except that the results are empty.
You need to define direction as return something like this:
SqlParameter retval = sqlcomm.Parameters.Add("#TotalNoRatio", SqlDbType.Decimal);
retval.Direction = ParameterDirection.ReturnValue;
You will need to specify the direction of you parameters as ParameterDirection.Output. You will also need to declare your parameters on your procedure as OUTPUT.
I have put together a small example below.
This is my procedure:
CREATE PROCEDURE [dbo].[procedureName]
#TotalNoRatio DECIMAL(18,2) OUTPUT,
#TotalRatio DECIMAL(18,2) OUTPUT
AS
SET #TotalNoRatio = 2
SET #TotalRatio = 3
This is my VB.NET code:
Using con As New SqlConnection(conString),
cmd As New SqlCommand("procedureName", con) With {.CommandType = CommandType.StoredProcedure}
con.Open()
cmd.Parameters.Add(New SqlParameter("#TotalNoRatio", SqlDbType.Decimal) With {.Direction = ParameterDirection.Output})
cmd.Parameters.Add(New SqlParameter("#TotalRatio", SqlDbType.Decimal) With {.Direction = ParameterDirection.Output})
cmd.ExecuteNonQuery()
lTotal1.Text = "TotalNoRatio: " & cmd.Parameters("#TotalNoRatio").Value.ToString()
lTotal2.Text = "TotalRatio: " & cmd.Parameters("#TotalRatio").Value.ToString()
End Using
This is a screenshot of the output:
On a seperate note consider turning Option Strict On:
Restricts implicit data type conversions to only widening conversions, disallows late binding, and disallows implicit typing that results in an Object type.
cmd.Parameters("#TotalNoRatio").Value returns type Object. You should be appending .ToString() to it if you're assigning to Label.Text.
Also note that I have implemented Using. You may already have, it's difficult to tell but if you haven't it's worth doing:
Sometimes your code requires an unmanaged resource, such as a file handle, a COM wrapper, or a SQL connection. A Using block guarantees the disposal of one or more such resources when your code is finished with them. This makes them available for other code to use.

Convert DT.Rows(0).item to DateTime String MM/dd/YYYY

Hi i am pulling the date from sql server which returns this: 12/19/2014 4:17:31 PM
However I only want it to return 12/19/2014
I am using this to get the order date: txtOrderDate.Text = dt.Rows(0).Item("OrderDate")
How do I convert this to only return the date in this format MM/dd/YYYY?
I cannot do it using the SQL Statement because I am pulling other columns as well.
Thanks
You could get the output desidered with
Dim dt as DateTime
if Not dt.Rows(0).IsNull("OrderDate") _
AndAlso DateTime.TryParse(dt.Rows(0).Item("OrderDate"), _
CultureInfo.InvariantCulture, _
DateTimeStyles.None, dt) Then
txtOrderDate.Text = dt.ToString("MM/dd/yyyy")
else
.... ' Something to do in case of null or invalid date
End If
The use of DataRow.IsNull and DateTime.TryParse is a precautionary step to avoid any possible exception in case your column "OrderDate" is null or not in a correct format.
I think this will work:
txtOrderDate.Text = dt.Rows(0).Item("OrderDate").ToString("MM/dd/yyyy")
However, it's been a while since I've had to work with DataTable cells directly; there's a chance the above code will only have the Object type, rather than the VB.Net DateTime type, and therefore that .ToString() overload won't be available. If that's the case, do this instead:
txtOrderDate.Text = DirectCast(dt.Rows(0).Item("OrderDate"), DateTime).ToString("MM/dd/yyyy")

SUM function does not return decimal

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.

Result type from SQL Server stored procedure

Ok so I'm calling a stored procedure and I'm unsure of what type my VB.net code will be receiving.
Here's the stored procedure:
#IDNo varchar(Max)
AS
select a.IDNo,
p.EMAIL
from person p
left join customer a on p.person_id=a.person_id
where (a.IDNo=#IDNo)
Here's my VB so far;
resultSet = thisDataCxt.sp_GetEmail(IDNo).FirstOrDefault()
My question is, what type should resultSet be? Can I make it an Object? If so how do I access its IDNo and EMAIL properties.
Also need to bear in mind I'm using this to see if there are no results back (aka IDNo didn't have a match) so I need to test if resultSet is NULL.
Why cant you use Dataset & datatables and store the sp output in that.Then try to iterate the values through it if datatable has more than 0 rows.
It's going to be whatever you've mapped the result of the FunctionImport sp_getEmail to, probably a ComplexType. It's not going to be a set, per se, as you're taking the FirstOrDefault.
Incidentally, prefixing your SPs with sp_ is bad practice. http://sqlserverpedia.com/blog/sql-server-bloggers/stored-procedure-performance-using-%E2%80%9Csp_%E2%80%9D-prefix-%E2%80%93-myth-or-fact/
Check this sample code.
cmd.CommandText = "your proc name";
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter param1 = cmd.Parameters.Add("#param1", SqlDbType.VarChar, 255);
param1.Direction = ParameterDirection.Input;
SqlParameter param2 = cmd.Parameters.Add("#param2", SqlDbType.Int, 8);
param2.Direction = ParameterDirection.OutPut;
cmd.ExecuteNonQuery();
Now you have your output value in #param2.

Resources