SQL for INSERT from SELECT with additional values - sql

I'm not sure if this is possible but I'm trying the run the following SQL from a VBA application in ACCESS DB. I'd like to INSERT a record into 'outputTable' with most of the data coming from a record in 'stagingTable'. However, two fields need to come from a form and I cannot figure out how to include those values into the INSERT statement.
sql = "INSERT INTO " & outputTable ([Date],[Carrier],[Division],[Code],[Status],[Total])
SELECT [Division],[Code],[Status],Sum([Claim]) AS [SumOfClaim]
FROM " & stagingTable & "
GROUP BY [Division],[Code],[Status];"
On the outputTable, the [Date] and [Carrier] values are missing. These would come from user input on a form. Is there a way I could add these values into to SQL statement?
Thank you

The best solution is to create a parameterized query as shown here: https://stackoverflow.com/a/2317225/3820271
It would e.g. look like this:
Dim DB As Database
Dim QD As QueryDef
Dim S As String
Set DB = CurrentDb
S = "PARAMETERS parDate DateTime, parCarrier Text(255); " & _
"INSERT INTO " & outputTable & "([Date], [Carrier], [Division], [Code], [Status], [Total]) " & _
" SELECT [parDate], [parCarrier], [Division],[Code],[Status],Sum([Claim]) AS [SumOfClaim] " & _
" FROM " & stagingTable & _
" GROUP BY [Division],[Code],[Status];"
' Create a temporary query object
Set QD = DB.CreateQueryDef("", S)
' Set parameter values from your input form
QD.Parameters!parDate = Forms!myForm!myDateField
QD.Parameters!parCarrier = Forms!myForm!Carrier
' Run the query
QD.Execute
Set QD = Nothing

Related

Update or insert field from table into another table VBA sql

First this is my first post so I apologize for the layout or any other errors with presentation.
I have two tables.
tempWkEndHrs: Is created when the user selects a weekending date and their name from two comboboxs. The result is 5 fields: Name1, Task, Closed Date, Initiated Date and #xx/xx/xxxx# <--the same date as chosen by the user from the combobox to create the table. This is done to limit the number of date fields returned and built into the temp table.
The purpose of this table is so the user can populate as many values under the #xx/xx/xxxx# field/column to show/see the distribution of hours taken on tasks for that week. (its also used as a check to make sure entered values sum up as expected)
I would like to save the new values entered underfield #xx/xx/xxxx# in tempWkEndHrs to the same field #xx/xx/xxxx# in tblHrs.
tblHrs: has fields... Task , #xx/xx/xxxx#, #xx/xx/xxxx#, #xx/xx/xxxx#, #xx/xx/xxxx#, etc.. <--Same dates available within combobox.
I have having difficulty finding an example of updating multiple records from one table to another to fit my situation.
Below is my last attempt from several variations.
Dim strITEM As String
Dim strWkEnd As String
strWkEnd = Me.cmbWkEnd
strSQL = "UPDATE tblHrs SET " & _
"[" & strWkEnd & "] = [" & strWkEnd & "] " & _
"FROM tempWkEndHrs " & _
" WHERE [Task] = [Task]"
*Update 10-24-2017 5:37pm
Dim strITEM As String
Dim strWkEnd As String
strWkEnd = Me.cmbWkEnd
strSQL = "UPDATE tblHrs " & _
"SET tempWkEndHrs.[" & strWkEnd & "] = tblHrs.[" & strWkEnd & "] "& _
"FROM tempWkEndHrs " & _
" WHERE tempWkEndHrs.[Task] = tblHrs.[Task]"
Result:
UPDATE tblHrs SET tempWkEndHrs.[9/30/2017] = tblHrs.[9/30/2017] FROM tempWkEndHrs WHERE tempWkEndHrs.[TASK] = tblHrs.[TASK]
***Run-Time error '3075
***Syntax error(missing operator) in query expression 'tblHrs.[9/30/2017] FROM tempWkEndHrs'.
If this is clear as mud please let me know.
enter image description here
BIG SHOUT OUT TO
Oscar Anthony and Parfait
https://stackoverflow.com/a/34910889/8797058
5.You don't need the FROM tblTemp clause in the SQLReplace String.
6.EDIT: As #Parfait pointed out, tblTemp does not exist in scope of the SQLReplace statement. You should do an INNER JOIN to fix that: <--AWESOME!!
strWkEnd = Me.cmbWkEnd
strSQL = "UPDATE tblHrs INNER JOIN tempWkEndHrs ON tblHrs.TASK = tempWkEndHrs.TASK SET tblHrs.[" & strWkEnd & "] = tempWkEndHrs.[" & strWkEnd & "] "
Works! >:P
I didn't receive any answers to this post so obviously I need to write better questions, I figured it was mud...Thanks for the ~21 Views ?lol.

Run Time error 3061 Too Few parameters. Expected 6. Unable to update table from listbox

All,
I am running the below SQL and I keep getting error 3061. Thank you all for the wonderful help! I've been trying to teach myself and I am 10 days in and oh my I am in for a treat!
Private Sub b_Update_Click()
Dim db As DAO.Database
Set db = CurrentDb
strSQL = "UPDATE Main" _
& " SET t_Name = Me.txt_Name, t_Date = Me.txt_Date, t_ContactID = Me.txt_Contact, t_Score = Me.txt_Score, t_Comments = Me.txt_Comments" _
& " WHERE RecordID = Me.lbl_RecordID.Caption"
CurrentDb.Execute strSQL
I am not sure but, you can try somethink like that
if you knom the new value to insert in the database try with a syntax like this one
UPDATE table
SET Users.name = 'NewName',
Users.address = 'MyNewAdresse'
WHERE Users.id_User = 10;
Now, if you want to use a form (php)
You have to use this
if(isset($_REQUEST["id_user" ])) {$id_user = $_REQUEST["id_user" ];}
else {$id_user = "" ;}
if(isset($_REQUEST["name" ])) {$name= $_REQUEST["name" ];}
else {$name = "" ;}
if(isset($_REQUEST["address" ])) {$address= $_REQUEST["adress" ];}
else {$adress= "" ;}
if you use mysql
UPDATE table
SET Users.name = '$name',
Users.address = '$adress'
WHERE Users.id_User = 10;
i don't know VBA but I will try to help you
Going on from my comment, you first need to declare strSQL as a string variable.
Where your error expects 6 values and access doesn't know what they are. This is because form objects need to be outside the quotations of the SQL query, otherwise (as in this case) it will think they are variables and obviously undefined. The 6 expected are the 5 form fields plus 'strSQL'.
Private Sub b_Update_Click()
Dim db As DAO.Database
dim strSQL as string
Set db = CurrentDb
strSQL = "UPDATE Main" & _
" SET t_Name = '" & Me.txt_Name & "'," & _
" t_Date =#" & Me.txt_Date & "#," & _
" t_ContactID =" & Me.txt_Contact & "," & _
" t_Score =" & Me.txt_Score & "," & _
" t_Comments = '" & Me.txt_Comments & "'," & _
" WHERE RecordID = '" & Me.lbl_RecordID.Caption & "';"
CurrentDb.Execute strSQL
end sub
Note how I have used double quotes to put the form fields outside of the query string so access knows they aren't variables.
If your field is a string, it needs encapsulating in single quotes like so 'string'. If you have a date field it needs encapsulating in number signs like so #date# and numbers/integers don't need encapsulating.
Look at the code I have done and you can see I have used these single quotes and number signs to encapsulate certain fields. I guessed based on the names of the fields like ID's as numbers. I may have got some wrong so alter where applicable... Or comment and I will correct my answer.

ACCESS/SQL - Too Few Parameters

I am using the code below to create a new record in the "transactions table" the second line of the insert statement is throwing an error: Too few parameters. I have double checked and all of the field names are correct. What else could cause this type of error?
' Modify this line to include the path to Northwind
' on your computer.
Set dbs = CurrentDb
Dim vblCustomerID As String
Dim vblMealType As String
Dim Charge As Currency
Dim vblDate As String
vblDate = Format(Date, "yyyy-mm-dd")
txtCustomerID.SetFocus
vblCustomerID = txtCustomerID.Text
txtMealType.SetFocus
vblMealType = txtMealType.Text
txtCharge.SetFocus
vblCharge = txtCharge.Text
dbs.Execute "INSERT INTO dbo_Transactions" _
& "(CustomerID, MealID, TransactionAmount, TransactionDate) VALUES " _
& "(" & vblCustomerID & ", " & vblMealType & ", " & vblCharge & ", " & vblDate & ");"
dbs.Close
As others have suggested, using a parameterized query is a much better way of doing what you're attempting to do. Try something like this:
Dim qdf As DAO.QueryDef
Set qdf = dbs.CreateQueryDef("", _
"PARAMETERS prmCustomerID Long, prmMealID Long, prmTransactionAmount Currency, prmTransactionDate DateTime;" & _
"INSERT INTO dbo_Transactions (CustomerID, MealID, TransactionAmount, TransactionDate) " & _
"VALUES ([prmCustomerID], [prmMealID], [prmTransactionAmount], [prmTransactionDate]) ")
qdf!prmCustomerID = txtCustomerID.Value
qdf!prmMealID = txtMealType.Value
qdf!prmTransactionAmount = txtCharge.Value
qdf!prmTransactionDate = Date()
qdf.Execute dbFailOnError
Set qdf = nothing
Do any of the text fields you're loading into your vbl fields contain special characters like these?
, ' "
All of those in a text field in a perfectly good SQL Insert command could screw things up, I bet that's what happening here.
It would be better if you actually use parameters here to, rather than loading the text in textboxes directly into your SQL queries, since you're opening yourself up to SQL Injections. What if someone types
"; Drop Table dbo_Transactions;
in one of your textboxes and you run this query? Your database is then totally screwed up because someone just deleted one of your tables.
A few links to info on using Parameters to prevent this issue, which I'll bet will also fix the too few parameters issue you're having.
http://forums.asp.net/t/886691.aspx
http://sqlmag.com/blog/t-sql-parameters-and-variables-basics-and-best-practices

Use a ComboBox Value as part of an SQL Query? (MS Access 2010-2013)

I have a Database that we use to create Bills of Materials from Tags in AutoCAD. Because of the nature of this, I need to create 3 separate queries. One for our "Steel", one for our
"Non-Steel", and one for our "Uncut Tubes".
The SQL for the Queries is as follows:
Steel:
SELECT DISTINCTROW Sum([CUT-LENGTH-WEIGHT]) AS [SumOfCUT-LENGTH-WEIGHT], Sum([CUT-SHEET-WEIGHT]) AS [SumOfCUT-SHEET-WEIGHT], Sum([TOTAL-SHEETING-WEIGHT]) AS [SumOfTOTAL-SHEETING-WEIGHT], Sum([TOTAL-ITEM-WEIGHT]) AS [SumOfTOTAL-ITEM-WEIGHT]
FROM [13-1302 Cut-Lengths];
Non-Steel:
SELECT tbl2013BOM.fJobID, Sum(tbl2013BOM.fWeight) AS SumOffWeight
FROM tbl2013BOM
GROUP BY tbl2013BOM.fJobID
HAVING (((tbl2013BOM.fJobID)=23));
Uncut Tubes:
SELECT DISTINCT [13-1302 Cut-Lengths].[TOTAL-LENGTH-WEIGHT], [13-1302 Cut-Lengths].MATERIAL, [13-1302 Cut-Lengths].ORDER
FROM [13-1302 Cut-Lengths]
ORDER BY [13-1302 Cut-Lengths].ORDER;
I have a ComboBox that chooses the Job Number (For Main and Uncut Tubes, e.g. 13-1302) and a Textbox that displays the JobID (For Non-Steel).
Is there a way that I can set up the SQL shown above to look at the ComboBox and TextBox Values, instead of me having to change them by hand?
EDIT
I figured it all out now. (Thank you Elias)
Basically, I cannot use a Field on a table as a RecordSource in SQL, in other words, Combo26 cannot be the Table in an SQL Query. HOWEVER, what CAN be done is to use VBA to inject that value into an SQL Definition, then use that definition as a Recordsource.
I will place the code for my Button below so anyone can use it and reference it:
Private Sub Command27_Click()
Dim dbs As Database
Dim rstSQL As DAO.Recordset
Dim strSQL As String
Dim strSQL2 As String
Dim strSQL3 As String
Dim Field As String
Set dbs = CurrentDb
Field = [Forms]![frmBOM_Combined]![Text26].[Value]
strSQL = "SELECT DISTINCTROW Sum([CUT-LENGTH-WEIGHT]) AS [SumOfCUT-LENGTH-WEIGHT], Sum([TOTAL-SHEETING-WEIGHT]) AS [SumOfTOTAL-SHEETING-WEIGHT], Sum([TOTAL-ITEM-WEIGHT]) AS [SumOfTOTAL-ITEM-WEIGHT] FROM " & "[" & [Forms]![frmBOM_Combined]![Text26].[Value] & "]" & ";"
strSQL2 = "SELECT tbl2013BOM.fJobID, Sum(tbl2013BOM.fWeight) AS SumOffWeight FROM tbl2013BOM GROUP BY tbl2013BOM.fJobID HAVING (((tbl2013BOM.fJobID)= " & [Forms]![frmBOM_Combined]![Combo25].[Value] & "));"
strSQL3 = "SELECT DISTINCT [TOTAL-LENGTH-WEIGHT], [MATERIAL], [ORDER] FROM " & "[" & [Forms]![frmBOM_Combined]![Text26].[Value] & "]" & " ORDER BY [ORDER];"
Debug.Print strSQL
Debug.Print strSQL2
Debug.Print strSQL3
DoCmd.OpenForm ("frmEstWeight")
Forms!frmEstWeight.RecordSource = strSQL
Forms!frmEstWeight.frmTestBomWeight.Form.RecordSource = strSQL2
Forms!frmEstWeight.frmTotalLengthWeight.Form.RecordSource = strSQL3
End Sub
This is working exactly as it should with no errors or anything.
This is within a form correct?
If so, replace the manual values you put in with
REST OF THE QUERY HERE " & Me!Controlname.value & " REST OF THE QUERY HERE
and if you are using something with a control source then just reset the control source value.
me!ControlWithResult.control source = "SELECT tbl2013BOM.fJobID, Sum (tbl2013BOM.fWeight) AS SumOffWeight
FROM tbl2013BOM
GROUP BY tbl2013BOM.fJobID
HAVING (((tbl2013BOM.fJobID)=" & me!controlname.value & "));"
For Non-Steel try:
On the VBA for the popup form
me!Combo25.rowsource = "SELECT tbl2013BOM.fJobID, Sum(tbl2013BOM.fWeight) AS SumOffWeight
FROM tbl2013BOM
GROUP BY tbl2013BOM.fJobID
HAVING (((tbl2013BOM.fJobID)=" & forms!MAINFORMNAME! &"));

VBA string length problem

I have an Access application where everytime a user enters the application, it makes a temp table for that user called 'their windows login name'_Temp. In one of my reports I need to query using that table, and I can't just make a query and set it as the recourdsource of the report, since the name of the table is always different.
What I tried then was to programatically set the recordset of the report by running the query and setting the form's recordset as the query's recordset. When I tried this, it kept giving me an error about the query.
I tried to debug, and I found that the string variable isn't able to contain the whole query at once. When I ran it with break points and added a watch for the string variable, it shows me that it cuts off the query somewhere in the middle.
I've experienced this problem before, but that was with an UPDATE query. Then, I just split it into two queries and ran both of them separately. This one is a SELECT query, and there's no way I can split it. Please help!
Thank you
Heres what I've tried doing:
ReturnUserName is a function in a module that returns just the login id of the user
Private Sub Report_Open(Cancel As Integer)
Dim strQuery As String
Dim user As String
user = ReturnUserName
strQuery = "SELECT " & user & "_Temp.EmpNumber, [FName] & ' ' & [LName] AS [Employee Name], " & _
"CourseName, DateCompleted, tblEmp_SuperAdmin.[Cost Centre] " & _
"FROM (tblCourse INNER JOIN (" & user & "_Temp INNER JOIN tblEmpCourses ON " & _
user & "_Temp.EmpNumber = EmpNo) ON tblCourse.CourseID = tblEmpCourses.CourseID) " & _
"INNER JOIN tblEmp_SuperAdmin ON " & user & "_Temp.EmpNumber = tblEmp_SuperAdmin.EmpNumber" & _
"WHERE (((" & user & "_Temp.EmpNumber) = [Forms]![Reports]![txtEmpID].[Text])) " & _
"ORDER BY CourseName;"
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim rsCmd As ADODB.Command
Set rsCmd = New ADODB.Command
rsCmd.ActiveConnection = CurrentProject.Connection
rsCmd.CommandText = strQuery
rs.Open rsCmd
Me.Recordset = rs
rs.Close
End Sub
This what strQuery contains when I add a breakpoint on rsCmd.CommandText = strQuery:
SELECT myusername_Temp.EmpNumber, [FName]
& ' ' & [LName] AS [Employee Name],
CourseName, DateCompleted,
tblEmp_SuperAdmin.[Cost Centre] FROM
(tblCourse INNER JOIN (myusername_Temp
INNER JOIN tblEmpCourses ON
myusername_Temp.EmpNumber = EmpNo) ON
tblCourse.CourseID=
(It's all one line, but I've written it like this because the underscores italicize the text)
And the error I get says Run Time Error: Join not Supported.
Not quite what I was hoping for, but guessing, for:
strQuery = "long query goes here"
Try:
strQuery = "some long query goes here "
strQuery = strQuery & "more query goes here "
BASED ON NEW INFORMATION:
strQuery = "SELECT " & user & "_Temp.EmpNumber, [FName] & ' ' & [LName] AS [Employee Name], " & _
"CourseName, DateCompleted, tblEmp_SuperAdmin.[Cost Centre] " & _
"FROM (tblCourse " & _
"INNER JOIN tblEmpCourses ON tblCourse.CourseID = tblEmpCourses.CourseID) " & _
"INNER JOIN (Temp INNER JOIN tblEmp_SuperAdmin " & _
"ON Temp.EmpNumber = tblEmp_SuperAdmin.EmpNumber) " & _
"ON Temp.EmpNumber = tblEmpCourses.EmpNo " & _
"WHERE " & user & "_Temp.EmpNumber = " & [Forms]![Reports]![txtEmpID] & _
" ORDER BY CourseName;"
Note that in VBA:
& [Forms]![Reports]![txtEmpID].[Text] &
That is, the reference to the form must go outside the quotes so you get the value.
NEW INFORMATION #2
Your best bet would be to add these tables to the Access query design window and create the joins that you want, then switch to SQL view and use the string generated for you. I do not believe that the string is too long, only that the SQL is incorrect. The SQL I posted above should work, but it may not be what you want.
You can programmatically create a querydef that fits the user. So, when your report is called, you
Delete LoginName_Query_Temp (CurrentDb.QueryDefs.Delete), if it already exists.
Create the querydef (CurrentDB.CreateQueryDef), using LoginName_Temp as the table name.
Set the RecordSource of your Report to LoginName_Query_Temp.
Open the report.
I don't see what purpose the table myusername_Temp serves here. Is that where the name fields are? If so, avoid the join entirely:
Dim lngEmpNumber As Long
Dim strName As String
Dim strSQL As String
lngEmpNumber = Forms!Reports!txtEmpID
strName = DLookup("[FName] & ' ' & [LName]", "myusername_Temp", "EmpNumber=" & lngEmpNumber
strSQL = "SELECT " & Chr(34) & strName & Chr(34) & " AS [Employee Name], " & _
"CourseName, DateCompleted, tblEmp_SuperAdmin.[Cost Centre] " & _
"FROM tblCourse " & _
"INNER JOIN tblEmpCourses " & _
"ON tblCourse.CourseID = tblEmpCourses.CourseID) " & _
"INNER JOIN tblEmp_SuperAdmin " & _
"ON tblEmp_SuperAdmin.EmpNumber = tblEmpCourses.EmpNo " & _
"WHERE tblEmp_SuperAdmin.EmpNumber = " & lngEmpNumber & _
" ORDER BY CourseName;"
Now, the parentheses may need to be changed in the join (I always do my equi-joins in the Access QBE and let it take care of the getting the order and parens correct!), and my assumptions about the purpose of the temp table may be wrong, but I don't see it being used for anything other than as an intermediate link between tables, so I guessed it must be there to provide the name fields.
If that's wrong, then I'm at a loss as to why the temp table needs to be there.
Also, in your second post you referred to the control on the form as:
Forms!Reports!txtEmpID.Text
...the .Text property of Access controls is accessible only when the control has the focus. You could use the .Value property, but since that's the default property of Access controls, you should just stop after the name of the control:
Forms!Reports!txtEmpID
...you'll see this is how I did it in my suggested code.
I find the idea of your name-based temp table to be highly problematic to begin with. Temp tables don't belong in a front end, and it's not clear to me that it is actually a temp table. If it's temp data, put it in a shared table and key the record(s) to the username. Then you don't have to worry about constructing the table name on the fly.