I am writing Insurance Managment System as project at University.
This is my MySQL commadn:
string lifeQuery = "insert into lifeinsurance values( null, '" + surname.Text + "." + pesel.Text + "', " + double.Parse(lifeInsSumTB.Text) + ", '" + double.Parse(lifeInsPriceTB.Text)
+ ");";
But te problem is that in UWP double is with ',' and to MySQL i need to have it with '.'.
When I try to do this like this: '25,453' it says data truncated. Without ' ', like this 25,453 it says that column count doesn't match value count at row 1, because it interets it as two different values 25 and 453.
So my question is:
How do I insert this double value to my table?
This problem is caused by the implicit conversion to a string when you call double.Parse and then concatenate the result back into the sql text. This requires the compiler to represent the double value as a string and it will use the current culture to do the conversion. Of course the result is not what MySql expect to be a double value.
Moreover using string concatenation to build sql commands leads to Sql Injection hacks. A very nasty problem that you should avoid. Always.
So let's try to add some code to resolve these problems
// A parameterized string without any concatenation from user input
string lifeQuery = #"insert into lifeinsurance
values( null, #surname, #sum, #price)";
MySqlCommand cmd = new MySqlCommand(lifeQuery, connection);
// Add the parameters with value for each placeholder in string
cmd.Parameters.AddWithValue("#surname", surname.Text + "." + pesel.Text);
// Parse the user input as a double using the current culture to correctly
// interpret the comma as decimal separator.
// Note that here I have no check on the correctness of the input. If your
// user cannot be trusted to type a valid double number then you should use
// the double.TryParse approach separating these lines from the actual check
cmd.Parameters.AddWithValue("#sum", double.Parse(lifeInsSumTB.Text, CultureInfo.CurrentCulture));
cmd.Parameters.AddWithValue("#price", double.Parse(lifeInsPriceTB.Text, CultureInfo.CurrentCulture));
cmd.ExecuteNonQuery();
Like other said - there are better ways to send over data with Sql. That being said this answer focuses on addressing your specific problem.
I think your problem may be your language/culture settings.
Try this:
Console.WriteLine(double.Parse("19.2323244").ToString("G", CultureInfo.InvariantCulture));
Output:
19.2323244
https://learn.microsoft.com/en-us/dotnet/api/system.globalization.cultureinfo?view=netcore-3.1#Invariant
Related
This my code:
string myDate = dateTime.Month.ToString() + "/" + dateTime.Year.ToString();
sqlCommand.CommandText = ("ALTER TABLE working_hours ADD "+ myDate +" float ");
It doesn't work. But if I replace the Date value with something else then everything works
//*string myDate="DateTime";
I have to get a new column named date (month/year) -> 11/20 10/20 09/20.
First of all - I'd highly suggest against this kind of data model. It's going to be hard to scale it. However if you insist of doing so, the issue is generated SQL statement. I assume you're using SQL Server and this would be the statement it generates:
ALTER TABLE working_hours ADD 11/20 float
Which is incorrect, identifiers in SQL Server, that have illegal characters, must be wrapped in square brackets.
ALTER TABLE working_hours ADD [11/20] FLOAT;
So this should work:
string myDate = dateTime.Month.ToString() + "/" + dateTime.Year.ToString();
sqlCommand.CommandText = ("ALTER TABLE working_hours ADD [" + myDate + "] FLOAT;");
But again - I'd highly suggest against this kind of design. Create a dedicated table with a normalized date field. It's going to be easier to query and maintain that kind of structure.
I have this Oracle 11g table
CREATE TABLE "DBNAME"."CANDIDATES"
(
"ID" NUMBER(24,0),
"USRINS" VARCHAR2(30 CHAR),
"DATINS" DATE,
"USRUPD" VARCHAR2(30 CHAR),
"DATUPD" DATE,
"EXM_ID" NUMBER(24,0),
"TYPE" NUMBER(3,0),
"PSN_ID" NUMBER(24,0),
"KOD" NUMBER(20,0),
"STATUS" NUMBER(20,0),
"PRICINA" VARCHAR2(200 CHAR)
)
Now i have this command in C#
string insertIntoCandidates = "INSERT INTO CANDIDATES " &
"(USRINS, DATINS, PSN_ID, KOD, STATUS, PRICINA) " &
values ("
+ ":usrins, "
+ ":datins, "
+ ":psn_id, "
+ ":kod, "
+ ":status, "
+ ":pricina"
+ ") ";
command.Parameters.Add(":usrins", null);
command.Parameters.Add(":datins", DateTime.Now);
command.Parameters.Add(":psn_id", getPsnIDByEMBG(result.embg));
command.Parameters.Add(":kod", result.kod_kandidat);
if (result.status)
{
command.Parameters.Add(":status", 1);
}
else
{
command.Parameters.Add(":status", 0);
}
command.Parameters.Add(":pricina", result.pricina);
int res = command.ExecuteNonQuery();
The columns for which I don't insert a value, can get null values.
After executing the last line, I get am exception ORA-01722: invalid number. I tried looking for an answer, but without any luck. Could you help me out? Thanks
add
command.BindByName=true;
apparently Oracle defaults to positional binding instead of name binding.
An ORA-01722 ("invalid number") error occurs when an attempt is made to convert a character string into a number, and the string cannot be converted into a valid number. So, check the parameters for correct data types.
And also see:
C# parameterized queries for Oracle - serious & dangerous bug!
and
Why am I getting an ORA-01722 (invalid number)?
Further to michaos's answer, also note that it doesn't matter what you name your parameters, they have to be added in the order in which they appear in the query. If not, then you can get misleading ORA-01722 (and other) errors. Yes this is a horrible bug!
Instead of null you have to use DBNull.Value
I want to compare date entering from a combobox as string with the date that saved into SQL Server database,then summation some values X but comparison doesn't work ...
string from = (comboBox4.Text+ '/' + comboBox5.Text + '/' + comboBox6.Text+ " 00:00:00 AM");
string to = (comboBox1.Text+ '/' + comboBox2.Text + '/' + comboBox3.Text);
cmd.CommandText = "SELECT * from issued where issued.Date >='" +from + " ' And issued.Date < '" + to + " ' "; //مقارنة الاسم
dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
item = new ListViewItem(dr[0].ToString());
item.SubItems.Add(dr[4].ToString());
f6.listView1.Items.Add(item);
x += Convert.ToInt16(dr[4]);
}
}
Help me please..
As Marc stated above, you really should be careful of sql injection attacks here. Look it up and do some research because you'll suddenly find you have a compromised server someday.
Is your Date column of type Date or DateTime? If it's DateTime, then simply comparing on a specific date does not include that date for the upper bound. For instance, if your dates are:
From: 1/1/2013
To: 1/1/2014
Then your comparison would not return any values from 1/1/2014, and the last date included in the search would actually be 12/31/2013.
Add a little more specifics to your question regarding what values you are actually sending in your sql and what the types are in your db and you'll get a better answer!
Good luck!
I'm getting a weird issue with substringing. Apparently the string I get can't be cast into an Int32 for some odd reason. The error message I get when I try doing that is "input string is not in correct format". Because of this, I can't insert these values into the Database either.
Here's the code...
string width = GetMetadata(filename, 162); //returns "1280 pixels"
string height = GetMetadata(filename, 164); //returns "700 pixels"
width = width.Substring(0, width.IndexOf(' ')); //returns "1280"
height = height.Substring(0, height.IndexOf(' ')); //returns "700"
//test: "System.Convert.ToInt32(width)" will fail, giving error "input string was not in correct format"
//doing the above on "width" yields the same result
//fails, giving error "no such column: 1280" (underlying database is sqlite)
Database.NonQuery("INSERT INTO image VALUES (" + fileid + ", " + width + ", " + height + ")");
For all the normal reasons - primarily avoiding leaving data conversions to the database, and preventing SQL injection attacks - I would suggest that you perform the parsing to a number in C#, and then use a parameterized query to talk to SQLite.
In this case, that will make it a lot easier to debug - either .NET will fail to parse the string as well (in which case it's likely to be a problem with your data) or it will work, and you won't need to worry about what conversions database was performing.
EDIT: I've just seen your comment saying that Convert.ToInt32 fails as well. That's a pretty clear indication that it's the data which is causing a problem.
I'd expect your code to look something like this:
string widthText = GetMetadata(filename, 162);
string heightText = GetMetadata(filename, 164);
widthText = width.Substring(0, width.IndexOf(' ')).Trim();
heightText = height.Substring(0, height.IndexOf(' ')).Trim();
int width = int.Parse(widthText, CulutureInfo.InvariantCulture);
int height = int.Parse(widthText, CulutureInfo.InvariantCulture);
using (SQLiteCommand cmd = Database.CreateCommand())
{
cmd.CommandText = "INSERT INTO image VALUES (?, ?, ?)";
cmd.Parameters.Add(fileid);
cmd.Parameters.Add(width);
cmd.Parameters.Add(height);
cmd.ExecuteNonQuery();
}
Note that the Trim call will remove any leading spaces, which it seems was the cause of the problem.
There may be some stray whitespaces in the string variables width and height. Invoke Trim() method on the strings before casting them into integers:
width = width.Trim();
height = height.Trim();
Hope this helps. Let us know.
I know we should never do this:
string select = "SELECT * FROM table1 ";
string where = "WHERE Name = '" + name + "' ";
string sql = select + where;
//execute the sql via ADO.NET
because of sql injection, because name can contain the char ', because of another 100 reasons. But now I have to do something similiar. I have a Dictionary<string, object> whose data look like:
Key(string) Value(object)
"Name" "Bob" //string
"ID" 10092L //long
"Birthday" 1980-05-07 00:00:00 //DateTime
"Salary" 5000.5m //decimal
//some others, whose key is a string, and value is string/long/int/DateTime/decimal
I want an easy way, to get all items in the dictionary collected in a String, just like a where statement:
Name = 'Bob' and ID = 10092 and Birthday = '1980-05-07 00:00:00' and Salary = 5000.5
String and DateTime are quoted with ', but note that the Name can be O'Neal. Is there any easy implementation? Input the dictionary, and return the string as a result.
EDIT Note that what I want is the string, I'm not going to execute it, parameterized command doesn't help. I just want a string that looks like a perfect safe WHERE statement.
The first code is only a problem if name is something entered by the user. Otherwise, it should be fine.
I don't know that it eliminates all problems but you might try experimenting with something like name = name.Replace("'", "''"). By converting all single quotes to double single quotes, you prevent the type of problems you described. Another approach might be to remove any single quotes.
However, the best route is to use query arguments. ADO supports these nicely and that would also eliminate any possibility of injection attacks.
The easy way could be like this:
string results = string.Join(" and ", myDict.Select( x=> x.Key + " = " + x.Value));
This of course wouldn't solve the quotes ' issue depending on different datatypes so you cannot use this as input to a SQL query - for that I would strongly recommend named parameters anyway - but is otherwise correct depending on the ToString() implementation of the values in your dictionary.
I wrote this many years ago, and always use it, and never ever have to think about this again. it is a waste of brain cells to solve this more than once:
// replace things like:
// O'Keefe with
// 'O''Keefe'
// make sure you don't call this twice!
static public string SqlString(string strInputSQL)
{
string strOut;
strOut = strInputSQL;
strOut = strOut.Replace ("'", "''");
strOut = "'" + strOut + "'";
return strOut;
}
Use it like this:
string sql = "SELECT * FROM FOO WHERE Name LIKE " + SqlString(myvalue);
There may be a dozen other ways to do it, but if you can have one and only one function, and use it consistently, you will save alot of time.
Try this link : Creating safe SQL statements as Strings
Some people consider this over-engineered, or just labourious to type. I fall back on a simple argument though...
Someone has already invested time and effort ensuring arguements can be safely and reliably included in SQL statements. Are you 100% certain you have pre-empted every possible scenario? Or is it more likely tried and tested code is more reliable?
But, then, I'm a bit anal ;)
var sb = new StringBuilder();
var isFirst = true;
foreach (var element in dic)
{
if(!isFirst)
sb.Append(" AND ");
else
isFirst = false;
sb.Append(element.Key);
sb.Append(" = ");
if(element.Value is decimal)
sb.Append(CastToSqlDecimalString((decimal)element.Value));
else
sb.Append("'" + String.Format(CultureInfo.InvariantCulture, "{0:G}", element.Value).Replace("'", "''") + "'");
}
You might want to handle decimals using this function
public static string CastToSqlDecimalString(decimal dec)
{
var sqlDecimal = new System.Data.SqlTypes.SqlDecimal(dec);
return string.Format("CAST({0} AS DECIMAL({1}, {2}))",
string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:G}", dec),
sqlDecimal.Precision,
sqlDecimal.Scale);
}