MS Access: How to set outer join in constraint in VBA? - sql

When I create a relationship between two tables manually at Database Tools > Relationships, Access lets me set the join properties so that it is either an inner join or a left or right outer join:
But when I create the relationship in VBA:
sSQL = "ALTER TABLE [" & sTable1 & "] ADD CONSTRAINT [" & sTable1 & "] " & _
"FOREIGN KEY ([" & sKey & "]) REFERENCES [" & sTable2 & "]([" & sKey & "]);"
oDB.Execute sSQL
it creates the relationship as an inner join. I can see this by going to Database Tools > Relationships and looking at the relationship created by VBA:
I do not see a way to tell VBA what join properties to use, and it apparently decides on its own to make an inner join. (Another problem is that the little infinity symbol on the left side of the connector line means that Access thinks this is a one-to-many relationship, but since the linked fields are the primary key, it's one-to-one, as seen in the first image above.)
Microsoft has documentation on this process at:
ALTER TABLE statement (Microsoft Access SQL)
CONSTRAINT clause (Microsoft Access SQL)
Modify a table's design using Access SQL
Create Foreign Key Relationships
There is also documentation on how to do this in DAO instead of SQL:
Database.CreateRelation method (DAO)
I don't see anything in any of that that allows me to choose the join properties.
I need the table relationship to be an outer join so that it includes all the records of one table and only the records of the second table in which the primary keys are equal. How can I create that relationship in VBA?

Updates:
Looking at this more, you will need the attributes value of the relation object.
Problem is, the attribute constants are bitwise and a bit elusive in the documentation. A value of 0 is the default you see and the rest have to be added up.
So this is what you can do:
Create a relationship in your database in the way you want it (left join, right join etc) and save. Assuming northwind is your database, in a function or module:
Set dbsNorthwind = OpenDatabase("Northwind.mdb")
With dbsNorthwind
' Display the attributes of the Northwind database's
' relations.
Debug.Print "Attributes of relations in " & _
.Name & ":"
For Each relLoop In .Relations
Debug.Print " " & relLoop.Name & " = " & _
relLoop.Attributes
Next relLoop
.Close
End With
The relation you created should show the attribute value you need.
There is also a reference you can use here.
Now when you go to create your own relation, you simply use the CreateRelation function (as in the documentation) and set the attributes you need like so:
Set dbsNorthwind = OpenDatabase("Northwind.mdb")
With dbsNorthwind
Set relNew = .CreateRelation(Name, Table, ForeignTable, Attributes)
' Add join fields
relNew.Fields.Append relNew.CreateField("newFieldName")
relNew.Fields!newFieldName.ForeignName = "joinfieldName"
.Relations.Append relNew
.Close
End With
If for example you wanted a left join, the value you set for "Attributes" would be a combination of dbRelationLeft + another attribute constant represented as one numeric value.

Related

Operation must use and updatable query. (Error 3073)

What is wrong with my logic below, is there any alternative to get calculatable column which will sum Balances for every unique KEY ?
Purpose: To create a summary column, calculation of Balances for each unique Key created ( Sort Code + Source Account) which will be used later to define whether acc type is Dr/Cr.
Code: below code should create summary column , but every time it triggers error depicted in attached screenshot.
***' Creating Sum of Balances based on Key , to differtiate Dr/Cr Account types
DoCmd.RunSQL "ALTER TABLE Output_File ADD Summing varchar(255)"
DoCmd.RunSQL "UPDATE Output_File SET Summing =" _
& "(SELECT SUM(Output_File.CURR_VALUE)" _
& " FROM Output_File GROUP BY Output_File.`UNIQUE KEYS`)"***
Error:
Error
In MS Access SQL, update queries must be updateable or not read-only. Any use of subqueries renders the query read-only. See Allen Browne's Why is my query read-only? One workaround is to use domain aggregates such as DSum available in Access SQL and VBA.
Ideally, too, consider using a saved query and avoid the need of building long SQL statements in VBA and have to worry about line breaks and concatenations. Below assumes UNIQUE KEYS is a number field. If text field, wrap in single quotes. If a date field, wrap in hashtags/pound symbols.
SQL (save as stored query)
UPDATE Output_File o
SET Summing = DSum("CURR_VALUE", "Output_File", "`UNIQUE KEYS` = " & o.`UNIQUE KEYS`)
VBA (reference above saved query)
DoCmd.OpenQuery "mySavedQuery" ' NO NEED TO CLOSE ACTION QUERIES
CurrentDb.Execute "mySavedQuery" ' ALTERNATIVE CALL

OleDBCommands: executing two commands and checking

I am trying to perform some OLEDB commands between a list of dictionary values and an access database. I am wondering if it is possible to check if one column in the access database matches the key of a dictionary, if you find the key that matches check the keyvalue in the dictionary to the access database quantity in another column. I am just wondering if this is possible since I am new to the SQL in vb.net commands.
I wanted to run these two queries but I am not sure if this is even possible. I tried to find some documents on this but I came out short. Anything would help!
sqlQry = "SELECT Column1 FROM [Table] WHERE Column1 = '" & Key & "' "
sqlQry = "SELECT Column2 FROM [Table] WHERE Column2 < " & Value & " "

Access VBA Putting name of a Field as a Record

I am with a little bit of a coding problem that I don't know how to solve. I want to put in the table as a record a field name of another table in the same Database.
I will give you an example:
Table1
What I have
Table 2
What I want
The table 1 is update weekly from an external source so I need to record the field name as a record in the second table using VBA language. Does anybody knows if it's possible?
Thank You in advance
You could do something like this
Dim db As Database
Dim fld As Field
Dim sql As String
Set db = CurrentDb
For Each fld In db.TableDefs("YourTable").Fields
sql = "Insert into YourSummaryTable([Date], Hours) select '" & fld.Name & "', sum([" & fld.Name & "]) as s from YourTable"
DoCmd.RunSQL sql
Next fld
Note that you've used a reserved word Date as a fieldname, which isn't best practice and requires the use of the square brackets in the query.

Combining two SQL Update Statements in Access with VBA

I have two update statements:
Dim newvalue As Integer
sSQL = "UPDATE Workstations SET SID = 0 WHERE SID = txtID3"
DoCmd.RunSQL sSQL
AND
Dim strsql As String
strsql = "UPDATE Workstations SET [SID] = " & newvalue & " WHERE [Workstation ID] = '" & selectedwks & "'"
DoCmd.RunSQL strsql
When I run my code, it prompts me with two yes/no windows right after another saying whether if I want to update the table or not.
Is it possible to write those two update statements together so that I'm only prompted once? If yes, how should I do it?
Thanks in advance
I do not see these two update statements as being compatible. You are potentially (and quite likely) targeting two different rows (or sets of rows if SID and [Workstation ID] are not unique).
If you are are actually trying to target a row where the SID AND [WorkStation ID] are a match on what the user inputs, then just change your WHERE clause to include both columns separated by AND. Else, I am not sure you can logically accomplish what you're asking.

Automatically updating/duplicating a table in Microsoft Access with VBA

Back again! So I am currently trying to programmatically have a table (Table2) update after a button is pressed. I would like for Table2 to resemble exactly another table (Table1). I'm going through this effort because Access does not allow double relationships and I have need to create one. I will therefore have two tables containing all the contact info.
I tried deleting Table2 and then creating another copy of Table1 and saving it as Table2. This would have worked is Microsoft Access didn’t throw an error because I am deleting a Table that has established relationships. So I then tried to programmatically delete and then create the appropriate relationships. However, this turns out to be a tedious exercise. A little too tedious for my taste.
My next thought is to create an append query that automatically looks for differences between the two tables and updates Table2 accordingly. The problem is that I have no idea how to structure the SQL statement for such an append query. Also is there an easier way to do this using VBA that I am missing? Thanks in advance for your help!
There is no need to go to all this trouble. You can have double relationships in MS Access. Simply add the table as many times as you need it to the relationship design window, you will get Table1, Table1_1, Table1_2 and so on, but they are all just aliases for Table1. You can now add self-joins and as many relationships as you need.
Like so:
*People*
PersonID *People_1*
ManagerID -- > PersonID
It sounds like you are able to append from Table1 to Table2 without running afoul of any relationship. If that is true, you can empty out Table2, then append all the rows from Table1.
Dim cn As Object
Set cn = CurrentProject.Connection
cn.Execute "DELETE FROM Table2"
If Table2 includes an autonumber field, reset its seed value.
cn.Execute "ALTER TABLE Table2" & vbCrLf & _
"ALTER COLUMN autonum_fld COUNTER(1, 1)"
Then do the append ...
cn.Execute _
"INSERT INTO Table2 (autonum_fld, text_field, long_int_field)" & vbCrLf & _
"SELECT autonum_fld, text_field, long_int_field" & vbCrLf & _
"FROM Table1;"
... or if the two table structures are identical, you don't even have to list the field names ...
cn.Execute "INSERT INTO Table2" & vbCrLf & _
"SELECT *" & vbCrLf & _
"FROM Table1;"
And finally ...
Set cn = Nothing
AFAICT, that could work. However, I don't understand the background details of your question, for example "Access does not allow double relationships". So I may be completely off the mark.