In the below code, the value of skuSet.Fields(0), which is a text field in the database, is "000000002".
If skuSet.RecordCount = 0 Then
sql = "SELECT Stock_Code FROM Stock WHERE Stock_Code = '" & stkLine.StockCode & "'"
Set skuSet = dbStock.OpenRecordset(sql, dbOpenDynaset)
End If
sql = "SELECT * FROM PickedByPicco WHERE OrderID = " & stkLine.OrderId & " AND StockCode = '" & skuSet.Fields(0) & "'"
Set SOPSLineSet = dbSOPS.OpenRecordset(sql, dbOpenDynaset)
If SOPSLineSet.RecordCount = 0 Then
sql = "INSERT INTO PickedByPicco(OrderID, StockCode, Qty, ScannedBy, ProcessedBy, processed) VALUES(" & stkLine.OrderId & _
", " & skuSet.Fields(0) & ", " & stkLine.Quantity & ", '" & stkLine.UserId & "', '', False)"
dbSOPS.Execute (sql)
When I step through the code, the value in skuSet.Fields(0) is still the same, as expected.
When the query has been executed, I check the PickedByPicco table, and the StockCode field shows just a value of 2 instead, and it's removed all of the leading 0's.
Why would it be doing this and how can I stop it?
That's because your INSERT statement looks like this:
INSERT INTO PickedByPicco (...) VALUES (..., 000000002, ...)
when it should look like this:
INSERT INTO PickedByPicco (...) VALUES (..., '000000002', ...)
(Note the quotes around your value.)
Normally, I'd tell you to use parameterized SQL, because SQL creation by string concatenation is evil, but, unfortunately, DAO's Database.Execute does not support that. So, the next best thing is to properly escape strings. To do that:
put single quotes around your value and
escape any single quotes occurring in your value:
I.e. this line
", " & skuSet.Fields(0) & ", " & ...
becomes
", '" & Replace(skuSet.Fields(0), "'", "''") & "', " & ...
While you are at it, be sure to replace single quotes in your other strings as well! Currently, a UserId of O'Brien would break your SQL, and other values might do worse.
Related
I'm out of my league on this... Another developer before me did something similar to what I want to do by adding a value in a table while updating another table. However, he was running updates as well as inserting, and his primary key was text. Mine PK is integer. Here's his code (works great) that I am trying to reverse engineer and apply to my situation:
Dim sqlQuery As String
sqlQuery = "IF EXISTS (SELECT ReportPK FROM
ACIST_MobilePipelineReportReviewed WHERE ReportPK = '" & ReportPk & "') " &
_
" UPDATE ACIST_MobilePipelineReportReviewed set Status = 'Approved'
WHERE ReportPK = '" & ReportPk & "'" & _
" ELSE " & _
" INSERT INTO ACIST_MobilePipelineReportReviewed ([ReportPK],
[PipelineUID],[ReportDate],[ReportInspector],[Status]) VALUES (" & _
"'" & ReportPk & "','" & Me!PipelineUID & "','" & Me!ReportDate & "','"
& Me!ReportInspector & "','Approved')"
End Sub
Here's what I'm doing: I have a combo box on a form called FacilityEntryF. That form is tied to my FacilityT table. I am selecting "CampaignID" from the CampaignT table and adding it to the FacilityT using that combo box in the aforementioned form. No biggie there... Works great.
The FacilityT has many columns of which I have [FacilityID] which is the primary key and is an autogenerated integer. It also has a column for [CampaignID] which is a foreign key from the CampaignT table.
After adding the CampaignID and starting a new FacilityID in FacilityT, I also want to create a new record in my CampaignFacilityParticipationT table. That table consists of only three columns: CampaignFacilityParticipationID, CampaignID, ParticipantFacilityID. I want to take the new [FacilityID] and the [CampaignID] I added to that table and insert them into the CampaignFacilityParticipationT table (FacilityID goes into the ParticipantFacilityID column). Here's the code below that didn't work (which I'm not surprised because I don't know what I'm doing):
Dim sqlQuery As String
sqlQuery = "IF EXISTS (SELECT FacilityID FROM FacilityT WHERE FacilityID =
" & FacilityID) " & _
" INSERT INTO CampaignFacilityParticipationT ([CampaignFacilityParticipationID],[CampaignID],[ParticipantFacilityID]) VALUES (" & _
"" & CampaignFacilityParticipationID,'" & Me!CampaignID," & Me!ParticipantFacilityID, CampaignID)"
End Sub
Using MS Access 2013 with Microsoft SQL backend.
Thanks!!!
Concatenation is not correct. If apostrophes are needed to delimit parameters then make sure they are used consistently. Normally in Access, apostrophes would only be used for text fields, # for date/time and nothing for number. Maybe because backend is MS SQL apostrophes are needed for all field types? Why do you repeat CampaignID in VALUES clause?
sqlQuery = "IF EXISTS (SELECT FacilityID FROM FacilityT WHERE FacilityID = '" & Me!FacilityID & "')" & _
" INSERT INTO CampaignFacilityParticipationT ([CampaignFacilityParticipationID],[CampaignID],[ParticipantFacilityID])" & _
" VALUES ('" & Me!CampaignFacilityParticipationID & "','" & Me!CampaignID & "','" & Me!ParticipantFacilityID & "')"
Is it possible for you to use a subform on FacilityEntryF on which you select the CampaignID? That will eliminate the need for this code.
So all I'd like to do is add two queries into a table called tmpGroupSearch. I'm not sure how to do it wit out creating a record set and looping through every record and individually adding them in. I'm thinking there is a much easier way to do this I just can't find the proper structure.
Here are my queries:
"SELECT tblGroupHeader.GroupName" _
& ", tblGroupHeader.GroupNum" _
& ", tblAlsoKnown.AlsoKnown" _
& " FROM tblGroupHeader" _
& " LEFT JOIN tblAlsoKnown ON tblGroupHeader.GroupNum = tblAlsoKnown.GroupNum" _
& " WHERE tblGroupHeader.GroupName like '" & txtgroupSearch.Value & "*'" _
& " OR tblGroupHeader.GroupNum like '" & txtgroupSearch.Value & "*';"
"Select * FROM tblActionLog WHERE AlsoKnown LIKE '" & txtgroupSearch.Value & "*';"
You can follow an INSERT INTO clause with a list of values, like #Asad shows, or also a SELECT query. Do yourself a favor and always list the field names in your SQL or you are just creating time bombs for the future.
Dim strSelect1 As String
Dim strSelect2 As String
strSelect1 = "SELECT tblGroupHeader.GroupName" _
& ", tblGroupHeader.GroupNum" _
& ", tblAlsoKnown.AlsoKnown" _
& " FROM tblGroupHeader" _
& " LEFT JOIN tblAlsoKnown ON tblGroupHeader.GroupNum = tblAlsoKnown.GroupNum" _
& " WHERE tblGroupHeader.GroupName like '" & txtgroupSearch.Value & "*'" _
& " OR tblGroupHeader.GroupNum like '" & txtgroupSearch.Value & "*';"
strSelect2 = "Select * FROM tblActionLog WHERE AlsoKnown LIKE '" & txtgroupSearch.Value & "*';"
Dim strInsert1 As String
Dim strInsert2 As String
strInsert1 = "INSERT INTO tmpGroupSearch (GroupName, GroupNum, AlsoKnown) " & strSelect1
'the next version is valid SQL, but *dangerous* because field names are not enumerated
strInsert2 = "INSERT INTO tmpGroupSearch " & strSelect2
It is possible to write the INSERT INTO statement in two forms.
The first form does not specify the column names where the data will be inserted, only their values:
INSERT INTO table_name
VALUES (value1,value2,value3,...);
The second form specifies both the column names and the values to be inserted:
INSERT INTO table_name (column1,column2,column3,...)
VALUES (value1,value2,value3,...);
Test this parameter query in the Access query designer and adjust as needed so that it returns the row set you expect for the pSearchText parameter value you supply.
PARAMETERS pSearchText Text ( 255 );
SELECT gh.GroupName, gh.GroupNum, ak.AlsoKnown
FROM
tblGroupHeader AS gh
LEFT JOIN tblAlsoKnown AS ak
ON gh.GroupNum = ak.GroupNum
WHERE
gh.GroupName Like "'" & pSearchText & "*'"
OR gh.GroupNum Like "'" & pSearchText & "*'"
UNION ALL
SELECT al.GroupName, al.GroupNum, al.AlsoKnown
FROM tblActionLog AS al
WHERE al.AlsoKnown Like "'" & pSearchText & "*'"
Once you have it returning the correct data, convert it to an INSERT query by changing the beginning of the statement to this ...
PARAMETERS pSearchText Text ( 255 );
INSERT INTO tmpGroupSearch (GroupName, GroupNum, AlsoKnown)
SELECT gh.GroupName, gh.GroupNum, ak.AlsoKnown
... and the rest
Save that query as qryGroupSearchAppend. Then you can execute that query from your VBA code:
Dim qdf As DAO.QueryDef
Set qdf = CurrentDb.QueryDefs("qryGroupSearchAppend")
qdf.Parameters("pSearchText").Value = Me.txtgroupSearch.Value
qdf.Execute dbFailOnError
I'm trying to fix it about hour but it's not work Please help me :(
CurrentDb.Execute "INSERT INTO match_day( home_team, away_team, date, time, home_score, away_score, stadium) " & _
" VALUES('" & Me.textHT & "','" & Me.textAT & "',#" & Me.textDATE & "#,#" & Me.textTime & "#," & Me.textHS & "," & Me.textAS & ",'" & Me.textSTD & ",')"
Are the fields for date and time considered reserved words and should be wrapped in brackets or ticks to qualify it as the column name...
..., [date], [time], ...
But I think it is most likely the trailing final comma before your final closing ) of the inserted values making it look like it wants another field to be inserted.
Me.textSTD & ",')"
change to
Me.textSTD & "')"
I ran into a similar error - thanks to this post I realised that I had used a reserved name "note" in a table ( instead of "notes").
StrSQL = "INSERT INTO option_notes ( OPTION_ID , USER_ID , [NOTE] ) VALUES ( " & currID & " , " & currUserID & " , '" & currNote & "' ) ; "
CurrentDb.Execute StrSQL
I ended up changing the field name - however, wrapping the field name with [ ] allowed the code to execute correctly.
We'd like to count from an Access database that has multiple tables - about 50.
We need to count from 1 column in each table that is 'QCPASS' This is a check box - if a product passed the box was checked if failed then not. We need to count both for EACH table, also allowing the user to specify a date range from a date column that exists in every table.
I've tried this with a query but I am told the query is unable to select, count and do the date range. Any VBA help would be great.
Exporting to Excel would be great, but any results would be fine. Here is the query I created that counts in a column from each table passes and failures. I can't iterate with a query either, so VBA seems the way to go:
SELECT "Table1" , Count('qcpass') AS column
FROM 5000028
GROUP BY [5000028].qcpass
union
SELECT "Table2",count('qcpass')
FROM 5000029
Group By [5000029].qcpass;
You can traverse the full TableDefs collection in your database, and create a query using VBA.
A word of warning: The TableDefs collection has the Access database system tables, so you need to skip this. A way I suggest you is to check for a specific table name prefix (it is noted in the code below).
public sub createMyBigUnionQuery()
dim db as DAO.database(), tbl as DAO.tableDef
dim strSQL as string, i as integer
set db = currentdb()
i = 1
for each tbl in db.TableDefs
if left(tbl.name, 1) = "5" then ' Check for a table name prefix
if i = 1 then
' The final spaces are important
strSQL = "select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"group by qcpass "
else
' The final spaces are important
strSQL = strSQL & " union all " & _
"select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"group by qcpass "
end if
i = i + 1
end if
next tbl
db.createQueryDef "qryYourFinalQuery", strSQL
db.close
exit sub
Notice that you can define any valid query you want. Take this as a hint, and tweak it to fit your specific needs.
Hope this helps you
Adressing #HansUp comment, if you need to filter your data by date, you have two options:
Include the where condition on every select created by the procedure
Include the date field in your query and group by it, and create a second query to filter the data you need from the created query.
I would personally go with option 1, and here is a sample code:
public sub createMyBigUnionQueryWithDates(d0 as date, d1 as date)
dim db as DAO.database(), tbl as DAO.tableDef
dim strSQL as string, i as integer
set db = currentdb()
i = 1
for each tbl in db.TableDefs
if left(tbl.name, 1) = "5" then ' Check for a table name prefix
if i = 1 then
' The final spaces are important
strSQL = "select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"where rowDate between " & cDbl(d0) & " and " &cDbl(d1) & " " & _
"group by qcpass "
else
' The final spaces are important
strSQL = strSQL & " union all " & _
"select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"where rowDate between " & cDbl(d0) & " and " &cDbl(d1) & " " & _
"group by qcpass "
end if
i = i + 1
end if
next tbl
db.createQueryDef "qryYourOtherFinalQuery", strSQL
db.close
exit sub
The reason I use cDbl(d0) is because Access dates are sensitive to regional settings, and I've had a lot of headaches dealing with it. Access (and many other Microsoft products) store dates as floating-point numbers (the integer part is the date, and the decimal part is the time).
Another word of warning: If your dates don't include time, then the between condition will work. But if they do include time, then I recommend you change the where condition to this:
"where rowDate >= " & cDbl(d0) & " and rowDate < " & cDbl(d1 + 1)"
I have 11 columns as Note1,Note2,Note3,......Note11. I have write a query like this to combine
SELECT DormData.BuildingID,
DormData.DormRoomID,
DormData.Item,
DormData.Result,
DormData.InspectorID,
DormData.Date,
DormData.Qty,
DormData.Section,
(Note1 & " , "
& Note2 & ", "
& Note3 & " , "
& Note4 & " , "
& Note5 & " , "
& Note6 & " , "
& Note7 & ", "
& Note8 & ", "
& Note9 & ", "
& Note10 & ", "
& Note11) AS Notes,
DormData.Comments,
DormData.Resident
FROM DormData;
It works and combine my records but problem is that it is not necessary that all the notes
columns have values.suppose that if in a row there is values in only Note1 and Note5 then it gives output like not1,,,,note5. but I want it show "Note1,Note5"
How can I fix this?
You could use an Iif statement in each 'Note1 * ","' section to check for null values.
Iif(IsNull(Note1), Note1, Note1 & ",")
I think that should work.
The key is IIF() aka immediate if.
For example, on the orders table in the Northwind sample database:
IIF(orders.ShipRegion IS NOT NULL, orders.ShipRegion & ',', ''
Or a more complete query:
SELECT
orders.OrderID, orders.CustomerID, orders.EmployeeID,
orders.ShipVia, orders.Freight,
(orders.ShipName & ',' & orders.ShipCity & ',' & IIF(orders.ShipRegion IS NOT NULL, orders.ShipRegion & ',', '') & orders.ShipPostalCode & ',' & orders.ShipCountry) AS Expr1
FROM orders
WHERE orders.[OrderID]=10282;
If you want to go the vba function route, the following function will do the job:
Function JoinStrings(Delimiter As String, _
ParamArray StringsToJoin() As Variant) As String
Dim v As Variant
For Each v In StringsToJoin
If Not IsNull(v) Then
If Len(JoinStrings) = 0 Then
JoinStrings = v
Else
JoinStrings = JoinStrings & Delimiter & v
End If
End If
Next v
End Function
You would call it like this:
JoinStrings(", ", Note1, Note2, Note3, Note4, Note5, Note6, Note7)
You can also use a trick with how Null expressions and concatenation works in Access:
Note1 & (", " + Note2) & (", " + Note3)...
When concatenating text, Access treats Null as it were an empty string. But if you're "adding", the Null would cause the expression inside the parentheses to result in Null. As long as your notes aren't numeric, this will work.
A modification to TheOtherTimDuncan' solution, which will work well to concatenate two (or may be three) Notes. Use IIF() to have delimiter or blank based on whether Note1 is Null. It could be like:
Note1 & (IIF(Note1 Is Null, "",", ") + Note2) & (IIF((Note1 & Note2) Is Null, "",", ") + Note3)...