Date MS access vb.net - vb.net

I want to update an item's expiration date in MS access but It throws a data type mismatch
This is the code I used to update the item please check this Thanks I tried doing addwithvalue and add("expD",oledbtype.Date) Non works
Query
query = "Update Medicines set BarcodeID = #BarcodeID, Drugs =#DrugName, Dosage = #Dosage, Quantity= #Quantity, Station =#Station, ExpD =#ExpDate, Price=#Price, stckid=#stckid, IsActive='" & ComboBox1.Text & "' where BarcodeID=#BarcodeID"
My parameters
cmd.CommandText = query
cmd.Parameters.AddWithValue("#BarcodeID", txtbarcode.Text)
cmd.Parameters.AddWithValue("#DrugName", txtdrugs.Text)
cmd.Parameters.AddWithValue("#Dosage", txtdosage.Text)
cmd.Parameters.AddWithValue("#Quantity", txtquantity.Text)
cmd.Parameters.AddWithValue("#Station", txtstation.Text)
cmd.Parameters.AddWithValue("#Price", txtprice.Text)
'cmd.Parameters.Add("#ExpD", OleDbType.Date)
'cmd.Parameters.AddWithValue("#ExpDate", dtExpD.Value.Date)
cmd.Parameters.Add("#ExpDate", OleDbType.Date).Value = Me.dtExpD.Value.Date
cmd.Parameters.AddWithValue("#stckid", txtstockid.Text)
cmd.Parameters.Add("#IsActive", OleDbType.LongVarChar)
cmd.Parameters("#IsActive").Value = combocontainer
Thanks

Even though you are using parameter names in your SQL code, the Jet and ACE OLE DB providers ignore those names and substitute values from parameters into the SQL code based on position. That means that you MUST add the parameters to the command in the same order as they appear in the SQL code. You ought to do that regardless but it is essential for Access databases. Your SQL code contains "ExpD =#ExpDate, Price=#Price" but you add parameters like this:
cmd.Parameters.AddWithValue("#Price", txtprice.Text)
cmd.Parameters.Add("#ExpDate", OleDbType.Date).Value = Me.dtExpD.Value.Date
The order is reversed so those values are actually getting used the wrong way around. At least you were alerted by the data type mismatch. If they had been the same type then it would have worked but saved the wrong data to the wrong columns.

Related

Retrieving "Number" From Sql VB.NET System.Data.OleDb.OleDbException: 'Data type mismatch in criteria expression.'

If I want to retrieve a value that is saved as a number in an access database.
Im using the following:
Dim sql As String = "SELECT ArithmeticScore FROM " & tablename & " WHERE DateAscending = '" & todaysdate & "'"
Using connection As New OleDbConnection(getconn)
Using command As New OleDbCommand(sql, connection)
connection.Open()
scorevalue = CDec(command.ExecuteScalar()) 'Data type mismatch in criteria expression.
connection.Close()
End Using
End Using
MsgBox(scorevalue)
getconn = connection string as a string
scorevalue = Nothing as decimal
The field ArithmeticScore is set to Number in the table.
The exact value in the cell right now is 50, but the program should allow for any decimal value.
The error im getting is "Data type mismatch in criteria expression".
The criteria expression mentioned in the error message does not refer to the ArithmeticScore output. It's talking about the WHERE clause. Whatever you have for todaysdate does not match what the database is expecting for the DateAscending column.
Since OleDb is a generic provider, we don't know exactly what kind of database you're talking to, but most databases have a way to get the current date value in SQL: getdate(), current_timestamp, etc. Using that mechanism will likely solve the conflict, and there's no need to use string concatenation for this in the first place.
Dim sql As String = "SELECT ArithmeticScore FROM " & tablename & " WHERE DateAscending = Date()"
The other way you can fix this is with proper parameterized queries, which you should doing anyway. It's NEVER okay to use string concatenation to substitute data into an SQL query, and if you find yourself needing to think about how to format a date or number string for use in an SQL command, you're almost always doing something very wrong.

Data adapter troubles

When I run the code the line which filled my datatable says that there is no value given for one or more parameters
Order = New OleDb.OleDbDataAdapter("SELECT * FROM Orders WHERE
Driver_ID = " & ID, DBREF)
Order.Fill(dataODtable)
DGVorders.DataSource = dataODtable
The code says this:
An unhandled exception of type 'System.Data.OleDb.OleDbException'
occurred in System.Data.dll
Below is an image link to the database and table it is referencing.
(Database orders table)
If I try run the code without the where statement it runs without crashing.
The field DRIVER_ID is clearly a string, as such you need single quotes around the value you want to use for the WHERE clause.
But that would be wrong for a long list of reasons (Sql Injection, Parsing errors, automatic type conversion with incompatible locales).
So you really need to start using parameterized queries as soon as possible to avoid these misteps
Dim cmdText = "SELECT * FROM Orders WHERE Driver_ID = #drvID"
Order = New OleDb.OleDbDataAdapter(cmdText, DBREF)
Order.SelectCommand.Parameters.Add("#drvID", OleDbType.VarWChar).Value = ID
Order.Fill(dataODtable)
DGVorders.DataSource = dataODtable
Now the query is no more built concatenating together strings pieces (the main source for sql injection hacks) but you create a parameter object of the correct type and pass it to the database engine that will use it when needed.
Another benefit is the more clear code you get. In this case perhaps is not very evident but with more complex queries you will have a more clear understanding of what you are asking to do to the database.
You can try like this:
Order = New OleDb.OleDbDataAdapter("SELECT * FROM Orders WHERE
Driver_ID = '"& ID &"'", DBREF)
Order.Fill(dataODtable)
DGVorders.DataSource = dataODtable
maybe this will be the problem.
if Driver_ID is alphanumeric column, select query should be SELECT * FROM Orders WHERE Driver_ID = '" & ID & "' ;"

SQL Select statement suddenly retrieving wrong value only when selecting form another query

I have a order creation form in an Access database where the user selects a product and VBA code is triggered with SQL select statement to retrieve the current availability of that product. This is how it's set up:
I have a Packages table where products batches are added to inventory.
I have an OrderDetail table where items from product batches are allocated to orders.
I have a InventoryPrep query with a the total packaged per batch and field that sums the number of allocated products per batch from the OrderDetail table.
Then I have an Inventory query that that has a calculated field that takes the TotalPackaged field from the InventoryPrep query and subtracts the TotalAllocated field from the InventoryPrep query.
Here is the VBA code in my form, triggered by an update to the [Batch] combo box:
Dim VBatch As String
VBatch = Me.Batch.Value
Dim VAvail As Double
Dim mySQL As String
Dim conn1 As ADODB.Connection
Set conn1 = CurrentProject.Connection
Dim rs1 As New ADODB.Recordset
rs1.ActiveConnection = conn1
mySQL = "SELECT Available FROM Inventory WHERE BatchID = " & "'" & VBatch & "'"
rs1.Open mySQL
rs1.MoveFirst
VAvail = rs1.Fields("Available").Value
Forms!ChangeOrders.ChangeOrderSubform.Form.Availability.Value = VAvail
rs1.Close
conn1.Close
Set rs1 = Nothing
Set conn1 = Nothing
This has been working just fine for weeks, retreiving the correct available amount as packaged items are added to the Packages table and orders are being added in the OrderDetail table. Yesterday it started returning the Packaged field from the InventoryPrep query instead.
I tried a bunch of things and then created a table from the query and used the SELECT statement to look it up in the table. That worked. There is something about my query set up that has caused it to stop recognizing my calculated field. I need help!
This is my first time posting and I hope this is enough information. I'm pretty new to Access and VBA but I've learned a lot from reading in this forum. I hope someone can help or let me know what other information could shed light on the problem.
To read a single value from a table or query, your code is a bit over the top.
For this scenario, Access has the DLookup function.
VAvail = DLookup("Available", "Inventory", "BatchID = '" & VBatch & "'")
Forms!ChangeOrders.ChangeOrderSubform.Form.Availability.Value = VAvail
That's all that is needed.

Retrieving the Query used for a OleDBCommand

I'm currently using the following VB code to make a query against an Access Database, I would like to know is it possible to obtain what the SELECT statement that is being run and send that output to the console.
Dim QuestionConnectionQuery = New OleDb.OleDbCommand("SELECT Questions.QuestionID FROM Questions WHERE Questions.QuestionDifficulty=[X] AND ( Questions.LastDateRevealed Is Null OR Questions.LastDateRevealed < DateAdd('d',-2,Date() ) AND Questions.LastUsedKey NOT LIKE ""[Y]"" );", QuestionConnection)
QuestionConnectionQuery.Parameters.AddWithValue("X", questionDifficulty.ToString)
QuestionConnectionQuery.Parameters.AddWithValue("Y", strDatabaseKey)
Right now when I try to use: Console.WriteLine("Query: " & QuestionConnectionQuery.ToString)
I only get this:
Loop Question #1
Query: System.Data.OleDb.OleDbCommand
The short version comes down to this:
QuestionConnectionQuery.ToString
The QuestionConnectionQuery object is much more than just the text of your command. It's also the parameters, execution type, a timeout, and a number of other things. If you want the command text, ask for it:
QuestionConnectionQuery.CommandText
But that's only the first issue here.
Right now, your parameters are not defined correctly, so this query will never succeed. OleDb uses ? as the parameter placeholder. Then the order in which you add the parameters to the collection has to match the order in which the placeholder shows in the query. The code in your question just has X and Y directly for parameter placeholders. You want to do this:
Dim QuestionConnectionQuery AS New OleDb.OleDbCommand("SELECT Questions.QuestionID FROM Questions WHERE Questions.QuestionDifficulty= ? AND ( Questions.LastDateRevealed Is Null OR Questions.LastDateRevealed < DateAdd('d',-2, Date() ) AND Questions.LastUsedKey NOT LIKE ? );", QuestionConnection)
QuestionConnectionQuery.Parameters.Add("?", OleDbType.Integer).Value = questionDifficulty
QuestionConnectionQuery.Parameters.Add("?", OleDbType.VarChar, 20).Value = strDatabaseKey
I had to guess at the type and lengths of your parameters. Adjust that to match the actual types and lengths of the columns in your database.
Once you have made these fixes, this next thing to understand is that the completed query never exists. The whole point of parameterized queries is parameter data is never substituted directly into the sql command text, not even by the database engine. This keeps user data separated from the command and prevents any possibility of sql injection attacks.
While I'm here, you may also want to examine the WHERE conditions in your query. The WHERE clause currently looks like this:
WHERE A AND ( B OR C AND D )
Whenever you see an AND next to an OR like that, within the same parenthetical section, I have to stop and ask if that's what is really intended, or whether you should instead close the parentheses before the final AND condition:
WHERE A AND (B OR C) AND D
This will fetch the command text and swap in the parameter values. It isnt necessarily valid SQL, the NET Provider objects haven't escaped things yet, but you can see what the values are and what the order is for debugging:
Function GetFullCommandSQL(cmd As Data.Common.DbCommand) As String
Dim sql = cmd.CommandText
For Each p As Data.Common.DbParameter In cmd.Parameters
If sql.Contains(p.ParameterName) AndAlso p.Value IsNot Nothing Then
If p.Value.GetType Is GetType(String) Then
sql = sql.Replace(p.ParameterName,
String.Format("'{0}'", p.Value.ToString))
Else
sql = sql.Replace(p.ParameterName, p.Value.ToString)
End If
End If
Next
Return sql
End Function
Given the following SQL:
Dim sql = "INSERT INTO Demo (`Name`, StartDate, HP, Active) VALUES (#name, #start, #hp, #act)"
After parameters are supplied, you can get back this:
INSERT INTO Demo (`Name`, StartDate, HP, Active) VALUES ('johnny', 2/11/2010 12:00:00 AM, 6, True)
It would need to be modified to work with OleDB '?' type parameter placeholders. But it will work if the DbCommand object was created by an OleDBCOmmandBuilder, since it uses "#pN" internally.
To get or set the text of the command that will be run, use the CommandText property.
To print the results, you need to actually execute the query. Call its ExecuteReader method to get an OleDbDataReader. You can use that to iterate over the rows.
Dim reader = QuestionConnectionQuery.ExecuteReader()
While reader.Read
Console.WriteLine(reader.GetValue(0))
End While
reader.Close()
If you know the data type of the column(s) ahead of time, you can use the type-specific methods like GetInt32. If you have multiple columns, change the 0 in this example to the zero-based index of the column you want.

Date Subtraction within Select Statement

I am currently working on an MS Access database, and am having problem with date subtraction.
Essentially I am trying to create a target date for example:
Target Date = Deadline - Lead Time
i.e. the lead time could be 30 days, therefore the target date should be 30 days prior to the deadline.
The code I am trying to use is this:
strSQL = "INSERT INTO dbo_DEALER_TASK ( Dlr_Number, Action_Id, Task_Id, Area_Id,
Task_Deadline_Date, Responsible_Person_Id, Alternate_Person_Id, Priority, Comment,
Suppress_Email, Dealer_Type ) "
strSQL = strSQL & "SELECT dbo_DEALER_ACTION.Dlr_Number, dbo_DEALER_ACTION.Action_Id,
qryAllTasksToAdd.Task_Id, qryAllTasksToAdd.Area_Id, Deadline_Date - Deadline_adjustment
AS 'Task_Deadline_Date', qryAllTasksToAdd.Person_Responsible_Id,
qryAllTasksToAdd.Alternate_Responsible_Id, qryAllTasksToAdd.Priority,
qryAllTasksToAdd.Comment, qryAllTasksToAdd.Suppress_Email,
qryAllTasksToAdd.Applies_To_Dealer_Type "
strSQL = strSQL & "FROM dbo_DEALER_ACTION LEFT JOIN qryAllTasksToAdd ON
(dbo_DEALER_ACTION.Dealer_Type = qryAllTasksToAdd.Applies_To_Dealer_Type) AND
(dbo_DEALER_ACTION.Action_Id = qryAllTasksToAdd.Action_Id) "
strSQL = strSQL & WHERE (((qryAllTasksToAdd.Task_Id)=" & Me.Task_Id & ") AND
((dbo_DEALER_ACTION.Date_Completed) Is Null));"
DoCmd.RunSQL strSQL
When the VBA code executes the statement, everything is updated correctly, except for the Task_Deadline_Date field, which is being left blank.
What is really confusing me though is if I run this SQL statement standalone it is working as expected. After trying a number of different ideas I tried to replace "Deadline_Date - Deadline_adjustment AS 'Task_Deadline_Date'" with a string literal date and the statement then worked fine
Does anybody have any ideas what is going wrong?
Thanks,
Chris
You have quoted the alias, you should not do that:
Deadline_Date - Deadline_adjustment AS Task_Deadline_Date
Not
Deadline_Date - Deadline_adjustment AS 'Task_Deadline_Date'
When you add the quotes, the name of the field is 'Task_Deadline_Date'
Depending on the data type of your date field and whether or not you are using SQL Server, you may need to use DateAdd, for example:
DateAdd("d",-[Deadline_adjustment],[Deadline_Date])
In Access' query designer, start with the version of your query which works and convert it to a parameter query.
WHERE
qryAllTasksToAdd.Task_Id=[which_id]
AND dbo_DEALER_ACTION.Date_Completed Is Null;
You can also add a PARAMETERS statement at the start of the query to inform the db engine about the data type of your parameter. Examples ...
PARAMETERS which_id Text ( 255 );
PARAMETERS which_id Long;
Once you get that query working, save it and give it a name. Then your VBA procedure can use that saved query, feed it the parameter value, and execute it.
Dim db As DAO.database
Dim qdf As DAO.QueryDef
Set db = CurrentDb
Set qdf = db.QueryDefs("YourQuery")
qdf.Parameters("which_id").value = Me.Task_Id
qdf.Execute dbFailOnError
Set qdf = Nothing
Set db = Nothing
This should be much easier than trying to recreate that SQL statement in VBA code each time you need to execute it.
It sounds like the data type of the column you are inserting in dbo_DEALER_TASK is not actually a datetime field.
I tried to replace "Deadline_Date - Deadline_adjustment AS 'Task_Deadline_Date'" with a string literal date and the statement then worked fine
If you mean '02/20/2012' (as you would correctly use on SQL Server, for example) then this shouldn't work in Access and only will if your output column is a text (= varchar/char)) data type. Date constants in Access are specified like #02/20/2012#
Please confirm the data type of Task_Deadline_Date in your output table.