I have two tables (lets call them Parameters 1 and 2) which both have a many-many relationship with a third table (Options). I need to group the third table records into three groups:
Those exclusively related to [specific Parameter 1 record],
Those exclusively related to [specific Parameter 2 record] and
Those related to both [specific Parameter 1 record] and [specific Parameter
2 record].
I can ignore Option records not related to either of them.
I need to be able to specify which Parameter 1 and 2 records apply in a form (using combo boxes), and have VBA juggle the three lists in the background, updating them as the Option records they contain are "used" elsewhere in the form (with check boxes).
At the risk of asking a bad question I'll submit the code I have - even though it's not a code that fails, just the framework for one that isn't even finished enough to debug yet. I simply haven't got the tools to complete it, as I don't know what methods/properties of what things to use to do it, and can't seem to find the answers in my own research thus far. Comments directing me to other resources will be appreciated, even if you don't have an answer that you're sure is best practice.
Function SetOptions()
If IsNull(cmbParam1) Or IsNull(cmbParam2) Then
MsgBox "You must select both an Param1 and a Param2!", vbCritical, "Wait!"
Exit Function
End If
'Recordsets of allowed Options
Dim Param1Opt, Param2Opt, OverlapOpt
'create recordset of tblOption.Option(s) referenced in qryPr1Opt with Param1 from cmbParam1
Param1Opt = CurrentDb.OpenRecordset("SELECT tblPr1Opt.Option FROM tblPr1Opt " &_
"WHERE Param1 = '" & cmbParam1 & "';")
'create recordset of tblOption.Option(s) referenced in qryPr2Opt with Param2 from cmbParam2
Param2Opt = CurrentDb.OpenRecordset("SELECT tblPr2Opt.Option FROM tblPr2Opt " &_
"WHERE Param2 = '" & cmbParam2 & "';")
'create recordset of tblOption.Option(s) in qryOptOvrlp with Param2 and Param1 from form
OverlapOpt = CurrentDb.OpenRecordset("SELECT qryOptOvrlp.Option FROM qryOptOvrlp " &_
"WHERE Param1 = '" & cmbParam1 & "' AND Param2 = '" & cmbParam2 & "';")
OverlapNum = Param1Num + Param2Num
'Steps remaining:
'1. Get Param1Opt and Param2Opt to only include Options not in overlap
For Each oOpt In OverlapOpt
For Each aOpt In Param1Opt
If aOpt.Value = oOpt.Value Then
'filter this record out of Param1Opt
End If
Next aOpt
For Each gOpt In Param2Opt
If gOpt.Value = oOpt.Value Then
'filter this record out of Param2Opt
End If
Next gOpt
Next oOpt
'2. Get the data in Param1Opt, Param2Opt and OverlapOpt, as well as their
'corresponding Nums to be accessible/editable in other functions/subs
End Function
You can reference the values of controls in SQL statements run in the context of Access, using the following syntax:
Forms!FormName!ControlName
or using square brackets if needed:
Forms![Form Name]!ControlName
Therefore, instead of opening multiple recordsets, you can express each of your points as a single SQL statement with joined tables. You can then either set the RowSource of a combobox or listbox to the statement (if you are only using the statement in one place); or you can save the statement as an Access query, and use the query name as the RowSource (if you need the statement in multiple places).
Given the following schema:
and two comboboxes: cmbParam1 and cmbParam2 on a form named Form1, you can use SQL statements as follows:
1. Records from Options which match tblPr1Opt but have no match in tblPr2Opt
SELECT DISTINCTROW Options.Option
FROM (Options
INNER JOIN tblPr1Opt ON Options.Option = tblPr1Opt.Option)
LEFT JOIN tblPr2Opt ON Options.Option = tblPr2Opt.Option
WHERE tblPr2Opt.Option IS NULL
AND tblPr1Opt.Param1 = Forms!Form1!cmbParam1
Or using the query designer (note the arrow head next to tblPr2Opt; this indicates a left join):
2. Records from Options which match tblPr2Opt but have no match in tblPr1Opt:
SELECT DISTINCTROW Options.Option
FROM (Options
INNER JOIN tblPr2Opt ON Options.Option = tblPr2Opt.Option)
LEFT JOIN tblPr1Opt ON Options.Option = tblPr1Opt.Option
WHERE tblPr1Opt.Option IS NuLL
AND tblPr2Opt.Param2 = Forms!Form1!cmbParam2;
or in the query designer:
3. Records from Options which match on both:
SELECT Options.Option
FROM (Options
INNER JOIN tblPr1Opt ON Options.Option = tblPr1Opt.Option)
INNER JOIN tblPr2Opt ON Options.Option = tblPr2Opt.Option
WHERE tblPr1Opt.Param1 = Forms!Form1!cmbParam1
AND tblPr2Opt.Param2 = Forms!Form1!cmbParam2
Or in the query designer:
I am trying to get an Access SQL query that does this (semi-pseudocode below)
UPDATE SignIn SET SignIn.Complete=True, CompletedBy=(Select [FirstName] & " " & [LastName] AS EmployeeName From UserList where POid = Forms!HiddenUserCheck!txtPOid), CompletedDateTime=Now()
So after the query would run, the data in the database would look like
Complete EmployeeName CompletedDateTime
True John Smith 3/23/2017 8:34:10 AM
THe update query doesn't work because of syntax and not sure how to fix it.
The exact error message is
Invalid Memo, OLE, or HyperLink Object in subquery '[FirstName] & " "
& [LastName]'.
The query could be throwing a fit because of the Double Exclamation marks. Instead of
Forms!HiddenUserCheck!txtPOid
Try
Forms!HiddenUserCheck.txtPOid
You also have an extra ) at the end of your WHERE Statment
OK, then your issue may be that the subquery may return more than one record:
UPDATE
SignIn
SET
SignIn.Complete=True,
CompletedBy =
(Select First([FirstName] & " " & [LastName]) AS EmployeeName
From UserList
Where POid = Forms!HiddenUserCheck!txtPOid),
CompletedDateTime = Now()
If your name fields are Memo/LongText fields, that may be the source of the error. If so, try:
UPDATE
SignIn
SET
SignIn.Complete=True,
CompletedBy =
(Select First(Left([FirstName], 255) & " " & Left([LastName], 255)) AS EmployeeName
From UserList
Where POid = Forms!HiddenUserCheck!txtPOid),
CompletedDateTime = Now()
Edit.
You may try using DLookup for the subquery:
UPDATE
SignIn
SET
SignIn.Complete=True,
CompletedBy =
DLookup("[FirstName] & " " & [LastName]", "UserList", "POid = " & Forms!HiddenUserCheck!txtPOid & ""),
CompletedDateTime = Now()
I'm trying to call a procedure in a module that needs some arguments, thus:
MySQL code to be executed (extracted from the module's procedure):
Sub InsertRecord(ByVal tbl As String, ByVal cols() As String, ByVal params() As String, ByVal colCondition As String, ByVal paramCondition As String) 'As String
:
:
comA.CommandText = "INSERT INTO " & tbl & " (" & newCols & ") SELECT * FROM (SELECT #params) AS tmp "
comA.CommandText &= "WHERE NOT EXISTS (SELECT " & newCols & " FROM " & tbl & " WHERE " & colCondition & " = #param) limit 1"
comA.Parameters.AddWithValue("#param", paramCondition)
comA.Parameters.AddWithValue("#params", newParams)
:
:
End Sub
Call Code:
myModule.SaveInfo("myprod", {"col_a", "col_b", "col_c", "col_d", "col_e", "col_f", "col_g", "col_h"}, _
{val_a, val_b, val_c, val_d, val_e, val_f, val_g, val_h}, "col_b", val_b)
hint: newCols and newParams (obtained from cols() and params() respectively) are comma-delineated lists of columns of the table in question and values to be inserted respectively.
When i run my code, i get the error: column count doesn't match value count at row 1
Please how do i address this issue? I've been on it for some days now.
Thanks in advance.
Edit:
I decided to write the code on the sub, instead of using a module. Here is the full subroutine:
Private Sub SaveProduct(ByVal p_code As String, ByVal b_id As String, ByVal m_id As String, _
ByVal c_id As String, ByVal des As String, ByVal o_det As String)
'modNewData.InsertRecord("products", {"prd_code", "brnd_id", "mnu_id", "cat_id", "prd_description", "prd_details", "prd_create_date", "prd_last_update"}, _
' {p_code, b_id, m_id, c_id, des, o_det, Date.Now.ToShortDateString, Date.Now.ToShortDateString}, "brnd_id", b_id)
con = New MySqlConnection("Server=localhost; Database=inventory_db; Uid=root; Pwd=;")
comA = New MySqlCommand
'INSERT NEW RECORD.
comA.CommandText = "INSERT INTO products (prd_code, brnd_id, mnu_id, cat_id, prd_description, prd_details, prd_create_date, prd_last_update) "
comA.CommandText &= "SELECT * FROM (SELECT #params) AS tmp "
comA.CommandText &= "WHERE NOT EXISTS (SELECT prd_code, brnd_id, mnu_id, cat_id, prd_description, prd_details, prd_create_date, prd_last_update FROM products "
comA.CommandText &= "WHERE brnd_id = #param) limit 1"
comA.Parameters.AddWithValue("#param", b_id)
comA.Parameters.AddWithValue("#params", {p_code, b_id, m_id, c_id, des, o_det, Date.Now.ToShortDateString, Date.Now.ToShortDateString})
comA.Connection = con
con.Open()
comA.ExecuteNonQuery()
con.Close()
'Release used up components
comA.Parameters.Clear()
comA.Dispose()
comA = Nothing
con = Nothing
MsgBox("done.")
At this point, i don't seem to know what i'm doing, but I know what i want to achieve - insert a new record in a table. I strongly believe that there's a problem with my sql code, but can't figure out exactly what it is. Your help is highly needed at this point. Thanks in advance.
EDIT 2:
I tweaked the mysql insert code above, and now i can successfully insert new record to my table. But one more problem exists: I get this <Unable to read data> error in my datetime and timestamp columns respectively.
id prd_code brnd_id mnu_id cat_id desc details create_date (datetime) last_update(timestamp)
10 PM-16326 10 9 6 Red NULL 10/15/2013 8:22:00 AM 7/16/2015 9:13:03 AM
17 PM-55326 23 28 11 Olive oil n/a <Unable to read data> <Unable to read data>
Here's the new insert code:
'INSERT NEW RECORD.
comA.CommandText = "INSERT INTO products (prd_code, brnd_id, mnu_id, cat_id, prd_description, prd_details, prd_create_date, prd_last_update) "
comA.CommandText &= "SELECT * FROM (SELECT #p_code, #b_id, #m_id, #c_id, #des, #o_det, '11/11/2015 9:00:00 AM', '11/12/2015 9:00:00 AM') AS tmp "
comA.CommandText &= "WHERE NOT EXISTS (SELECT prd_code, brnd_id, mnu_id, cat_id, prd_description, prd_details, prd_create_date, prd_last_update FROM products "
comA.CommandText &= "WHERE brnd_id = #b_id) limit 1"
comA.Parameters.AddWithValue("#p_code", p_code)
comA.Parameters.AddWithValue("#b_id", b_id)
comA.Parameters.AddWithValue("#m_id", m_id)
comA.Parameters.AddWithValue("#c_id", c_id)
comA.Parameters.AddWithValue("#des", des)
comA.Parameters.AddWithValue("#o_det", o_det)
If i replaced the two dates above with date.now.tostring, I'll get the error: you have repeated columns...
I really need your help guys. Thanks in advance.
The columns you pass to the procedure (which do match) are called cols, but in the query you use newCols.
The MySQL error you get means that the values you insert are not in the same number as the columns you say they should fill: you cannot insert four values into five columns, or three.
So what is happening is clearly that you do something to retrieve newCols from cols, in the part of code you have omitted. Probably, depending on some condition, you add some columns (or leave some out). That is what is causing your trouble. You should modify at the same time, apparently, the value of params into some other value, possibly newParams.
Also, perhaps the condition is not always true, and you observe the function misbehaving only occasionally, or passing some test (because that test does not trigger the column-modifying bug).
I use MySql.Data.MySqlClient.MySqlCommand and MySqlConnection
Public fillGridCmdTxt As String = "SELECT tblItems.part_num AS Part#, tblCategory.category_description AS Category, " _
& " tblItems.item_name AS 'Item Name', tblItems.item_desc AS Description, " _
& "tblItems.item_qty AS Qty, tblUnit.unit_name AS Unit, tblItems.item_price AS 'Selling Price(Php)' " _
& "FROM tblUnit INNER JOIN tblItems ON tblUnit.unit_id = tblItems.unit_id INNER JOIN tblCategory " _
& "ON tblItems.category_id = tblCategory.category_id "
and when i use executeNonQuery
on MySqlCommand, it gives me an error...
It says that "Unkown table '*tblItems in field list*" even the table is really existing on my database... a little help please?
You need to enclose Part# between quotes.
The # sign starts a comment in MySQL, so your whole statement is read as just SELECT tblItems.part_num AS Part. The error message tells you that you are naming a table in the fields list that you didn't specify in the FROM list (because the FROM list got commented out).
I have been racking my brain over this all day today.
I have the following ASP code that uses a Request.Querystring input from a dropdown box
to launch a select statement. The querystrinch does show in the ?= URL but will only work on
columns in the Microsoft SQL DB that are numeric. I cant lookup names or simple 3 character fields.
CODE:
If Request.QueryString("m") > 0 Then
filterID = Request.QueryString("m")
filterColmn = "imDegree"
Else filterID = 0
End If
If filterID > 0 Then
SQlQuery = "SELECT * FROM v_InternImport WHERE iID IN (SELECT iID FROM v_InternImport WHERE " & filterColmn & " = " & filterID & ")"
End If
End If
I understand that this select statement as a sub select stament in it but I cant even get a staight reuturn from my DB. The select statement references the same view that populates the main asp page that loads before and the shows fine?
When you pass a string to SQL Server, you need to surround it with single quotes.
When you pass a number, you don't use the quotes.
So, when you say (summarizing)
SELECT * FROM table WHERE filterColumn = filterID
you should be sending a number.
To match a string:
SELECT * FROM table WHERE filterColumn = 'filterID'
This assumes that you have solved any other problems mentioned by the commenters about whether you even have a value in the filterID variable. I heartly concur with the recommendation to use parameterized queries.
Edit: The single quotes go inside the double quotes.
SQlQuery = "SELECT * FROM v_InternImport
WHERE iID IN (SELECT iID FROM v_InternImport
WHERE " & filterColmn & " = '" & filterID & "')"