I have a table:
CREATE TABLE [Lines] (
[Value] TEXT NOT NULL,
[AddedOn] TIMESTAMP DEFAULT CURRENT_TIMESTAMP NULL
)
As you can see, the AddedOn column is a timestamp and is set to record the current datetime if one is not provided at insert time.
Please consider the following c# code:
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "INSERT INTO Lines(Value) VALUES (#Value)";
cmd.Parameters.AddWithValue("#Value", objectValue);
cmd.ExecuteNonQuery();
}
Note that above I am letting SQLite assign the date. Now, the same code, except I am passing the AddedOn value (e.g. DateTime.Now - right now)
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "INSERT INTO Lines(Value, AddedOn) VALUES (#Value, #AddedOn)";
cmd.Parameters.AddWithValue("#Value", objectValue);
cmd.Parameters.AddWithValue("#AddedOn", DateTime.Now);
cmd.ExecuteNonQuery();
}
If I then compare the results of these 2 inserts, I find that when I let the AddedOn default kick in (first example), it saved the current datetime at the GMT. When I passed the date explicitly (2nd example), it saved the actual current datetime in my timezone.
Is this by design? Is it a bug? It seems like the behavior should be consistent and the datetime I pass in should be converted to GMT.
Is it a bug?
Not sure, but I'd be more surprised if this didn't accomplish your goal:
cmd.Parameters.AddWithValue("#AddedOn", DateTime.UtcNow);
To me, the behavior you're experiencing makes sense.
I wouldn't imagine a TIMESTAMP column would have any information on whether a time is expected to be in UTC or not, and I certainly wouldn't expect it to force UTC by default.
This will also make for better perf, because time zone conversions are (relatively) expensive, and the automated conversion would be a hidden mechanism.
Related
I want the current day, month and year in inserted in my database.
The format needs to be: YYYY-MM-DD. How to do this? I use de datatype 'date' in my table. It has to be the same value as what it is in the database. I use C#.
Now I get the error: 'Error converting data type nvarchar to date'
Code:
string datenow = DateTime.Now.ToString("yyyy-mm-dd");
I use a Stored Procedure for adding the date value (and some other things):
conn.Open();
SqlCommand cmd = new SqlCommand("spAddContentment", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#question", SqlDbType.VarChar, 220);
cmd.Parameters.AddWithValue("#employeeid", Variabels.employeeid);
cmd.Parameters.AddWithValue("#score", SqlDbType.Char).Value = score;
cmd.Parameters.AddWithValue("#comment", SqlDbType.VarChar).Value = TextBxComment.Text;
cmd.Parameters.AddWithValue("#date", SqlDbType.Date).Value = datenow;
cmd.ExecuteNonQuery();
replace
cmd.Parameters.AddWithValue("#date", SqlDbType.Date).Value = datenow;
with
cmd.Parameters.AddWithValue("#date", SqlDbType.Date).Value = DateTime.Now;
since
Now I get the error: 'Error converting data type nvarchar to date'
says that you've tried to insert a string but the procedure expects a date.
If you want to skip the time part, you can use DateTime.Now.Date or DateTime.Today
The format needs to be: YYYY-MM-DD
Noooooooo!!
A date here should be stored as a typed value - perhaps of type date (no time part) or datetime. Now; here's the thing: a date value has no format. It is essentially just a number. It is simply incorrect to even ask the question "what (text) format is my date stored as", in the same way that it would be incorrect to ask what (text) format an int is stored as. Quite simply: it isn't, because it isn't text.
If you are storing dates (or integers) as text (in some kind of [n][var]char(...) column, for example): that is a problem, and can lead to huge confusions, problems, and inefficiencies - including problems with sorting, filtering, and i18n/l10n problems.
Instead: declare the column as date or datetime, and use a typed value from .NET to populate it, for example passing down a SQL parameter with a value that is a .NET DateTime. The ADO.NET SqlClient layer knows how to connect those things, and all the right magic will happen.
Only when you are actually displaying a date in some way does it become correct to ask about the format. It is, for example, perfectly correct to ask:
I have a DateTime value that I got from the database; what display format should I use in my web-page to display it?
The important point being : it is now a display concern, not a storage concern.
I am using the npgsql package to pass parameters to a postgresql function. But I am getting exception saying that a function with the specified number/type of arguments is not defined. I went throught the trouble of testing all the parameters and I am sure the one that is causing the problem is the c# datetime parameters that is passed to a postgresql date data type.
I orginally tried this:
//here BirthDate is Datetime, as it doesn't seem
// to have another built-in date type in asp.net core
cmd.Parameters.AddWithValue("#birth_date", cliente.BirthDate);
I read some post here in SO and they said that using the property Date would solve but it didn't work for me.
//doesn't work either
cmd.Parameters.AddWithValue("#birth_date", cliente.BirthDate.Date);
NpgSql's AddWithValue does its best to map the datatype of the C# property to the PostgreSQL field's datatype, but the issue is that PostgreSQL has two primary datatypes for date:
date
timestamp
But C# has just the one -- System.DateTime. So even the .Date Property of a DateTime object yields a DateTime type.
In other words, NpgSql has to make a choice -- and it renders the PostgreSQL datatype as a timestamp. If your DB type is actually a date, the execution will fail due to datatype mismatch.
For strings, integers, decimals and doubles AddWithValue always seems to work exactly as expected, but if your date is a [PostgreSQL] DATE then you need to be explicit with your parameter declaration's datatype. In general, this is a good practice anyway:
cmd.Parameters.Add(new NpgsqlParameter("#birth_date", NpgsqlTypes.NpgsqlDbType.Date));
cmd.Parameters[0].Value = cliente.BirthDate;
This is definitely advantageous over AddWithValue if you are doing multiple transactions like this:
cmd.Parameters.Add(new NpgsqlParameter("#birth_date", NpgsqlTypes.NpgsqlDbType.Date));
cmd.Parameters.Add(new NpgsqlParameter("#user_id", NpgsqlTypes.NpgsqlDbType.Integer));
foreach (User u in Users)
{
cmd.Parameters[0].Value = u.Birthday;
cmd.Parameters[1].Value = u.UserId;
cmd.ExecuteNonQuery();
}
For a single query or transaction, you can also use the Shorthand:
cmd.Parameters.Add(new NpgsqlParameter("#birth_date", NpgsqlTypes.NpgsqlDbType.Date)).
Value = cliente.BirthDate;
As a final alternative, you can "fix" the dbtype after the fact:
cmd.Parameters.AddWithValue("#birth_date", cliente.BirthDate);
cmd.Parameters[0].NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Date;
I don't think that's any easier than the other options, but it is an option that will work.
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 asked this question in many sites and my question remain unanswered. Some people advise me to use datetimepicker against maskedtextbox.
It is true that datetimepicker solved the all kind date related problem, whereas masked textbox return a string and that's why it's create a datetime conversion problem in parameterized sql query in C#.
In most case we are not utilise datetimepicker due to time consuming issue. I mean if there is thousand of data entry pending and if we use datetimepicker then over finger are divided between mouse and keyboard. Hence in my case I always use maskedtextbox and it creates a problem of date conversion. I have tried to solve it in the following way:
String sql="insertintodummy(name,date)values(#name,convert(datetime,'"+maskedTextBox1.text+"', 103)"; // for 'dd/mm/yyyy' format.
sqlcommand cmd=new sqlcommand(sql,con);
cmd.parameters.Add("#name",SqldbType.Varchar).Value= textbox1.text;
cmd.ExecuteNonQuery();
I think there is no way to utilise the above datetime conversion in a parameterized query with C#, VS-2005.
The above code is useful in case of only datefield must enter way. If there is better way than please suggest.
Now it is perfect Solution here below.
string sql="insert into dummy(name,date)values(#name,#date)";
IFormateprovider Culture = new CultureInfo("fr-FR",True);
DateTime mydate=DateTime.parse(
maskedtextbox1.text,Culture,DateTimeStyles.NocurrentDateDefault
);
sqlcommand cmd=new sqlcommand(sql,con);
cmd.Parameters.Add(#name,SqlDbtypes.Varchar).Values= Textbox1.text;
cmd.Parameters.Add(#date, SqlDbtypes.Datetime).Values=mydate;
cmd.ExecuteNonQuery();
Thanks.
Why do the conversion in Sql, (and risk injection by only partially parameterising your query) when there's a perfectly good parameter with SqlDbType.DateTime just begging to be used:
string sql = "insert into dummy (name, date) values (#name, #date)";
SqlCommand cmd = new SqlCommand(sql, con);
cmd.Parameters.Add("#name", SqldbType.Varchar).Value = textbox1.text;
cmd.Parameters.Add("#date", SqlDbType.DateTime).Value = Convert.ToDateTime(maskedTextBox1.Text);
cmd.ExecuteNonQuery();
Obvious caveats:
No check that maskedTextBox1.Text actually contains a DateTime (DateTime.TryParse)
No check that the provided DateTime falls in the range of DateTime's that SqlDbType.DateTime handles
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."