Transact SQL date query returning no results - c#

From my code, I call an SP using:
using (var cmd = new SqlCommand("sp_getnotes"))
{
cmd.Parameters.Add("#ndate", SqlDbType.SmallDateTime).Value
= Convert.ToDateTime(txtChosenDate.Text);
cmd.CommandType = commandType;
cmd.Connection = conn;
var dSet = new DataSet();
using (var adapter = new SqlDataAdapter { SelectCommand = cmd })
{
adapter.Fill(dSet, "ntable");
}
}
The Stored Procedure itself runs a simple query:
SELECT * FROM tblNotes WHERE DateAdded = #ndate
The problem is no records are returned! DateAdded is a smalldatetime column.
When I change the query to the following, it works:
SELECT * FROM tblNotes WHERE CONVERT(DATETIME, FLOOR(CONVERT(FLOAT, DateAdded))) = #ndate
Why is this happening? This change affects the entire application and I'd like to find the root cause before getting into changing every single query... The only changes we made are to use parameterized queries and upgrade from SQL Server 2005 to 2008.
TIA.

smalldatetime has a time portion which needs to match as well.
Use this:
SELECT *
FROM tblNotes
WHERE dateAdded >= CAST(#ndate AS DATE)
AND dateAdded < DATEADD(day, 1, CAST(#ndate AS DATE))
SQL Server 2008 and above also let you use this:
SELECT *
FROM tblNotes
WHERE CAST(dateAdded AS DATE) = CAST(#ndate AS DATE)
efficiently, with the transformation to a range performed by the optimizer.

SQL Server 2008 now has a DATE data type, which doesn't keep the time porttion like SMALLDATETIME does. If you can't change the data type of the column, then you'll have to truncate when doing the compare, or simply cast to DATE:
SELECT *
FROM tblNotes
WHERE cast(dateAdded as date) = #ndate

I don't know SQL Server but from Oracle experience I'd suspect you're comparing a date time with a date, eg 01/01/2012 01:01:01 against 01/01/2012.

Related

datetime in C# vs, SQL and GETDATE() from SQL Server

I use GETDATE() in a SQL Server stored procedure to insert a date into the SQL Server database table.
After that I need to implement a C# function which is based on datetime input parameter finds if the date was saved in the tables.
The datetime in C# and SQL are different. How do I convert from C# datetime to SQL datetime which has a form of yyyy-mm-ddT:yy:mm:ss.mmm? I need to specify explicitly yyyy-mm-ddT:yy:mm:ss.mmm.
Will be happy for all propositions/possible ways.
DateTime in .Net framework and SQL Server (if it is DateTime type field) is irrespective of the format. Format is only useful for displaying output.
If your field in SQL Server is of DateTime type then you can query it from C# code using parameterized query something like:
public DataTable GetRecords(DateTime dtParameter)
{
DataTable dt = null;
using (SqlConnection conn = new SqlConnection("connection string"))
{
using (SqlCommand cmd = new SqlCommand("SELECT * from yourTable where DateField = #dateparameter"))
{
conn.Open();
cmd.Parameters.AddWithValue("#dateparameter",dtParameter);
SqlDataReader dr = cmd.ExecuteReader();
//...rest of the code
dt.Load(dr);
}
}
return dt;
}
Datetimes between C# and SQL are 100% compatible. The format shouldn't make any difference if you are passing them as DateTimes. If you are generating a SQL string then I would highly recommend changing to SQL Parameters so you don;t have to worry about any formatting issues.
A datetime has no format at all, it has a value. SQL-DateTimes and C# DateTimes are compatible. So don't convert it (to string) at all but pass it as datetime-parameter to the database.
Then you're safe if the DateTime value is within SqlDateTime.MinValue(January 1, 1753) and SqlDateTime.MaxValue(December 31, 9999).
You should never write DateTime.Now from client code to insert into the database as this will be based on the clients local time; do this
public DateTime GetDatabaseTime()
{
var parameter = new SqlParameter("time", SqlDbType.DateTime2)
{
Direction = ParameterDirection.Output
};
using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();
using (var command = new SqlConnection("SELECT #time = SYSDATETIME()", connection))
{
command.ExecuteNonQuery();
}
}
return (DateTime)parameter.Value;
}
Also you should never use DATETIME in SQL Server you should always use DATETIME2 as DATETIME is less accurate than C#::DateTime and it will lead to rounding errors. I know this from bitter experience.
If you are using Entity Framework, and your database is using datetime and not datetime2, the trick is to use SqlDateTime to match the fact that .Net goes to nanosecond, versus sql's millisecond precision. You can use your DateTime variable in .net.. for a SqlDateTime instance, and then you can uniquely identify a record down to the millisecond.
System.Data.SqlTypes.SqlDateTime entry2 = new System.Data.SqlTypes.SqlDateTime(new DateTime(dto.LookUpDateTime));
DateTime entry = entry2.Value;
var existticket = from db in context.Tickets
where db.LookupDateTime == entry && db.UserId == UserId
select db;

SqlCommand timeout even though in SQL Studio same query is fast

I have what I thought was a simple query that I execute from my little log-processing application. The aim of this method is to simply get the highest date value out of the log table:
private DateTime GetLastEntryDate(string serverName, string siteName)
{
DateTime dt = DateTime.MinValue;
using (var con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["LogParserDB"].ConnectionString))
{
con.Open();
using (var cmd = new SqlCommand("SELECT MAX(date) FROM iislogs WHERE host=#Host AND site=#Site", con))
{
cmd.CommandTimeout = 120;
cmd.Parameters.AddWithValue("Host", serverName);
cmd.Parameters.AddWithValue("Site", siteName);
var result = cmd.ExecuteScalar();
if (result != DBNull.Value)
{
dt = (DateTime)result;
}
}
}
return dt;
}
There are some indexes on the table, but I'm not sure if that's relevant, because the problem I'm getting is that when I run this code, it throws a timeout after 2 minutes on the ExecuteScalar line.
If I copy and paste that query into SSMS with the same parameters, it completes in 00:00:04, or even 00:00:00 (if I've just updated stats).
SELECT MAX(date) FROM iislogs WHERE host='servername' AND site='W3SVC1'
I have checked for blocking, and I can't see anything like that - that database is only being accessed by this one app, and it's not multi-threaded or anything like that.
Update:
Interestingly, when I run the exact query as captured by Profiler, it also takes a long time in SSMS:
exec sp_executesql N'SELECT MAX(date) FROM iislogs WHERE host=#Host AND site=#Site',N'#Host nvarchar(13),#Site nvarchar(6)',#Host=N'servername',#Site=N'W3SVC1'
The actual columns are varchar(50) and varchar(10) respectively.
The query you execute in SSMS
SELECT MAX(date)
FROM iislogs
WHERE host = 'servername'
AND site = 'W3SVC1'
Is not the same as the one executed by your application.
EXEC sp_executesql
N'SELECT MAX(date) FROM iislogs WHERE host=#Host AND site=#Site',
N'#Host nvarchar(13),#Site nvarchar(6)',
#Host=N'servername',
#Site=N'W3SVC1'
The first one has varchar string literals. The second one has nvarchar parameters. Your column datatypes are in fact varchar.
nvarchar has higher datatype precedence than varchar so you are forcing an implicit cast of the column. This will render any indexes on the column useless.
Change the parameter datatypes in the application to varchar

DateTime from .NET to smalldatetime in SQL - how to do queries?

I have a DateTime component in my code, and I want to use it for a query in my SQL Server database.
When inserting this component, there seems to be no problem, but when querying for smalldatetime values, I just don't know how to do it. The dataset is always empty.
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "ReadDates";
dataset = new DataSet();
SqlParameter parameter = new SqlParameter("#date", SqlDbType.SmallDateTime);
parameter.Value = DateTime.Now();
cmd.Parameters.Add(parameter);
dataAdapter = new SqlDataAdapter(cmd);
dataAdapter.Fill(dataset);
return dataset;
And this is in my stored procedure:
select * from TableDates
where ValueDate <= #date
So I have no problems running the procedure in SQL Server Management Studio, when entering a parameter in this format: '2000-03-03 04:05:01', but when passing a DateTime, the query is always empty. Any suggestions?
I tried it by using SQL Server 2008 R2 Express.
Here is the example stored procedure i wrote:
CREATE PROCEDURE [dbo].[ShowGivenSmallDateTimeValue]
#givenSmallDateTime smalldatetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Simply return the given small date time value back to sender.
SELECT #givenSmallDateTime
END
And here is the C# code to execute the procedure:
var connectionBuilder = new SqlConnectionStringBuilder();
connectionBuilder.DataSource = "localhost\\sqlexpress";
connectionBuilder.IntegratedSecurity = true;
var now = DateTime.UtcNow;
using (var connection = new SqlConnection(connectionBuilder.ConnectionString))
using (var command = new SqlCommand())
{
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "ShowGivenSmallDateTimeValue";
command.Parameters.Add(new SqlParameter("#givenSmallDateTime", SqlDbType.SmallDateTime) { Value = now });
connection.Open();
var result = (DateTime)command.ExecuteScalar();
var difference = result - now;
Console.WriteLine("Due to the smalldatetime roundings we have a difference of " + difference + ".");
}
And it simply works.
Here's my code for creating the SqlParameter for a Datetime; For SQL Server 2008 we pass the value as datetime2 since SQL will implicity convert from datetime2 to every other date type so long as it is within the range of the target type...
// Default conversion is now DateTime to datetime2. The ADO.Net default is to use datetime.
// This appears to be a safe change as any datetime parameter will accept a datetime2 so long as the value is within the
// range for a datetime. Hence this code is acceptable for both datetime and datetime2 parameters, whereas datetime is not
// (because it doesn't handle the full range of datetime2).
SqlParameter sqlParam = new SqlParameter(name, SqlDbType.DateTime2);
Since Your parameter includes zeros in day and month parts...sql server converts it but doest match to your date.... i.e.,
if DATETIME.now() returns '2000-03-03 04:05:01'... it is casted into 2000-3-3 Without including zeros...so u need to specify zeros also to match your date.

Search datetime in MySQL

I have a MySQL database, there's a table which have column Time's Type is Nvachar(50) and its values is kind like this "05/09/2012 20:53:40:843" *(Month-date-year hour:mins:second:msecond)*
Now I want to query to get a record have Time after "10/05/2012 01:00:30 PM".
I had code in C# to converted it to "05/10/2012 13:00:30" before making a query.
My Query :
SELECT * FROM ABCDFEGH WHERE capTime > '05/10/2012 13:00:30' LIMIT 0, 1
But i got no record. So please tell me how can I can make it return record have time after the time above ???
More Info My C# code :
string tableName = "ABCDFEGH";
string date = "05/10/2012 13:00:30";
var query = "SELECT * FROM " + tableName + " WHERE capTime > '" + date + "' LIMIT 0, 1";
var cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = null;
try
{
dataReader = cmd.ExecuteReader();
}
I'm so so so so so so sorry. I made a mistake the query must be
SELECT * FROM ABCDFEGH WHERE capTime > '05/10/2012 13:00:30' LIMIT 0, 1
This query is successful return the record i need :)
But soemhow I have mistyped it into
SELECT * FROM ABCDFEGH WHERE capTime > '05-10-2012 13:00:30' LIMIT 0, 1
Sorry again, topic close. But tks for evveryone tried :)
I recommend using the DATETIME datatype instead of NVARCHAR. Store dates in YYYY-MM-DD HH:MM:SS format, which is the native DATETIME format recognized by MySQL.
Also use date literals in the same format.
Two reasons for this recommendation: First, DATETIME takes only 8 bytes, instead of up to 150 bytes which is the potential size of a multibyte 50 character varchar.
Second, the sort order of DATETIME will be the same as the chronological order. So if you create an index on the Time column, your > comparison can benefit from the index. Your query will be much faster as a result.
Use TIMESTAMPDIFF()
Schema
CREATE TABLE ABCDFEGH (`right` varchar(3), `time` datetime);
INSERT INTO ABCDFEGH (`right`, `time`)
VALUES
('Yes', '2012-10-02 13:00:30'),
('No', '2012-10-15 13:00:30');
SQL Code
SELECT * FROM ABCDFEGH
WHERE TIMESTAMPDIFF(MINUTE, time, '2012-10-05 13:00:30') > 0
LIMIT 0, 1
Explanation
TIMESTAMPDIFF() returns datetime_expr2 – datetime_expr1, where datetime_expr1 and datetime_expr2 are date or datetime expressions. One expression may be a date and the other a datetime; a date value is treated as a datetime having the time part '00:00:00' where necessary. The unit for the result (an integer) is given by the unit argument.
Fiddle: http://www.sqlfiddle.com/#!2/244cc/1 datetime
Fiddle: http://www.sqlfiddle.com/#!2/063b3/1 varchar(50)
PS1: Time may be a reserved word. Please avoid using it. Else use it with backticks (`).
PS2: The format of time is YYYY-MM-DD not the reverse.
First, why did you save the dates as NVARCHAR? If you are still able to change it to DATETIME datatype and all of the records on it, much better.
But if not, you can use STR_TO_DATE.
SELECT *
FROM tableName
WHERE STR_TO_DATE(`capTime`, '%m/%d/%Y %H:%i:%s:%x') >
STR_TO_DATE('05/10/2012 13:00:30', '%c/%d/%Y %H:%i:%s')
See SQLFiddle Demo
SOURCES
STR_TO_DATE
DATE Formats
UPDATE 1
and your query is vulnerable with SQL Injection. To avoid from it
Parameterized your query
code snippet,
string tableName = "ABCDFEGH";
string date = "05/10/2012 13:00:30";
String query = "SELECT * FROM " + tableName + " WHERE STR_TO_DATE(`capTime`, '%m/%d/%Y %H:%i:%s:%x') > STR_TO_DATE(#dateHere, '%c/%d/%Y %H:%i:%s')";
using (MySqlConnection connection = new MySqlConnection("connectionStringHere"))
{
using (MySqlCommand command = new MySqlCommand())
{
command.Connection = connection;
command.CommandType = CommandType.Text;
command.CommandText = query;
command.Parameters.AddwithValue("#dateHere",date)
MySqlDataReader dataReader = null;
try
{
dataReader = cmd.ExecuteReader();
}
catch(MySqlException e)
{
// do something here
// don't suppress the error
}
}
}

Select oracle date column using C#

I am trying to select data from my Oracle database BY DATE using C#. However I am always getting an empty data set although the same query string works just fine in Oracle SQL Developer
String Query = "Select position_date from position";
OracleDataAdapter adapter = new OracleDataAdapter(Query, ocon);
adapter.Fill(ds, "table"); //where ds is a dataset
PrintDataSet(ds);
returns
3/8/2011 12:00:00 AM.... and more
However, when I change my query to below, then there is no output!
String Query = "Select position_date from position
where to_char(position_date, 'mm-dd-yyyy') = '05-17-2012'"
This query works fine in oracle sql developer. I've also tried trunc(sysdate) but nothing seems to work! :(
select * from position where trunc(position_date) = to_date('05-17-2012', 'mm-dd-yyyy')
worked.
Thanks.
If your dates have no time component (and if that is so then guarantee it with a check constraint), then:
Select position_date
from position
where position_date = date '2012-05-17'
Otherwise:
Select position_date
from position
where position_date >= date '2012-05-17' and
position_date < date '2012-05-17' + 1

Categories