I have a project that is used by several clients but for one of them using sql server 2005 wherever any code that runs a sql statement which includes a date like so:
" AND ABS.AbsenceDate = '" + DateTime.Now.ToString("yyyy-MM-dd") + "'";
I get the error: The conversion of a varchar data type to a datetime data type resulted in an out-of-range value
This only happens for this one client/server, if I copy the actual sql string created and execute it in Sql Server on this server it runs ok. I created a test page to ensure the date string was correct and did indeed display as 2013-11-26 as expected. My assumption was that the app was sending the date as 2013-26-11 as this would cause the issue but then the test showed otherwise so leaves me stumped.
For info, this is on an English server so the regional setting is day/month/year and dates stored as year-month-day etc
Don't concatenate strings to build your sql string but sql-parameters. The main reason is to prevent sql-injection but it can also prevent localization- or conversion issues like this.
string sql = #"SELECT Columns
FROM dbo.tableName
WHERE ...
AND ABS.AbsenceDate = #AbsenceDate";
using(var con = new SqlConnection("ConnectionString"))
using(var cmd = new SqlCommand(sql, con))
{
cmd.Parameters.AddWithValue("#AbsenceDate", DateTime.Today);
con.Open();
using(var reader = cmd.ExecuteReader())
{
while(reader.Read())
{
// ...
}
}
}
I have solved the issue and quite surprised at what the problem was. I was able to run the sql ok in management studio but I was logged in using Windows Authentication. I realised I should try with the account the app uses and when logged in as this I did get the error.
Turns out whoever set the account up had the Language set to British English. I changed it to English and voila problem solved.
Never mind the added security, Sql Parameters would solve your problem automatically.
Is there a date part for that date or is it irrelevant ?
An example solution would be the following:
" AND ABS.AbsenceDate = Convert(DateTime, '" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "', 20) "'
Related
I am trying to insert some calendar dates into an Access database using C#. Unfortunately, it is not working for some reason. The problem is the code is running absolutely perfectly on the computers found in my high school, which are running Office 2007, Windows 7. When I run the same code on my Windows 10 laptop, I get the error:
System.Data.OleDb.OleDbException: 'Data type mismatch in criteria expression.'
However, the calendar dates are set in the short format, in the database.
I have already tried to convert the strings I am attempting to insert into the database. Some of the conversions I have tried are:
Convert.ToDateTime(itemi[1]);
DateTime.Parse(itemi[2]);
DateTime.ParseExact(itemi[2], "d", null);
Where itemi[2] is one of the strings which are written in calendar date format.
For example: itemi[2] = "02.05.2017"; or itemi[2] = "05.08.2019";
I have also tried to change the . characters found in the itemi[2] string with / characters, with no success. I have even tried to use the Trim() function, in order to make sure the string does not have any blank spaces in it. My professor could not find any solution for this issue, as well, and we looked over the code for hours and searched the internet with no result.
Here is the code with the described issue (the connection to the database has already been opened a few lines of code before, but I consider this to be irrelevant, so I do not include it in the mentioned code):
var query = "INSERT INTO Planificari (Frecventa, DataStart, DataStop, IDLocalitate) "
+ "VALUES ('" + itemi[1].Trim() + "', '" + itemi[2].Trim()
+ "', '" + itemi[3].Trim() +"', " + idLocalitate + ")";
OleDbCommand command = new OleDbCommand(query, connection);
command.ExecuteNonQuery(); // this is the point I get the mentioned error
// DataStart and DataStop are the calendar dates
// in my access 2016 database
I am currently writing an application which involves a user being able to write the time to a database by clicking a button. The problem is that the data will be send to the database table, but it does not show the time in SQL Server Management Studio.
This is my query:
{
string query = "insert into Sign_In_Out_Table(Sign_In)Values('"+ timetickerlbl.ToString()+ "')";
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue("#SignIn", DateTime.Parse (timetickerlbl.Text));
//cmd.ExecuteNonQuery();
MessageBox.Show("Signed in sucessfully" +timetickerlbl);
con.Close();
}
The datatype in SQL Server is set to datetime.
I'm open for suggestions to find a better way to capture the PC's time and logging it in a database.
Don't wrap the variable in ' when you are setting value with Parameters.Add(), or Parameters.AddWithValue() as they would wrap if needed.
The variable in here would be the value of Sign_In and not the Sign_In itself.
Always use Parameters.Add() instead of Parameters.AddWithValue():
string query = "insert into Sign_In_Out_Table(Sign_In) Values(#value)";
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.Add("#value", SqlDbType.DateTime).Value = DateTime.Parse(timetickerlbl.Text);
Edit (Considering your comment):
If still it does not insert it, of course there is an error in your code, it could be a syntax error, invalid table or column name, connection problem ,... so put your code in a try-catch block (if it isn't already) and see what error you you get, it should give you a hint:
try
{
//the lines of code for insert
}
catch(Exception ex)
{
string msg = ex.Message;
// the above line you put a break point and see if it reaches to the break point, and what the error message is.
}
Your table does not contain your timestamp because you have commented the execution of your query. Presumably you added the comment because this line was throwing an error, remove the comment and share the error with us.
cmd.ExecuteNonQuery();
We busy running c# asp website with MS SQL DB.
Some of the columns have been assigned type decimal(18,2).
SqlCommand cmd = new SqlCommand("select * from TABLE", conn);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Response.Write("Amount : " + dr["DEC_COLUMN"].ToString());
}
On my colleagues localhost, when he does a simply select, values come back as 10.01
10.02
15.03
On my localhost it comes back as
10,01
10,02
15,03
My colleague and our Dev Server has the same values.
Apart from the string replace hacks, I would like to get my settings the same so that my values also return with point not comma.
I checked the regional settings on my PC and its the exact same as the Dev server.
I dumped my local DB and used the Export / Import wizard from Dev server but still no luck.
Which setting in windows / .NET / SQL is needed to be changed to make my local environment the same?
But since my copy of source code is the same as my colleages as well as that of dev server, all controlled by SVN, how could it differ?
Because the default system culture isn't defined in the source code.
I very much doubt that you really want to write a response in exactly that format anyway, but you could always specify the invariant culture:
while (dr.Read())
{
decimal value = (decimal) dr["DEC_COLUMN"];
Response.Write("Amount : " + value.ToString(CultureInfo.InvariantCulture));
}
I have a SQL stored procedure which uses openrowset command and fetches values from an excel sheet and inserts it into the database.
I have created a C# application which will call the procedure and execute it.
PROBLEM!
When I execute the procedure from SQL management studio, there are no errors. It happens perfectly. But when I execute it through the C# application I get an error: "Conversion failed when converting date and/or time from character string."
Code
SQL Query (only the insert part)
insert into tbl_item ([Item code],[Dt Created])
select[Item code] ,
case when [Dt Created] is null or [Dt Created]='' then null when ISDATE(CONVERT(nvarchar,CONVERT(datetime, [Dt Created],103))) =1 then CONVERT(datetime, [Dt Created],103) else null end as [Dt Created]
FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0','Excel 12.0; Database=C:\Upload\Report.xlsx;HDR=YES;IMEX=1;',
'select * from [Sheet1$]')
C# Code
public int updateItem()
{
SqlCommand cmd; cmd = new SqlCommand("usp_updateItem", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter returnParameter = cmd.Parameters.Add("RetVal", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.ReturnValue;
try
{
if (conn.State.Equals(ConnectionState.Closed))
conn.Open();
cmd.ExecuteNonQuery();
ret = Convert.ToInt32(returnParameter.Value);
}
catch (Exception e)
{
err = "Error: " + e.Message;
return -1;
}
finally
{
conn.Close();
}
return ret;
}
What is the format you are having in the [Dt Created] variable.
the convert statement you have in the case will convert only the following types below
YYYY-MM-DD
YYYY-DD-MM
DD-MM-YYYY
The error you are getting is since you have a date in the format of "MM-DD-YYYY" something like '12-24-2015'. Due to this you are getting the conversion error.
Excuse me I want to stop you here. Your problem has resolved now but whatever
Karthik Venkatraman had said is correct. Somehow you got solution but for learning purpose i recommended to investigate little bit more. This is not belongs to the whatever you have said but damm sure this belongs to date-format.
**
One trick
Create one DateTimeVariable and once its initialized then just parse it using DateTimeParse class according to the records exist in database.
I am sure you will get solution.. Thanks :)
This is how I finally solved it...
The SQL error message 'Failed Conversion' was absolutely a wrong pointer. It had no connection to the issue at hand. [If only I knew this before :( ]
The actual problem was that I had called another procedure within the main procedure I had posted above. This setup ran perfectly in SQL management studio which was running under my credentials. Now in the C# application, I had created another SQL login user ID to run it. And this user ID did not have execute permission to run the sub procedure. And ironically, SQL gave me a misleading conversion error. Once I gave the right permission it worked perfectly.
I am currently writing my first .Net & C# application with Visual Studio, and have a need to write generated values to MySQL from the application.
At present, I can write values fine - but I need to be able to check to see if a value exists and display that line if it does exist, otherwise insert new line to table. My connection string is defined at the top of the form.
I have the following defined already, and it writes to the database successfully if no duplicate values exist in the LicenseKey column. If a duplicate exists, it throws an unhandled exception.
private void SaveDetails()
{
// MySQL 'insert' command
string InsertNewLicense = "insert into BCOM.LicenseDetails(LicenseeName,ComputerName,ContactName,ContactEmail,LicenseKey,CreationDate) values('" +this.textBoxLicenseeName.Text+ "','" +this.textBoxComputerName.Text+ "','" +this.textBoxContactName.Text+ "','" +this.textBoxContactEmail.Text+ "','" +this.textBoxLicenseKey.Text+ "','" +this.textBoxCreationDate.Text+ "');";
//MySQL instance details
MySqlConnection InsertLicenseDetails = new MySqlConnection(LicenseDatabaseConnection);
//MySQL command execution
MySqlCommand InsertCommand = new MySqlCommand(InsertNewLicense, InsertLicenseDetails);
// Handles command outputs.
MySqlDataReader InsertReader;
//Opens connection to run query on database
InsertLicenseDetails.Open();
// Here our query will be executed and data saved into the database.
MessageBox.Show("License Details Saved. Please ensure you have emailed the license to the customer.");
while (InsertReader.Read())
{
}
InsertLicenseDetails.Close();
}
What I want to happen is for a check to be run on the LicenseKey column to see if the value exists, before different actions are taken.
If the value does not exist, I would like to insert the new line to the table (like my existing command does).
If, however, the value does exist, I would like to pop up a form showing the values from the line that the duplicate appears in as a form.
Where would I put in an event handler to read MySQLException values? What exception would I have to respond to for a duplicate value or no database response?
I agree with what the others have said in their comments, you could change the SQL Query to do the check instead of having 2.
IF(SELECT ... WHERE A = B)
RETURN THAT THE VALUE ALREADY EXISTS
ELSE
INSERT NEW VALUE
Also there was a good comment about SQL Injection and parameterized queries. The query string should look a bit more like
INSERT into BCOM.LicenseDetails(LicenseeName,ComputerName,ContactName,ContactEmail,LicenseKey,CreationDate) values(#LicenseeName, #ComputerName, #ContactName ...);
and your SqlCommand be parameterized
InsertCommand.Paramaters.AddWithValue("#LicenseeName", this.textBoxLicenseeName.Text);
InsertCommand.Paramaters.AddWithValue("#ComputerName", this.textBoxComputerName.Text);
...
That should be a good start to get you going.
After looking at the queries for a while I decided to try a different tack - instead of using a direct check if it's there, I opted to use a count(*) query. When I click the save button on the form, the buttonClick_event calls SaveDetails(), which runs the following:
private void SaveDetails()
{
string InsertNewLicense = "INSERT into BCOM.LicenseDetails(LicenseeName,ComputerName,ContactName,ContactEmail,LicenseKey,CreationDate) values(#LicenseeName, #ComputerName, #ContactName, #ContactEmail, #LicenseKey, #CreationDate)";
string LicenseExistence = "SELECT COUNT(*) FROM BCOM.LicenseDetails WHERE LicenseKey LIKE #LicenseKey";
MySqlConnection LicenseDetails = new MySqlConnection(LicenseDatabaseConnection);
MySqlCommand InsertCommand = new MySqlCommand(InsertNewLicense, LicenseDetails);
InsertCommand.Parameters.AddWithValue("#LicenseeName", this.textBoxLicenseeName.Text);
InsertCommand.Parameters.AddWithValue("#ComputerName", this.textBoxComputerName.Text);
InsertCommand.Parameters.AddWithValue("#ContactName", this.textBoxContactName.Text);
InsertCommand.Parameters.AddWithValue("#ContactEmail", this.textBoxContactEmail.Text);
InsertCommand.Parameters.AddWithValue("#LicenseKey", this.textBoxLicenseKey.Text);
InsertCommand.Parameters.AddWithValue("#CreationDate", this.textBoxCreationDate.Text);
MySqlCommand QueryCommand = new MySqlCommand(LicenseExistence, LicenseDetails);
QueryCommand.Parameters.AddWithValue("#LicenseKey", this.textBoxLicenseKey.Text);
MySqlDataReader InsertReader;
LicenseDetails.Open();
if ((int)(long)QueryCommand.ExecuteScalar() >0)
{
MessageBox.Show("This license already exists in the database.");
}
else
{
InsertReader = InsertCommand.ExecuteReader();
MessageBox.Show("License Details Saved. Please ensure you have emailed the license to the customer.");
while (InsertReader.Read())
{
}
}
LicenseDetails.Close();
So, if the query against the license keys returns with any results at all (more than 0 rows returned), a messagebox pops up showing that the key already exists. If the resultant number of rows is 0, the insert command gets run.
This was figured out with a look through MySQL command notes, testing with phpMyAdmin, matching against existing projects online, and support from the following:
The SELECT query was figured out with great support from #Seige.
The query was parameterized with help from Seige, following on from the advice of Sani Huttunen. Many thanks to them both.
Changing to the count method was done on the advice of a fellow coder in another community online - a good friend and brilliant coder.