MS Access sql - Update query syntax - vba

Seems a small issue with an sql update query. But I can not get my head around this issue. Not very much acquainted with sql.
Based on a selection, selected rows from a table (7DARphases) are copied and inserted to another table (7tblDAR). And the Project ID (PRJID column) for all the inserted rows should be updated with a fixed value (PID) taken from the form.
Issue is: I am facing syntax issue in the part where the fixed value needs to be inserted in the PRJID column of added rows.
Code is:
Set dbs = CurrentDb
PID = Me.PRJID.Value
sqlstr = "INSERT INTO 7tblDAR (Phase, Deliverable, Link_PIM_temp, Link_PIM_WB, Description, Accept_criteria, Deliv_type, TollgateID, Workstream, Accountable, ClientRACI) SELECT [7DARphases].Phase, [7DARphases].Deliverable, [7DARphases].Link_PIM_temp, [7DARphases].Link_PIM_WB, [7DARphases].Description, [7DARphases].Accept_criteria, [7DARphases].Deliv_type, [7DARphases].TollgateID, [7DARphases].Workstream, [7DARphases].Accountable, [7DARphases].ClientRACI FROM 7DARphases WHERE ((([7DARphases].SolType) Like '*2PP*')) ORDER BY [7DARphases].Phase, [7DARphases].Deliverable;"
sqlUpdt = "update 7tblDAR set PRJID = '" & Me.PRJID.Value & "' from 7tblDAR where tblDAR.PRJID = """""
dbs.Execute sqlstr, dbFailOnError
dbs.Execute sqlUpdt, dbFailOnError
The 'sqlstr' works fine and inserts rows.
But 'sqlUpdt' gives error:
"Run-time error 3075: Syntax error (missing operator) in query expression ..."
Can you please help me out with this.
Plus, if possible, can you suggest to perform this action in one query itself.

Why not put the value in when you insert the values?
sqlstr = "INSERT INTO 7tblDAR (Phase, Deliverable, Link_PIM_temp, Link_PIM_WB, Description, Accept_criteria, Deliv_type, TollgateID, Workstream, Accountable, ClientRACI, PRJID)
SELECT . . .,
'" & Me.PRJID.Value & "'
WHERE [7DARphases].SolType Like '*2PP*')
ORDER BY [7DARphases].Phase, [7DARphases].Deliverable;"
This saves the trouble of having to update it later.

Related

How can I combine these two SQL queries (Access/VBA)

I am using two SQL queries in VBA that i believe they could be done in one, but I cant get it to work. I Want to turn the VBA portion into a Query outside of VBA, the VBA keeps breaking my file due to the amount of data it processes. (By break i mean it gives a message that says "this file is not a valid database" rendering the file corrupted). I search for that error but all i found was not related to breaking because of VBA code.
Anyways, here are the two queries ran with VBA.
SELECT ET.VerintEID AS EID, Sum(ET.ExceptMin)/60 AS Exeptions
FROM Tbl_VExceptTime AS ET
INNER JOIN Tbl_VCodes ON ET.Exception = Tbl_VCodes.Exception
WHERE (ET.ExceptDate Between #" & sDate & "# And #" & eDate & "#)
GROUP BY ET.VerintEID, Tbl_VCodes.IsApd
HAVING Tbl_VCodes.IsApd = ""OFF"";
I loop these results to update a table.
Do While Not .EOF
SQL = "UPDATE Tbl_AttendanceByAgent SET EXC = " & recSet.Fields(1).Value & _
" WHERE VerintID = '" & recSet.Fields(0).Value & "'"
CurrentDb.Execute SQL
.MoveNext
Loop
I know that i can save the results from the first query into a table and without looping I can update the main table with another SQL query, but I believe it can be done on a single SQL. I have tried using an UPDATE with a SELECT of the first query but it just errors out on me with an invalid syntax.
Yes this could be achieved in one single query as shown below
UPDATE Tbl_AttendanceByAgent
SET Tbl_AttendanceByAgent.EXC = t2.Exeptions
from Tbl_AttendanceByAgent t1
inner join (
SELECT ET.VerintEID AS EID, Sum(ET.ExceptMin)/60 AS Exeptions
FROM Tbl_VExceptTime AS ET
INNER JOIN Tbl_VCodes as TV ON ET.Exception = TV.Exception
WHERE (ET.ExceptDate Between #" & sDate & "# And #" & eDate & "#)
GROUP BY ET.VerintEID, TV.IsApd
HAVING Tbl_VCodes.IsApd = 'OFF'
) AS t2 on t2.EID = t1.VerintID
Note: I suppose you will replace sDate, eDate with values within your code
This question is an answer to the described errors and the given code, although it technically does not answer the request for a single SQL statement. I started adding a comment, but that's just too tedious when this answer box allows everything to be expressed efficiently at once.
First of all, referring to CurrentDb is actually NOT a basic reference to a single object instance. Rather it is more like a function call that generates a new, unique "clone" of the underlying database object. Calling it over and over again is known to produce memory leaks, and at the least is very inefficient. See MS docs for details.
Although the given code is short, it's not sweet. Not only is it repeatedly creating new database objects, it is repeatedly executing an SQL statement to update what I assume is a single row each time. That also entails regenerating the SQL string each time.
Even if executing the SQL statement repeatedly was an efficient option, there are better ways to do that, like creating a temporary (in-memory) QueryDef object with parameters. Each loop iteration then just resets the parameters and executes the same prepared SQL statement.
But in this case, it may actually be more efficient to load the table being updated into a DAO.Recordset, then use the in-memory Recordset to search for a match, then use the recordset to update the row.
I suspect that addressing a couple of those issues would make your VBA code viable.
Dim db as Database
Set db = CurrentDb 'Get just a single instance and reuse
Dim qry as QueryDef
SQL = "PARAMETERS pEXC Text ( 255 ), pID Long; " & _
" UPDATE Tbl_AttendanceByAgent SET EXC = pEXC " & _
" WHERE VerintID = pID"
set qry = db.CreateQueryDef("", SQL)
'With recSet '???
Do While Not .EOF
qry.Parameters("pEXC") = recSet.Fields(1).Value
qry.Parameters("pID") = recSet.Fields(0).Value
qry.Execute
.MoveNext
Loop
'End With recSet '???
'OR an alternative
Dim recUpdate As DAO.Recordset2
Set recUpdate = db.OpenRecordset("Tbl_AttendanceByAgent", DB_OPEN_TABLE)
Do While Not .EOF
recUpdate.FindFirst "VerintID = " & recSet.Fields(0).Value
If Not recUpdate.NoMatch Then
recUpdate.Edit
recUpdate.Fields("EXC") = recSet.Fields(1).Value
recUpdate.Update
End If
.MoveNext
Loop
I realized in commenting on Gro's answer, that the original query's aggregate clauses will produce unique values on EID, but it then becomes obvious that there is no need to group on (and sum) values which do not have Tbl_VCodes.IsApd = 'OFF'. The query would be more efficient like
SELECT ET.VerintEID AS EID, Sum(ET.ExceptMin)/60 AS Exeptions
FROM Tbl_VExceptTime AS ET
INNER JOIN Tbl_VCodes ON ET.Exception = Tbl_VCodes.Exception
WHERE (ET.ExceptDate Between #" & sDate & "# And #" & eDate & "#)
AND Tbl_VCodes.IsApd = 'OFF'
GROUP BY ET.VerintEID;
BTW, you could consider implementing the same temporary QueryDef pattern as I showed above, then you'd change the first WHERE expression to something like
PARAMETERS PsDate DateTime, PeDate DateTime;
...
WHERE (ET.ExceptDate Between [PsDate] And [PeDate])
...

Access delete query not deleting right record

This should not be that hard. I'm simply trying to delete a record from a table, where the ID is equal to a form value. Done it a thousand times.
In this case, the FIRST record in the table is being deleted, NOT the selected one in the form. I've looked at table properties, form properties and tried every delete query variation I'm aware of.
I've tried building a delete query in Query Design and executing that. I've tried a SQL statement by passing the Access query. And I've tried writing the SQL to the Access delete query. All results are the same.
HOWEVER, if I hard code the ID number in the Access Delete Query, the correct record deletes as expected. Here's a few I've tried:
Set dbs = CurrentDb
DoCmd.RunSQL "DELETE * FROM " _
& "tblCourse WHERE coCourseID = " & coCourseID & ";"
Set dbs = CurrentDb
dbs.Execute "DELETE * FROM " _
& "tblCourse WHERE coCourseID = " & coCourseID & ";"
CurrentDb.QueryDefs("dqryDeleteCourse").Sql = "DELETE * FROM tblCourse WHERE
coCourseID = " & coCourseID & ";"
dbs.Execute dqryDeleteCourse
In all cases, the variable IS populating correctly.
Here's the Query Design of the dqry (this does not work):
Field: coCourseID
Table: tblCourse
Delete: WHERE
Criteria: [Forms]![frmCourseEdit]![coCourseID]
(I use this method of Criteria = form object value all throughout this application without an issue)
When Criteria = 1003 (hardcoded), it works.
Any troubleshooting ideas would be most appreciated.

MS ACCESS VBA: type mismatch error in recordset name into SQL statement string

How should I write the name of the recordset correctly? I have a type mismatch error on & rsg & at "sq3=..." line. Thanks in advance.
Dim rsG As DAO.Recordset
Dim sq2, sq3 As String
sq2 = "SELECT * from GeneralTable "
sq2 = sq2 & "where gsede='LION' and (gExclu is null) and (gAda is null) "
sq2 = sq2 & "order by gnomb,gnif;"
Set rsG = CurrentDb.OpenRecordset(sq2)
sq3 = "UPDATE " & rsG & " SET gsede ='AA' WHERE gsede='LION'"
DoCmd.RunSQL (sq3)
You are mixing up totally different ways to update data - UPDATE SQL and VBA recordset.
If you want to update a recordset row by row, you do something like
Do While Not rsG.EOF
If rsG!foo = "bar" Then
rsG.Edit
rsG!gsede = "AA"
rsG.Update
End If
rsG.MoveNext
Loop
Do the update using a single query:
update generaltable
set gsede = 'AA'
where gsede ='LION' and (gExclu is null) and (gAda is null);
If you do the update off of rsG, then you'll likely do a separate update for each row, and that is inefficient.
You can't mix and match SQL and recordset objects. You can either build a full update statement that includes the logic of the first select (as other answer suggests), or you can open a dynamic recordset and loop through the records programmatically to make the updates.
That being said, looping through large recordsets programmatically to make updates is usually better handled by a bulk SQL statement, unless it is essential to consider each row individually inside the code - which in your basic example would not be the case.
MS has a good article on the DAO.Recordset object. There is a dynamic-type Recordset example about halfway down.

Syntax error in Update Statement ASP Classic

I am having the syntax error in my code on a update statement, after reading multiple posts about it I cant figure out what is causing the error.
The code is as follows:
if request.querystring("do")="customer" then
New_customer = request.Form("customer")
openconn con
sSQL="SELECT RelationNumber FROM Relations WHERE RelationName='" & New_customer & "'"
set rst = con.execute(sSQL)
if rst.EOF then
response.write "No relation found"
else
Relationnumber_update = rst("RelationNumber")
sSQL2="SELECT Number FROM Orders WHERE Relation=" & Relationnumber_update & ""
set rst2 = con.execute(sSQL2)
if rst2.EOF then
response.write("No order number found!")
else
if Relationnumber_update <> 1000 then
Ordernumber_update = rst2("Nummer")
sSQL3="UPDATE Bookings SET Order=" & Ordernumber_update & " WHERE ID=" & request("ID")
con.execute(sSQL3)
else
response.write("Order number 1000 is not allowed!")
end if
end if
end if
closeconn con
response.redirect("myPage.asp?action=page")
response.end
end if
The error happens on the line: sSQL3="UPDATE Bookings SET Order=" & Ordernumber_update & " WHERE ID=" & request("ID")
Things to know:
The request queriestring is from the form where the user can choose a customer in a dropdown list. See code: <form name="ChangeCustomer" method="post" action="myPage.asp?action=page&do=customer&ID=<%=rst("ID")%>" style="display:inline">
The rst from ID is from a select statement before which works since I used in also in other code in the same way (that does work).
The openconn con is a function for accessing my database (it works, same reason as above)
Eacht select statement in this code has been tested for its output in a response.write. All the results that came out were the expected ones.
Short description of what happens in the code above
A user changes the customer in the form (with a dropdown menu) and presses save (submit).
On submit the queriestring is launched, this was tested if the code actually comes to this and it does.
The chosen customer is saved in the var New_customer.
The relation number that matches the customer name is retrieved with the first select statement.
The right relation number is being put into the var Relationnumber_update
In the second query the right number is being searched for that equals the relation number.
A if/then follows which makes sure the Relationnumber_update is not equal to 1000 (no updates should be done on this number)
If its not equal to 1000 then the found order number (second select statement) is stored in the var ordernumber_update
The update statement follows where Order field in the bookings table is being updated with the found ordernumber.
In the end (after the if) the connection is being closed and the page is being 'refreshed'.
For some reasson I am getting the syntax error on my update statement but I have no clue why. I checked the data types of the Number field in the orders table, the Relationnumber from the Relations table and the Order field in the bookings table, they are all of type number/int.
I also tried to update with a set number directly in the update statement instead of the ordernumber_update var (like so: sSQL3="UPDATE Bookings SET Order=6477 WHERE ID=" & request("ID")) but this gives the same error..
Three things:
Read about Sql Injections
To debug sql statement "live", use
sSQL3="UPDATE Bookings ...
Response.Write(sSQL3)
'con.execute(sSQL3) -- comment it out
run page, and test resulted sql query against database
If ID has string datatype (char, varchar, etc) then you should quote its value using '...'
P.S.
Use [Order] to deal with reserved words.
Be aware of the reserve words of database management system.
Here you are using Order, which is a reserved one.
So use this if you using MySQL:
sSQL3="UPDATE Bookings SET `Order`=" & Ordernumber_update & " WHERE ID=" & request("ID") &";"
Or in case of SQL Server:
sSQL3="UPDATE Bookings SET [Order]=" & Ordernumber_update & " WHERE ID=" & request("ID") &";"
Hope this will help others also. Thank you.
Use bracketes aound [Order], not single quotes. And don't use reserved words for your field names. Jus sayin'.

"Null" value in Queries

I'm trying to run code that will copy fields into a new table, moving them from a _New table to the original table. The VBA code that does this works as such:
SQLStatement = CStr("INSERT INTO " & TName & " SELECT * FROM " & TName & "_New")
Log.WriteLine "Running query with string """ & SQLStatement & """ "
QueryTimer = Timer
DoCmd.RunSQL SQLStatement
Log.WriteLine "Query time: " & (Timer - QueryTimer)
The log is just a handful of procedures in a class module I threw together. Its output on the error is
#142921: Running query with string "INSERT INTO Records SELECT * FROM Records_New"
#142941: Error Date/Time: 7/21/2009 2:29:40 PM
#142941: Error # & Description: 3162, You tried to assign the Null value to a variable that is not a Variant data type.
I can confirm that TName and SQLStatement are both valid strings at the time the SQL operation is run, and that the sources (Records and Records_New) are both valid. Option Explicit is set elsewhere in the file to avoid any confusion from typos. The error is thrown on the DoCmd line.
Why would this have a Null value, even though DoCmd.RunSQL doesn't return a value?
Can you post the table descriptions for Records and Records_New tables?
I would wager that you are trying to insert a NULL value into one of the columns of the "Records" table (and the column description is NOT NULL).
Hope this helps.
I think it will help if you also change the insert statement to be more specific about which columns it is inserting/selecting. You are asking for bugs by being so non-specific.
This may seem like it is non-responsive to your answer, but I suspect that the columns in the select table and destination table are either not lined up, or there is a field in the destination table that disallows null.
Try this:
In a new Query (in SQL view) paste your query "INSERT INTO Records SELECT * FROM Records_New" in and try to run it manually. I bet you get a more specific error and can troubleshoot the query there before running it with the added complexity of the code around it.
INSERT INTO Statement (Microsoft Access SQL)
Your SQL INSERT statement is incorrect - it should be:
INSERT INTO Records SELECT * FROM [Records_New];
Here's what you need to use:
CStr("INSERT INTO " & TName & " SELECT * FROM [" & TName & "_New)"];")
Maybe Timer needs parens?
QueryTimer = Timer()