I have Date Var in Oracle, and I try to insert Data from my C# program
sql = "insert into Table(MyDate) values (" + convert.todatetime(txt) + ")";
I get an Error, what can i do ?
cmd.CommandText = "INSERT INTO Table (myDate)VALUES(:dateParam)";
cmd.Parameters.Add(new OracleParameter("dateParam", OracleDbType.Date))
.Value = DateTime.Now;
cmd.ExecuteNonQuery();
Use parameters. It's going to solve your problem and prevent injection.
Oracle expects it to be an actual date value, not just a string that looks like a date. You have to use the TO_DATE() function to explain how your string is formatted, something like this:
INSERT INTO Table (myDate)
VALUES(TO_DATE('2009-03-30 12:30:00', 'YYYY-MM-DD HH:mi:ss'));
Try using DateTime.TryParse(text) or DateTime.Parse(text)
I know this was a poorly asked question, but I saw some poor answers when I had the same question and ran into this. This is how I solved it, and I'll answer using the OP's context:
Parse the date in to a DateTime variable:
DateTime myDate = DateTime.Parse(txt);
Then parameterize your query:
sql = "insert into Table(MyDate) values (:myDate)";
Set up an OracleParameter:
OracleParameter param = new OracleParameter();
param.ParameterName = "myDate";
param.OracleDbType = OracleDbType.Date;
param.Value = myDate;
Assuming you already have an OracleConnection as connection, set up your command and add your parameter:
OracleCommand cmd = new OracleCommand(sql, connection);
cmd.Parameters.Add(param);
Execute:
cmd.ExecuteNonQuery();
Do NOT waste your time on any of the TO_DATE nonsense. This is for when you are adding something using SQL*Plus or Oracle SQL Developer directly, or MAYBE where you want to send in a STRING variable's value (not a DateTime variable) in the EXACT format that TO_DATE expects and that you assign within the TO_DATE construct within your query or a stored procedure (i.e. to_date('2013-05-13 12:13:14', 'YYYY-MM-DD HH24:MI:SS'). Using a DateTime variable and assigning that to an OracleParameter with an OracleDbType of OracleDbType.Date, assuming you have a DATE field in your table and can parse txt into a DateTime variable, however, is best and easiest.
Easiest way possible:
DateTime inputDate = Convert.ToDateTime("01/01/2019"); //<---Input Sample Date in format
string queryParameters = String.Format("SELECT * FROM TABLE WHERE DATE = '{0}')", inputDate.ToString("dd-MMM-yyyy")); //<-- Converts System.DateTime into Oracle DateTime
//Forget looking anywhere else for an answer, copy and paste and reform this very code
//and see the results
Please bind your variables (like ocdecio tells) ! Not only does it prevent sql injection it is also much faster. Especially in a multi concurrency situation. Read for example here: http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28844/building_odp.htm#CEGCGDAB .
"Bind variables are placeholders inside a SQL statement. When a database receives a SQL statement, it determines if the statement has already been executed and stored in memory. If the statement does exist in memory, Oracle Database can reuse it and skip the task of parsing and optimizing the statement. Using bind variables makes the statement reusable with different input values. Using bind variables also improves query performance in the database, eliminates the need for special handling of literal quotation marks in the input, and protects against SQL injection attacks."
Related
So the thing is, im trying to insert 2 dates into my local database using c#, the date values are taken from 2 different datetimepickers called dtp1 and dtp2 but i dont know how to do that, i tried the following:
connect.Open();
command = new SqlCommand("insert into ab (id, name, data1, data2) values ("+int.Parse(textbox_id.Text)+", '"+textBox_name.Text+"', "+dtp1.Value+","+dtp2.Value+")",connect);
command.ExecuteNonQuery();
connect.Close();
The error is : incorrect syntax
First let's fix the SQL injection vulnerability in your code. Create a query with parameters:
command = new SqlCommand("insert into ab (id, name, data1, data2) values (#id, #name, #data1, #data2)",connect);
Then you can simply add values for those parameters, without having to worry about their string representations (rendering your current problem moot):
command.Parameters.AddWithValue("#id", int.Parse(textbox_id.Text));
command.Parameters.AddWithValue("#name", textBox_name.Text);
command.Parameters.AddWithValue("#data1", dtp1.Value);
command.Parameters.AddWithValue("#data2", dtp2.Value);
The benefits here include:
Much cleaner and easier to read code
You can use values as-is rather than trying to convert them to specific string representations
Most importantly, you're treating user input as values rather than as executable code
Use SqlParameter to be sure no sql injection is possible: How does SQLParameter prevent SQL Injection?.
If you use string concation, try to use string.Format to get things more clear: string.Format("insert into ab (id, name, data1, data2) values ({0}, '{1}', {2}, {3})", textbox_id.Text, textBox_name.Text, dtp1.Value, dtp2.Value). But in general this is not a good idea to pass parameter.
Why do you use int.parse if you make a ToString later when concation? This is not needed: ("+int.Parse(textbox_id.Text)+",. This is the same like this: ("+(int.Parse(textbox_id.Text)).ToString()+", which is the same like: textbox_id.Text. Besides it throws an exception if textbox_id.Text does not contains some thing that could be parsed into an integer. If you want to check for integer, just use int.TryParse.
You may get some syntax error if dtp1.Value or dtp2.Value is empty or if you try to pass some thing besides integer.
Using SqlParamter for DateTime even has the advantagem that you don't have to care about the DateTime format. Which can be really annoying.
I'd like to execute a stored procedure on an sql server 2014. The sql server is set up in German, the user used for connecting to the sql server has also configured German as language. If I try to execute the sql procedure or raw sql, I always get the error
varchar cannot be converted to datetime
even if I provide german datetime values. I've found out that it works if I prepend the sql text with the command SET DATEFORMAT dmy.
The problem is the same for ADO .NET as well as Entity framework. Setting the thread and ui culture to German also didn't help.
It seems that C# SQL Connection sets the culture to default (English) independently of thread culture, date format or sql server language.
Any ideas highly appreciated how to set the culture correctly - such that I don't need to send always SET DATEFORMAT dmy before the real sql text.
UPDATE
This is my code to call the sql stored procedure and pass the dates using the c# sql parameter.
SqlConnection sqlConnection = null;
try
{
// open connection to the database
sqlConnection = new SqlConnection(Convert.ToString(ConfigurationManager.ConnectionStrings[ProductivityAnalyzerDatabase.ConnectionStringName]));
sqlConnection.Open();
// setup command
var sqlCommand = new SqlCommand("UpdateEmployeeBalances", sqlConnection);
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.Parameters.Add(new SqlParameter("#employeeId", employeeId));
sqlCommand.Parameters.Add(new SqlParameter("#startDate", startDate));
sqlCommand.Parameters.Add(new SqlParameter("#endDate", endDate));
sqlCommand.ExecuteNonQuery();
}
finally
{
if (sqlConnection != null && sqlConnection.State == ConnectionState.Open)
{
sqlConnection.Close();
}
}
Date values are not stored with their display format.
The problem is that you send your dates to Sql Server as strings, thus forcing sql server to cast the strings to date values. unless you send your dates in ANSI-SQL format (yyyy-mm-dd) this casting might fail or yield unexpected results (is 04/02/2015 April 2nd or February 4th?)
The correct solution, as Steve mentioned in his comment, is to use c#'s DateTime structure as the value of the parameter for the stored procedure. (don't use ToString or anything like that.)
Note that the parameter should be declared as a date type (datetime, datetime2, or date) in the stored procedure itself.
Good day,
You can read more about this issue in this clog:
http://ariely.info/Blog/tabid/83/EntryId/161/Date-displaying-format-vs-Date-storing-format.aspx
in short (from the link above):
Implicit conversion of ambiguous date formats are interpreted according to the language of the connection or the collate of the query. Always keep and following rules, in order to make your work more compatible.
Using .Net you should use a type that is mapped correctly to the SQL Server types. Check this link: https://msdn.microsoft.com/en-us/library/cc716729%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
When you specify dates in DML queries, always use constants way that
are interpreted the same way for all language settings!
for example use format yyyymmdd as 20160227, Use explicit CONVERT statement with an explicit style parameter, Use escape clauses while using ADO, OLE DB, or ODBC.
Remember that those are only display formats. In the database the
data stored in the same way, no matter what is your language!
*datetime is stored as 4 bytes for the date + 4 bytes for the time, Datetime2 is a bit more complex since it is flexible. you can read more on the undocumented internal stored format here.
I hope this is useful :-)
EDIT: I answered my question below, but can't accept it yet.
I'm using C# and SQL2014. I know this question is everywhere and the typical answer is to use the universal format, but that's not what I'm looking for. I have two scenarios. One works and one does not and that is what I am concerned with. Both are using the same stored procedure (albeit in different databases). If I edit the stored procedure to be a command and manually set the parameters to the same thing I am setting them to in C#, both work. Both scenarios are exactly the same except different databases, so here is what I am doing.
cmd = new sqlcommand......
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 60;
cmd.Parameters.AddWithValue("#date", "3/16/2015");
cmd.Parameters.AddWithValue("#startTime", "12:00 AM");
cmd.Parameters.AddWithValue("#endTime", "1:00 AM");
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt); //Error
What is interesting is that it only fails when #date is set to "3/16/2015" I've tried about 6 other dates all around that and it all works fine. That being said, this date works fine on the other database. Does anyone have an idea of what this could be? In the stored procedure, these parameters get set to SMALLDATETIME. If need be, I can try to put some of the stored procedure in here.
Here is the part of the stored procedure that causes the issue to happen:
#date SMALLDATETIME,
#startTime SMALLDATETIME,
#endTime SMALLDATETIME
--[DATE] is a smalldatetime column in the database
WHERE
[DATE] = #date --ERROR HAPPENS BECAUSE OF THIS
EDIT: Sorry for all of the confusion. After more debugging, it looks like the actual problem may be coming from this statement in the procedure:
SELECT
DATEDIFF(mi, '00:00:00', [START]) AS [START],
CASE WHEN [END] = '00:00:00' THEN 1440
ELSE DATEDIFF(mi, '00:00:00', [END]) END AS [END]
.
.
.
This is probably based on the internal date format set up for the databases. I would recommend that you use ISO standard formats in all your code so pass in:
cmd.Parameters.AddWithValue("#date", "2015-03-16");
The String "3/16/2015" is something that will break unless you have hard coded the regional settings in the thread to US English in some fashion.
Have you tried being more specific with the SQL Parameter?
Sorry for the VB Syntax but I'd be guessing the C# equivalent...
Dim dt As Date = DateTime.ParseExact("3/16/2015", "M/d/yyyy", Globalization.CultureInfo.GetCultureInfo("us-en"))
cmd.Parameters.Add(New SqlClient.SqlParameter("#date", dt) With {.SqlDbType = SqlDbType.SmallDateTime})
My issue was using this statement in the procedure:
DATEDIFF(mi, '00:00:00', [END])
[END] column was an nvarchar that had 24:00:00 set as midnight instead of 00:00:00.
Thanks to everyone that helped me debug this.
I have val MyDate in my C# program that contain today-date or null.
I have date field in my access 2007 - TdateOpen
I try to insert to the database like this:
SQL = "insert into MyCount(TdateOpen) values ('" + MyDate +"')";
and I get this error:
Data type mismatch in criteria expression
what can be the problem?
Coz in your SQL statement you are entering date as String . Instead of String it should be a date/date format.
Try to surround by # .
You will need to ensure that the date is in US order (mm/dd/yyyy) or ANSI/ISO order, whether you use dash or slash is not important, ANSI/ISO is to be preferred.
Then as, Madhu CM said, the delimiter for dates in Access is hash (#), however, your date can be null and null cannot be delimited, so you will either have to add the delimiter to a date string, if a date is returned, or use two sql statements, one for null and one for date.
You could SQL parameters instead of dynamically embedding the date value into the statement.
SQL = "insert into MyCount(TdateOpen) values (?)";
var parameter = yourCommand.CreateParameter();
parameter.Value = yourDateTime;
yourCommand.Parameters.Add(parameter);
(DISCLAIMER: The code was not compiled nor tested, but it should give you a hint)
.NET, Java and other high level database API's in various language often provide techniques known as prepared statements and parameter binding as opposed to sending plain text commands to the Database server. What I would like to know is what happens when you execute a statement like this:
SqlCommand cmd = new SqlCommand("GetMemberByID");
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter param = new SqlParameter("#ID", memberID);
para.DbType = DbType.Integer;
cmd.Parameters.Add(param);
I know this is a best practice. SQL injection attacks are minimized this way. But what exactly happens under the hood when you execute these statements? Is the end result still a SQL safe string? If not, what is the end result? And is this enough to prevent SQL injection attacks?
The MySQL manual page on prepared statements provides lots of information (which should apply to any other RDBMS).
Basically, your statement is parsed and processed ahead of time, and the parameters are sent separately instead of being handled along with the SQL code. This eliminates SQL-injection attacks because the SQL is parsed before the parameters are even set.
in layman terms: if a prepared statement is sent then the DB will use a plan if it is available, it doesn't not have to recreate a plan every time this query is sent over but only the values of the params have changed. this is very similar to how procs work, the additional benefit with procs is that you can give permission through procs only and not to the underlying tables at all
If you're using MS SQL, load up the profiler and you'll see what SQL statements are generated when you use parameterised queries. Here's an example (I'm using Enterprise Libary 3.1, but the results are the same using SqlParameters directly) against SQL Server 2005:
string sql = "SELECT * FROM tblDomains WHERE DomainName = #DomName AND DomainID = #Did";
Database db = DatabaseFactory.CreateDatabase();
using(DbCommand cmd = db.GetSqlStringCommand(sql))
{
db.AddInParameter(cmd, "DomName", DbType.String, "xxxxx.net");
db.AddInParameter(cmd, "Did", DbType.Int32, 500204);
DataSet ds = db.ExecuteDataSet(cmd);
}
This generates:
exec sp[underscore]executesql N'SELECT * FROM tblDomains WHERE DomainName = #DomName AND DomainID = #Did',
N'#DomName nvarchar(9),
#Did int',
#DomName=N'xxxxx.net',
#Did=500204
You can also see here, if quotation characters were passed as parameters, they are escaped accordingly:
db.AddInParameter(cmd, "DomName", DbType.String, "'xxxxx.net");
exec sp[underscore]executesql N'SELECT * FROM tblDomains WHERE DomainName = #DomName AND DomainID = #Did',
N'#DomName nvarchar(10),
#Did int',
#DomName=N'''xxxxx.net',
#Did=500204