executing SELECT statement with date in WHERE clause fails - sql-server

I'm building a dynamic query in my ASP.NET MVC project by the following:
Dim queryString As String = "SELECT VALUE userInfos FROM MyDBEntities.UserInformations AS userInfos"
If strWhere <> "" Then
queryString = queryString & " WHERE " & strWhere
End If
' Call the constructor with the specified query and the ObjectContext.
Dim SearchUsersQuery As New System.Data.Objects.ObjectQuery(Of UserInformation)(queryString, MyDB)
Dim lstOfUsers As List(Of UserInformation) = SearchUsersQuery.ToList
Where basically the strWhere is a string that I build up a dynamic filter depending on what the user selects to search on.
This works great until I need to add a date comparison to the date clause.
I'm trying the following:
strWhere = " userInfos.BirthDate <= " & StartDateForQuery.ToShortDateString
Which will end up as:
"SELECT VALUE userInfos FROM MyDBEntities.UserInformations AS userInfos Where userInfos.BirthDate <= 10/09/1992"
But when i try to execute the query with the ToList whenever a date is in the where string i get the following error:
The argument types 'Edm.DateTime' and 'Edm.Int32' are incompatible for this operation. Near WHERE predicate, line 1, column 103.
Any ideas on what my issue is?
Thanks in advance

You can't compare dates that way.
When you do this:
"SELECT VALUE userInfos FROM MyDBEntities.UserInformations AS userInfos
WHERE userInfos.BirthDate <= 10/09/1992"
10/09/1992 is being interpreted as an Int value.
Try putting single quotes around this value as in:
"SELECT VALUE userInfos FROM MyDBEntities.UserInformations AS userInfos
WHERE userInfos.BirthDate <= '10/09/1992'"
Probably you'll have to call a database date conversion function (depends on your database vendor) passing to it this date string.
Like this:
"SELECT VALUE userInfos FROM MyDBEntities.UserInformations AS userInfos
WHERE userInfos.BirthDate <= DataBaseSpecificToDateFunction('10/09/1992')"
The problem is that this query is being sent to the database and is the database server that'll execute it. That's why you need a database specific date conversion function.
For example: in Oracle we have the to_date function to convert a string to a datetime using a given pattern:
to_date('1998/05/31:12:00:00AM', 'yyyy/mm/dd:hh:mi:ssam')
In SQL Server we have the convert function as in:
convert(datetime, '2016-10-23 20:44:11',20) -- yyyy-mm-dd hh:mm:ss(24h)
More samples here.

Why don't you use the next code:
Dim queryString As String = "SELECT VALUE userInfos FROM MyDBEntities.UserInformations AS userInfos"
' Call the constructor with the specified query and the ObjectContext.
'
Dim SearchUsersQuery As New System.Data.Objects.ObjectQuery(Of UserInformation)(queryString, MyDB)
'verify if should be a startdate for adding to query
'
If StartDateForQuery <> "" Then
'add the condition to the query
'
SearchUsersQuery = SearchUsersQuery.Where("it.BirthDate <= #BirthDate ")
'add the parameter to be used
'
SearchUsersQuery.Parameters.Add(New ObjectParameter("BirthDate ", StartDateForQuery))
End If
Dim lstOfUsers As List(Of UserInformation) = SearchUsersQuery.ToList
You make use of the linq capabilities to generate queries (it "knows" how to generate the datetime parameter for DB query).
Check a sample here

Related

Dcount A Parameterised Query Access

Beginner at access, so sorry if this is a question that has been asked before (I've searched for ages, so maybe im searching for the wrong thing?). Anyway, in my database I have a form that is used to submit records, and a query that checks for double bookings (it shows all records that overlap with the inputted dates). I have created a 'submit record' button on the form, and all I am trying to do is validate that there are no double bookings by running the double booking query and checking if there are no records.
I have tried using a Dcount function for this, however I cannot seem to find how to run the query as it has parameters (I need to pass the inputs of the form to the query). I am unsure if this is the most efficient way to check for double bookings, but I just need a solution what works at the moment :P. This is my current code, which obviously doesnt work as the sql query requires parameters:
If DCount("*","Double Booked")=0 Then ...
(Where 'Double Booked' is the name of my query in the database)
Sorry if I was unclear, thanks in advance.
EDIT: Here is the double booked query code:
SELECT *
FROM Booking
WHERE (
([Your VanID] = [Booking].[VanID])
AND (
( ([Your Collection Date] >= [Booking].[Collection date]) AND ([Your Collection Date] <= [Booking].[Return date]))
OR ([Your Return Date] >= [Booking].[Collection date]) AND ([Your Return Date] <= [Booking].[Return date])
OR (([Your Collection Date] <= [Booking].[Collection date]) AND ([Your Return Date] >= [Booking].[Return date]))
)
);
If you only want to know if there are double bookings (not how many), DCount is unnecessary. Opening a recordset is enough.
Queries with form fields as parameters run fine when opened directly, or as a RecordSource, but not when opened in VBA.
To be able to do this, I have this function in a public module:
Public Sub EVal_Params(QD As DAO.QueryDef)
On Error GoTo EVal_Params_Err
Dim i As Integer
Dim par As DAO.Parameter
For i = 0 To QD.Parameters.Count - 1
Set par = QD.Parameters(i)
' This is the key line: Eval "evaluates" the form field and gets the value
par.Value = Eval(par.Name)
Next i
EVal_Params_Exit:
On Error Resume Next
Exit Sub
EVal_Params_Err:
MsgBox Err.Description, vbExclamation, "Runtime-Error " & Err.Number & " in EVal_Params"
Resume EVal_Params_Exit
End Sub
With that you can open a recordset on the query, and its .EOF property will tell you whether there are double bookings:
Dim DB As DAO.Database
Dim QD As DAO.QueryDef
Dim RS As DAO.Recordset
Set DB = CurrentDb
Set QD = DB.QueryDefs("Double Booked")
' Get form field values into query parameters
Call EVal_Params(QD)
Set RS = QD.OpenRecordset(dbOpenSnapshot)
If RS.EOF Then
' no doubles
Else
' there are double bookings
End If
RS.Close
Edit
If the query parameters are not references to form controls, but "normal" named parameters, you'd do instead:
Set QD = DB.QueryDefs("Double Booked")
QD.Parameters("Your VanID") = someValue
QD.Parameters("Your Collection Date") = someOtherValue
Set RS = QD.OpenRecordset(dbOpenSnapshot)

Clone the value of a DATETIME column using arrays?

I wrote the function below to get the values of two columns in a database, one is composed by integers (ID) and other dates/times in DATETIME format, in SQL Server 2008 R2. It stores the two values in two distinct arrays (lists), defined here:
Dim arrPartIDs As New List(Of Integer)
Dim arrPartUMDates As New List(Of Date)
My goal is to clone the datetime value of each row to the column 'Part_Previous_UMDate', which are currently set as NULL.
However, when my code execute the line:
WinToolSQLCmd.ExecuteReader()
After
WinToolSQLCmd = New SqlCommand("UPDATE WTData.dbo.Parts SET Part_Previous_UMDate = '" & arrPartUMDates.Item(intUMDateCounter) & "' WHERE ID = " & PartID.ToString, WinToolConnection)
The application returns an exception
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
I thought that by creating the array (list) arrPartUMDates as a list of date I could simply transfer its values back to the database, but apparently they are created as strings when added to the array...
What's the best approach to clone the DATETIME value in UMDate to Part_Previous_UMDate with full precision? I need to have full precision because later I´ll compare the values of the two columns in order to determine if they need an update.
Any ideas? I've searched for this error message but could not find anything related to dealing with dates in arrays...
Image of table here: http://i.stack.imgur.com/BYT1j.png
Code:
Function MirrorUMDateInPartsTable()
Dim arrPartIDs As New List(Of Integer)
Dim arrPartUMDates As New List(Of Date)
Dim WinToolConnection As New SqlConnection(StrGlobalWinToolConnection)
Dim intUMDateCounter As Integer = 0
WinToolSQLCmd = New SqlCommand("SELECT TOP 5 ID, UMDate FROM WTData.dbo.Parts WHERE WTData.dbo.Parts.Part_Previous_UMDate IS NULL ORDER BY ID", WinToolConnection)
WinToolConnection.Open()
Dim reader = WinToolSQLCmd.ExecuteReader()
While reader.Read()
arrPartIDs.Add(reader.Item(0))
arrPartUMDates.Add(reader.Item(1))
End While
reader.Close()
WinToolSQLCmd.Dispose()
If arrPartIDs.Count > 0 Then
For Each PartID As Integer In arrPartIDs
WinToolSQLCmd = New SqlCommand("UPDATE WTData.dbo.Parts SET Part_Previous_UMDate = '" & arrPartUMDates.Item(intUMDateCounter) & "' WHERE ID = " & PartID.ToString, WinToolConnection)
WinToolSQLCmd.ExecuteReader()
Next
End If
Return Nothing
End Function
You should use SqlParameter to add values to your query (and also to guard against SQL injection). Your problem is that you convert the date to a string in the code and SQL Server treats it as a string. The error about conversion from varchar occurs because the date format is not the one SQL Server uses. If you use parameters, it knows that you pass the date value and sends it correctly - you don't need to worry about any string conversions.
WinToolSQLCmd = New SqlCommand("UPDATE WTData.dbo.Parts SET Part_Previous_UMDate = #DateParam WHERE ID = #IdParam", WinToolConnection)
WinToolSQLCmd.Parameters.Add("#DateParam", arrPartUMDates.Item(intUMDateCounter))
WinToolSQLCmd.Parameters.Add("#IdParam", PartID)
Also, it's an update query, so you should use ExecuteNonQuery to execute your query:
WinToolSQLCmd.ExecuteNonQuery()
ExecuteReader is used when you want to read the data from the database.

How to insert date and retrieve records based on that entered date

I am a PHP-MySql Guy & new to the vb.net & SQL Server CE.
how to handle records based on dates ?
Consider any table(tbl_demo) with with some columns having 1 column to store today's date.
For example (table structure)- Id Name today
-- ----- -----
int nvarchar datetime
If i have following data in a table -
Id Name today
-- ----- -----
1 vikram 11/08/2013 11:16:57 PM
then how do i retrieve this record by providing only 11/08/2013 to the query ?
PS-
I have facing following problem while executing the query (here is the code snippet) -
Dim Ddate As Date
Ddate = MonthCalendar1.SelectionRange.Start.ToString
SQLquery = "SELECT id,today FROM tbl_demo WHERE today = '" & Ddate & "'"
ERROR :The data type is not valid for the boolean operation.[Data type (if known) = datetime,Data type (if known) = nvarchar]
Though it is not best to have functions in the fields in the where clause (performance wise) this will do the job.
"SELECT id,today FROM tbl_demo WHERE CONVERT(DATETIME,CONVERT(VARCHAR,today,120)) = CONVERT(DATETIME,CONVERT(VARCHAR,'" & Ddate.ToString() & "',120))"
An alternative would be providing the Date directly to ISO format:
"SELECT id,today FROM tbl_demo WHERE CONVERT(DATETIME,CONVERT(VARCHAR,today,120)) = CONVERT(DATETIME,CONVERT(VARCHAR,'" & Ddate.ToString("yyyyMMdd") & "',120))"
I am not sure if it is yyyyMMdd or yyMMdd for SQL CE, so better try both.
According to this MSDN article it should be "yyMMdd" but it could be a typo...
While experimenting...I got this working as follows (please correct me if i wrong)
Dim Ddate As Date
Dim d, m, y
Ddate = MonthCalendar1.SelectionRange.Start.ToString
d = Ddate.ToString("dd")
m = Ddate.ToString("MM")
y = Ddate.ToString("yyyy")
And the Query is :
SQLquery = "SELECT billId,c_id,amount FROM tbl_outward WHERE (DATEPART(dd, ddate) = '" & d & "' AND DATEPART(mm, ddate) = '" & m & "' AND DATEPART(yyyy, ddate) = '" & y & "')"
Here's a complete example using a Data Reader. This is appropriate if you are going to process one row at a time. If you need to hold all the rows in memory or perform further operations you may want to use ExecuteDataSet to get the values.
This example prints the row values to the command line.
Dim recordDate as DateTime = new DateTime(2013,8,11)
Using connection As SqlCeConnection = New SqlCeConnection("Data Source=Database.sdf;Persist Security Info=False;")
connection.Open()
Using command As SqlCeCommand = connection.CreateCommand()
command.CommandText = "Select id, name, today from demo where today = #date"
Dim dateParameter As SqlCeParameter
dateParameter = New SqlCeParameter("#date", DbType.DateTime)
dateParameter.Value = recordDate
command.Parameters.Add(dateParameter)
Using reader As SqlCeDataReader = command.ExecuteReader()
Do While reader.Read()
Dim id As Integer = reader.GetInt32(0)
Dim name As String = reader.GetString(1)
Dim today As DateTime = reader.GetDateTime(2)
Console.WriteLine("{0,-4} {1,-10} {2,-10}", id, name, today)
Loop
End Using
End Using
End Using
A few important things to note:
The Using statements automatically clear up unused resources when you are finished with them
The sql statement used is parameterised, which allows you to pass in a strongly typed value rather than a string.
The first argument to Console.WriteLine is a string format. {0, -4} is a placeholder that will be filled by the next argument. -4 say that the value should be displayed left aligned in a column 4 characters wide. For more information, see the String.Format method documentation on MSDN.

Error converting nvarchar to numeric

I used the following statement for a parameter.
.Parameters("#SearchValue").Value = TextBoxParentID.Text
for this query:
objSqlCommand.CommandText = "Select ID " & _
"From Parents " & _
"Where ID = #SearchValue"
ID is a SQL server numeric column but I get this error:
error converting nvarchar to numeric
Can you show me the coding needed fix this?
At this point you are trying to assign value which is of type string and the parameter is bound as string (nvarchar). You need to convert it at first.
' Let's suppose that this is a value from your textbox
Dim strNumber As String = "12"
' Prepare a placeholder to convert your string value into integer
Dim myInteger As Integer
' Try to convert
If Int32.TryParse(strNumber, myInteger) Then
'If the conversion is successful
Dim myConnection As New SqlConnection("Your ConnectionString")
Dim myCommand As New SqlCommand("INSERT INTO Foo(Bar) VALUES (#Bar", myConnection)
'Use this syntax to assign values to parameters
myCommand.Parameters.AddWithValue("Bar", myInteger)
End If
This snippet also uses AddWithValue method. I suggest you to use this approach.

Adding more than 1 id to search for in SQL

Hey all i am in need of some ideas on how to go about doing the following:
I have a textbox that a user can type in an ID to search for in a database. It currently just checks for 1 ID.
Example:
User types in ID 645378
The Query would look like:
SELECT * FROM blahTable WHERE theID = '645378';
Now, i am looking to allow the user to type in more than 1 ID at a time and display those results.
So again an example would be:
User types in ID(s): 645378, 78664, 901524
And now this is where my question comes into play. How can i create a query based on how many ID's the user inputs into the textbox?
Any help would be great!
David
You could use the IN statement in SQL.
SELECT * FROM blahTable where theID in ('123','456','789')
I would advise implementing this via a parametrized query to avoid Bobby Tables (SQL Injection)
Just use IN:
SELECT * FROM blahTable WHERE theID IN (645378, 78664, 901524);
Note that if your values are actual strings and not numbers, then it will require some additional work:
Dim asValues As String()
Dim sbQuery As New System.Text.StringBuilder(5000)
' Get the text, but remove any embedded semi-colons and single quotes for sql injection'
asValues = Miles.Text.Replace(";", " ").Replace("'", " ").Split(New Char() {","c}, StringSplitOptions.RemoveEmptyEntries)
sbQuery.Append("SELECT * FROM blahTable WHERE theID IN (")
Dim fUseComma As Boolean
' Add each value to the query string. In this case, we are wrapping with '
For Each sValue As String In asValues
' Test the value for reasonableness (example only)'
If IsNumeric(sValue) Then
' Only use the comma starting from the second valid item added
If fUseComma Then
sbQuery.Append(",")
Else
fUseComma = True
End If
sbQuery.Append("'").Append(CInt(sValue)).Append("'")
End If
Next
sbQuery.Append(")")
cmd.CommandText = sbQuery.ToString
try this thing.
Dim xIDList As String = "645378, 78664, 901524" 'the user should separate ID by COMMA
Dim xID() As String = xIDList.Split(CChar(",")) 'splits the xIDlist
Dim xIDforQuery As String = String.Empty
For Each oID As String In xID
If oID.Trim.Length <> 0 Then
xIDforQuery &= "," & " '" & oID & "'" ' if ID is not numeric
' xIDforQuery &= "," & oID.ToString ' use this line if ID is numeric
End If
Next
xIDforQuery = xIDforQuery.Trim
xIDforQuery = CStr(IIf(Mid(xIDforQuery, 1, 1) = ",", Mid(xIDforQuery, 2, xIDforQuery.Length - 1), xIDforQuery))
Dim xFinalQuery As String = String.Empty
xFinalQuery = String.Format("SELECT * FROM blahTable where theID in ({0})", xIDforQuery)
' xFinalQuery is the final query statement but this approach is vulberable to SQL Injection.
How do users know which ID's they want? If there aren't too many ID's, using a multiple-selection list-box would improve the UI and simplify the code. If there are too many, then you might consider using an auto-complete text-box for users to choose items that can then be copied (removed) from a list-box to be used by the query.

Resources