I have the following command, used in a C# WinForms app that uses OleDb to connect to a Access 2010 database:
oc_payslips = new OleDbCommand("SELECT <fields> FROM Payslips WHERE LicenseID = \"" + IDs[cb_Employees.SelectedIndex] + "\" AND DateOfPayment >= \"" + startDate + "\" AND DateOfPayment <= \"" + endDate + "\"", DB_Connection.con);
This doesn't work. My best guess is that I cannot compare two strings like that using SQL.
The idea is to get the records that have a date between two dates, all of which have the "dd/MM/yyyy" format. The date is stored as a string in the database.
I couldn't find the answer to this on the internet, so here is my question:
Is there a way to compare two strings using SQL and determine which is alphabetically first?
P.S.: I know I can get all the dates first, compare them and then search for the IDs which have a correct date but my question is related to doing this in a single SQL query.
You have several problems
You should used parametrized commands instead of using string concatenation.
You are using double quotes instead of single quotes as string delimiters in SQL.
You are comparing dates as strings. If the table field if of type Date/Time, you would have to use a date litterals (if you persist in using string concatenation). If the dates are stored as strings formatted like "dd/MM/yyyy" the comparison will not work.
Same thing with LicenseID. If it is a numeric type compare LicenseID = 123 not LicenseID = "123".
The three last problems automatically disappear, if you use parametrized queries.
See: How to: Execute a Parameterized Query on MSDN.
oc_payslips = new OleDbCommand(
#"SELECT <fields> FROM Payslips
WHERE LicenseID = #lid AND
DateOfPayment >= #start AND DateOfPayment <= #end", DB_Connection.con);
oc_payslips.Parameters.AddWithValue("#lid", IDs[cb_Employees.SelectedIndex]);
oc_payslips.Parameters.AddWithValue("#start", startDate);
oc_payslips.Parameters.AddWithValue("#end", endDate);
...
It is a bad idea to store the dates as string in the database. If you want to compare dates stored as strings, it will only work if the strings are formatted as "yyyy/MM/dd" as Vlad Schnakovszki has pointed out in his comment. However, you could try to use
"... CDate(DateOfPayment) BETWEEN #start AND #end"
and make sure that you pass parameters of type DateTime.
http://www.tutorialspoint.com/sql/sql-string-functions.htm#function_strcmp
afaik if it returns -1 than the first string would be before the second using english alphabet
Related
I am vb.net newbie and working on a program which will be used as a daily-worklog. As backend I use MS ACCESS. I store the "datetime.utc.now" time in a field (type:date/time) of MS Access.
This is shown in the database like: dd.mm.yyyy hh:mm:ss
I want to see all entered items of the last 12 hours. I used many different ways, but I´m not able to fix it.
My preferred / logical (for me :-)) way to do this was:
add the parameter:
mycommand.SelectCommand.Parameters.AddWithValue("date12",OleDbType.DBTimeStamp).Value = DateTime.UtcNow.AddHours(-12)
Query the database
select * from complaints where entrydate >= #date12;
But I can't figure out why it doesn't work.
Failure message = "data types in criteria expression incompatible"
I assume the problem is the different time formats, but I'm not sure and I have no clue how I could fix it.
MS Access does not use named parameters. You use a ? for all of the placeholders in the SQL statement. You still can and should give the parameter object a name, but the value is matched to the placeholder based on position in the Parameters collection and query string rather than name.
SQL:
"select * from complaints where entrydate >= ?;"
VB:
mycommand.SelectCommand.Parameters.Add("date12",OleDbType.Date).Value = DateTime.UtcNow.AddHours(-12)
Do NOT settle for hard-coding the parameter value. What you can do is use SQL expressions to determine the date value, and avoid both parameters and string concatentation:
select * from complaints where entrydate >= DATEADD('h', -12, Now())
You can change the type to OleDbType.Date or hardcode the query:
select * from complaints where entrydate >= ( Now() - 0.5 )
Trouble inserting DateTime into Access with OleDb
As a side note, most value types are generally safe to hardcode:
"select * from complaints where entrydate >= " & DateTime.UtcNow.AddHours(-12).ToOADate()
In my SQL WHERE caluse, I'm checking to see if a Report Date is in one of the list of dates which I am passing to my SQL stored procedure.
WHERE REPORT_RUN_DATE IN (#REPORT_RUN_DATES)
Let's say #REPORT_RUN_DATE IS EQUAL TO '11/09/2013'
That did not match (no records returned) so then, looking at the compare, I'm comparing a date field with a date that has already been converted to a string before being passed into the stored procedure. So then I tried.
WHERE CONVERT(VARCHAR, REPORT_RUN_DATE, 101) IN (#REPORT_RUN_DATES)
Same issue. No match. No records returned. The reason why the dates are passed in as a string is there may be times I'll be passing in multiple dates e.g. ''11/09/2013','11/14/2013'' which is why I am using the IN clause. We do not store any time portions of the date so I'm only dealing with the date data type and not datetime or smalldatetime.
Most of examples of using the IN CLAUSE in T-SQL that I found had to do with integers or strings but not dates. I'm passing my parameters via ADO.NET using VB.Net 2012. Stepping through my code I know the values are passed correctly and that the values should return a result set.
Any advise on how to proceed would be greatly appreciated...
You can't just pass in multiple values like that. You'll end up passing a string as a single value, then SQL will compare the date column as a string to the value passed in:
Here are some options:
Use multiple date parameters (2?, 3?)
Create a table-value parameter type for the stored procedure
Call the sproc multiple times with different dates (loop in your VB code)
Generate SQL in VB instead of calling a sproc (need to be cautious of SQL injection)
reverse the comparison and use LIKE:
WHERE #REPORT_RUN_DATES LIKE '%' + CONVERT(DATE, REPORT_RUN_DATE, 101) + '%'
For example, I'm trying to combine "String1" "String2" and "String3" to read as "String1 / String2 / String3". Then I'd like to convert that string to a date as each of my three string variables are month, day, and year saved separately.
I'm trying to do something like the following:
SELECT *, CONVERT(DATETIME, CONVERT(VARCHAR, month + "/" + day + "/" + year), 101) AS ActualDate
I actually have a functional page already connected to a database. I'm trying to add additional search features, and for that I need to be able to compare an actual date with search parameters when all I have are three varchars. What I'm looking for is how to convert those three varchars in to one string, and then convert that to a date in the SQL. The code example I used above does not work when added to the SQL statement. I don't' know if it's a simple syntax error, or if this isn't even the correct way to go about making the date.
In mysql try looking at the STR_TO_DATE() command. Also you have to use concat() in mysql you cannot use the + operand.
STR_TO_DATE(concat(month,'/',day,'/',year), '%m/%d/%Y')
EDIT:
If you are using sql server change the "/" to '/' in your original question and it will work.
I have the following code:
"SELECT top 1 * FROM CensusFacility_Records WHERE Division_Program = 'Division 1' AND JMS_UpdateDateTime = '" & date & "'"
The date format in column JMS_UpdateDateTime is:
8/22/2013 12:00:07 AM
How can I make sure that my "date" in the query is converted to the correct time format?
My date variable in my SQL query is a real/date time. I would like for it to match the format within the JMS_UpdateDateTime field.
If your database table is small enough, you can cast the value to an actual datetime inside your query, and pass the value in as a datetime parameter, so you're comparing dates instead of comparing strings.
If your table has a decent amount of records, don't do this, because it will be a performance hog.
SELECT top 1 *
FROM CensusFacility_Records
WHERE Division_Program = 'Division 1'
AND cast(JMS_UpdateDateTime as datetime) = #dateParam
I believe SQL Server will be able to read the string that's in your database and automatically cast it properly, assuming your server settings are standard.
But in any case, use parameterized SQL instead of passing in a string like you've got.
The format of your SQL DateTime is actually a bit of a red herring here - it can be displayed in any way the front end (e.g. Management Studio) chooses. The important thing here is that your date variable is in an unambiguous format. With this in mind I'd recommend using the ISO 8601 date/time format, e.g. date.ToString("o") (assuming date is a DateTime).
I've been tasked to take a calendar date range value from a form front-end and use it to, among other things, feed a query in a Teradata table that does not have a datetime column. Instead the date is aggregated from two varchar columns: one for year (CY = current year, LY = last year, LY-1, etc), and one for the date with format MonDD (like Jan13, Dec08, etc).
I'm using Coldfusion for the form and result page, so I have the ability to dynamically create the query, but I can't think of a good way to do it for all possible cases. Any ideas? Even year differences aside, I can't think of anything outside of a direct comparison on each day in the range with a potential ton of separate OR statements in the query. I'm light on SQL knowledge - maybe there's a better way to script it in the SQL itself using some sort of conversion on the two varchar columns to form an actual date range where date comparisons could then be made?
Here is some SQL that will take the VARCHAR date value and perform some basic manipulations on it to get you started:
SELECT CAST(CAST('Jan18'||TRIM(EXTRACT(YEAR FROM CURRENT_DATE)) AS CHAR(9)) AS DATE FORMAT 'MMMDDYYYY') AS BaseDate_
, CASE WHEN Col1 = 'CY'
THEN BaseDate_
WHEN Col1 = 'LY'
THEN ADD_MONTHS(BaseDate_, -12)
WHEN Col1 = 'LY-1'
THEN ADD_MONTHS(BaseDate_, -24)
ELSE BaseDate_
END AS DateModified_
FROM {MyDB}.{MyTable};
The EXTRACT() function allows you to take apart a DATE, TIME, or TIMESTAMP value.
You have you use TRIM() around the EXTRACT to get rid of the whitespace that is added converting the DATEPART to a CHAR data type. Teradata is funny with dates and often requires a double CAST() to get things sorted out.
The CASE statement simply takes the encoded values you suggested will be used and uses the ADD_MONTHS() function to manipulate the date. Dates are INTEGER in Teradata so you can also add INTEGER values to them to move the date by a whole day. Unlike Oracle, you can't add fractional values to manipulate the TIME portion of a TIMESTAMP. DATE != TIMESTAMP in Teradata.
Rob gave you an sql approach. Alternatively you can use ColdFusion to generate values for the columns you have. Something like this might work.
sampleDate = CreateDate(2010,4,12); // this simulates user input
if (year(sampleDate) is year(now())
col1Value = 'CY';
else if (year(now()) - year(sampleDate) is 1)
col1Value = 'LY'
else
col1Value = 'LY-' & DateDiff("yyyy", sampleDate, now());
col2Value = DateFormat(sampleDate, 'mmmdd');
Then you send col1Value and col2Value to your query as parameters.