Possible to join two recordsets using VBA/ADO? - ms-access

The goal is to join an Access table with matching data from a SQL Server table. I would do this using linked tables in Access but I'm running into Access' BigInt problem (I would have a view created to cast BigInt as Int but that isn't an option right now).
So I've been trying to create two recordsets and join them in VBA/ADO. The left side of the join would be the Access table with Season and WeekNum and the right side of the join would be the SQL Server table with Season and Weeknum and other data. This works fine until I try to create a third recordset that is the result of the join (in this example, I haven't tried to do a join, just the first part of the join by selecting from the Access recordset). I'm getting a Type Mismatch error on the line when I do Set ObjRecordset3 = "SELECT * FROM " & Access_Recordset '.
Is it even possible to join two recordsets? If so, how is this done?
Function Join()
Dim SQL_Server_Connection As ADODB.Connection
Set SQL_Server_Connection = New ADODB.Connection
Dim SQL_Server_Query As String
Dim SQL_Server_Recordset As New ADODB.Recordset
Dim Access_Recordset As New ADODB.Recordset
Dim ObjConnection As ADODB.Connection
Set ObjConnection = CreateObject("ADODB.Connection")
Dim ObjRecordset3 As New ADODB.Recordset
' Get data from Bump Table 3:
Access_Recordset.Open "SELECT * FROM [Bump Table 3]", CurrentProject.Connection
' Open connection to SQL Server:
SQL_Server_Connection_String = "DSN=MySQLServer"
SQL_Server_Connection.Open SQL_Server_Connection_String
' Define the SQL Server query:
SQL_Server_Query = "SELECT Season, WeekNum FROM TE"
' Populate the SQL_Server_Recordset:
SQL_Server_Recordset.Open SQL_Server_Query, SQL_Server_Connection, adOpenDynamic, adLockOptimistic
'Join Access_Recordset (Table: Bump Table 3) to SQL_Server_Recordset (Table: TE)
Set ObjRecordset3 = "SELECT * FROM " & Access_Recordset ' Type Mismatch error on this line
Access_Recordset.Close
Set Access_Recordset = Nothing
SQL_Server_Recordset.Close
Set SQL_Server_Recordset = Nothing
SQL_Server_Connection.Close
End Function
* UPDATE *
I figured out how to get to my ultimate goal which was to get data about a list of account numbers in an Access table from SQL Server based on the account number field which is common to both tables. Realizing that I can create a persistent temp table on SQL Server, I used a combination of DAO and ADO to get the values from the Access table and create a temp table. All I had to do then is run the pass-through query which references the temp table. The only odd thing (which is not a problem at this point) is if I create the temp table and run the pass-through query in VBA, this setup works. But if I create the temp table in VBA and double-click on the pass-through query, Access says that the temp table can't be found. Anyway, here's the code:
Public Sub Insert_Into_Access_From_ADO_Recordset_Using_PTQ_Simpler()
Dim dbs As DAO.Database
Set dbs = CurrentDb()
Dim cnn As ADODB.Connection
Set cnn = New ADODB.Connection
Dim rst As ADODB.Recordset
'Open SQL Server
Dim str_cnn As String
str_cnn = "MYDSN"
cnn.Open str_cnn
' Drop the temp table:
Dim str_SQL_Drop_Temp_Table As String
str_SQL_Drop_Temp_Table = "IF OBJECT_ID('tempdb..##BumpData','U') IS NOT NULL "
str_SQL_Drop_Temp_Table = str_SQL_Drop_Temp_Table & " DROP TABLE ##BumpData "
cnn.Execute str_SQL_Drop_Temp_Table
' Create the temp table:
Dim str_SQL_Create_Temp_Table As String
str_SQL_Create_Temp_Table = " CREATE TABLE ##BumpData "
str_SQL_Create_Temp_Table = str_SQL_Create_Temp_Table & " " & "("
str_SQL_Create_Temp_Table = str_SQL_Create_Temp_Table & " " & " ID INT "
str_SQL_Create_Temp_Table = str_SQL_Create_Temp_Table & " " & " , AccountNumber VARCHAR(Max)"
str_SQL_Create_Temp_Table = str_SQL_Create_Temp_Table & " " & ")"
cnn.Execute str_SQL_Create_Temp_Table
' Insert values from the Access table into the temp table
' by looping through the Access table as a recordset:
Dim rst_DAO As DAO.Recordset
Set rst_DAO = dbs.OpenRecordset("Bump Data")
Dim str_SQL_Insert As String
rst_DAO.MoveFirst
With rst_DAO
Do While Not rst_DAO.EOF
'str_Loan_Number_List = str_Loan_Number_List & "'" & Trim(rst![Loan Number]) & "'" & ","
str_SQL_Insert = " INSERT INTO ##BumpData VALUES (" & rst_DAO![ID] & ",'" & Trim(rst_DAO![Loan Number]) & "') "
cnn.Execute str_SQL_Insert
.MoveNext
Loop
End With
' Run the pass-thru query which joins to the temp table:
DoCmd.SetWarnings False
DoCmd.RunSQL "SELECT * INTO [Bump Results] FROM [Bump PTQ]"
DoCmd.SetWarnings True
End Sub

You reported this line triggers the error:
Set ObjRecordset3 = "SELECT * FROM " & Access_Recordset
The right side of the = sign attempts to concatenate a string with an ADODB.Recordset object. That is probably the immediate cause of the compile error. However, that's not the only problem with that line. Set <recordset object> = "any string value" will not work. And finally, Access SQL does not support FROM <recordset object> for any type of recordset object (ADO or DAO).
I think you should look for a simpler approach. In following query, dbo_BigIntTable is an ODBC link to a SQL Server table. It includes a field, bigint_fld, whose SQL Server data type is BigInt. However, Access sees that field as Text type. Therefore I can join it with the string equivalent of a Long Integer field (tblFoo.id).
SELECT tblFoo.id, dbo_BigIntTable.bigint_fld
FROM
tblFoo
INNER JOIN dbo_BigIntTable
ON CStr(tblFoo.id) = dbo_BigIntTable.bigint_fld;
The Access query designer complained it can't display that join in Design View, but I was able create the join from SQL View and it worked fine.

Related

In VBA Query cannot be completed

I want to find the sum of records from different tables and insert the output in a new column, when I run the code it show me the error:
"The query cannot be completed. Either the size of the query result is
larger than the maximum size of the database (2GB) or there is not enough
temporary storage space on the disk to store the query result"
And it highlight the line
STD.Open sql, cnn, adOpenStatic
My code is the following
Option Compare Database
Option Explicit
Public cnn As New ADODB.Connection
Public db As DAO.Database
Public Sub SMain()
Set db = Access.Application.CurrentDb
Set cnn = CurrentProject.Connection
Get_Value
End Sub
Private Sub Get_Value()
Dim sql As String
Dim STD As New ADODB.Recordset
Dim ODR As DAO.Recordset
Set ODR = db.OpenRecordset("Total_tbl")
Do Until ODR.EOF
DoEvents
sql = "SELECT SUM(MONT_VOL.tot_n* STD_tbl.factor_n)AS TOTAL_N FROM MONT_VOL " & _
" INNER JOIN (STD_tbl INNER JOIN Total_tbl ON STD_tbl.AREA =Total_tbl.AREA_1" & _
" AND STD_tbl.AID = Total_tbl.AID)" & _
" ON MONT_VOL.BID = STD_tbl.BLOCK" & _
" WHERE MONT_VOL.BDATE = Total_tbl.Adate" & _
" GROUP BY MONT_VOL.BID"
STD.Open sql, cnn, adOpenStatic
If STD.RecordCount <> 0 Then
ODR.Edit
ODR!New_Col= STD!TOTAL_N
ODR.Update
End If
STD.Close
ODR.MoveNext
Loop
End Sub
What mistake I did?
And am I calling the output correctly on
ODR!New_Col= STD!TOTAL_N
If the query is too big (which the error message indicates), then let's split it into smaller chunks. This is only properly possible in MySQL, Access doesn't support LIMIT or OFFSET, workarounds are messy, especially for totals queries
I'm making a few assumptions here:
All relevant tables are stored within the same MySQL database
Your tables have valid connection strings that can be used for ADO
Note that executing the query in MySQL alone is probably enough to fix this error.
Private Sub Get_Value()
Dim sql As String
Dim STD As New ADODB.Recordset
Dim ODR As DAO.Recordset
Set ODR = db.OpenRecordset("Total_tbl")
'Create a new ADODB connection that's directly to MySQL, and doesn't use Access
Dim adoConn2 As ADODB.Connection
adoConn2.ConnectionString = CurrentDb.TableDefs("MONT_VOL").Connect
adoConn2.Open
'Initialize variables used for pagination
Dim RecordCount As Integer
Dim PageSize As Integer
Dim Offset As Integer
Offset = 0
RecordCount = 1
PageSize = 100
Do Until ODR.EOF
DoEvents
While RecordCount <> 0
sql = "SELECT SUM(MONT_VOL.tot_n* STD_tbl.factor_n)AS TOTAL_N FROM MONT_VOL " & _
" INNER JOIN (STD_tbl INNER JOIN Total_tbl ON STD_tbl.AREA =Total_tbl.AREA_1" & _
" AND STD_tbl.AID = Total_tbl.AID)" & _
" ON MONT_VOL.BID = STD_tbl.BLOCK" & _
" WHERE MONT_VOL.BDATE = Total_tbl.Adate" & _
" GROUP BY MONT_VOL.BID" & _
" LIMIT " & Offset & "," & PageSize
STD.Open sql, adoConn2, adOpenStatic
RecordCount = STD.RecordCount
If STD.RecordCount <> 0 Then
ODR.Edit
ODR!New_Col = STD!TOTAL_N
ODR.Update
End If
STD.Close
Offset = Offset + PageSize
Wend
ODR.MoveNext
Loop
adoConn2.Close
End Sub

Using Excel column data to create sql statement that queries database

I am looking for any advice on how i can read a single column in excel that contains 500 user_id's and query a database to display results in a WPF application. A user can own or rent so the SQL would look like;
SELECT * FROM users WHERE own= 'user_id' or rent= 'user_id'
This is fine for one user but i want to read each user_id and concatenate it to the SQL statement to pull out all results from the database. Any one have any easy way of doing this?
Replace the range as necessary, credit to brettdj on the join - Simple VBA array join not working
Sub test()
Dim strQuery As String
Dim strVals As String
Dim rngTarget As Range
Set rntTarget = Range("A1:A7")
Dim varArr
Dim lngRow As Long
Dim myArray()
varArr = rntTarget.Value2
ReDim myArray(1 To UBound(varArr, 1))
For lngRow = 1 To UBound(varArr, 1)
myArray(lngRow) = varArr(lngRow, 1)
Next
strVals = "('" & Join$(myArray, "','") & "') "
strQuery = "SELECT * FROM users WHERE own in " _
& strVals & "or rent in " & strVals
End Sub

MS Access - How to split one large table into smaller tables by record count

I have a table in MS Access that has +17K of records. I am trying to break down that table into smaller tables of 500 records each. Using the following code, I am able to create the temp table, but I cannot reset the number of ID column. The ID column on the original table is an autonumber. I am trying to reset the ID field on the temp table so I can do a record search starting at 1 and going to 500.
The alter SQL that I have does not update/reset the temp table's ID column to 1. Any ideas?
Function SplitTables_Actual()
Dim rs As New ADODB.Recordset
Dim cn As New ADODB.Connection
Set cn = CurrentProject.Connection
Dim rowcount As Long
Dim tblcount As Integer
Dim i As Integer
SQL = "SELECT * INTO tmp_Flush_Actual FROM BIG_Table"
DoCmd.RunSQL SQL
SQL = "ALTER TABLE tmp_Flush_Actual ALTER COLUMN ID COUNTER(1,1)"
DoCmd.RunSQL SQL
SQL = "SELECT count(*) as rowcount from BIG_Table"
rs.Open SQL, cn
rowcount = rs!rowcount
rs.Close
tblcount = rowcount / 500 + 1
For i = 1 To tblcount
SQL = "SELECT * into tmp_flush_Actual" & i & " FROM tmp_Flush_Actual" & _
" WHERE ID <= 500*" & i
DoCmd.RunSQL SQL
SQL = "DELETE * FROM tmp_Flush_Actual" & _
" WHERE ID<= 500*" & i
DoCmd.RunSQL SQL
Next i
End Function
Bottom line, on the initial query, don't select the ID (Autonumber) column. Select the columns you want into the initial temp table, then alter the table to add a new counter column. I used COUNTER(1,1) so that each time the temp table is created, the first record is 1.
I added a little nugget that saves the broken files to a folder. I commented out the error handling, but uncomment it to make sure your save directory is working correctly.
Function SplitTables_RTPA_Actual()
Dim rs As New ADODB.Recordset
Dim cn As New ADODB.Connection
Set cn = CurrentProject.Connection
Dim rowcount As Long
Dim tblcount As Integer
Dim i As Integer
'Just don't select the ID column
SQL = "SELECT Company, Incurred_By, Transaction_Type, Format(Transaction_Date, 'mm/dd/yyyy'), Investment_ID, " & _
"Task_ID, Charge_Code, Resource_ID, Role, Notes, Quantity INTO tmp_Flush_Tran_Actual FROM Actual_Transaction_Data"
DoCmd.RunSQL SQL
SQL = "ALTER TABLE tmp_Flush_Tran_Actual ADD COLUMN ID COUNTER(1,1)"
DoCmd.RunSQL SQL
SQL = "SELECT count(*) as rowcount from Actual_Transaction_Data"
rs.Open SQL, cn
rowcount = rs!rowcount
rs.Close
tblcount = rowcount / 100 + 1
For i = 1 To tblcount
'Create Temp Flush File
SQL = "SELECT * into tmp_Flush_Tran_Actual" & i & " FROM tmp_Flush_Tran_Actual" & _
" WHERE ID <=100*" & i
DoCmd.RunSQL SQL
SQL = "ALTER TABLE tmp_Flush_Tran_Actual" & i _
& " DROP COLUMN ID;"
DoCmd.RunSQL SQL
'Delete 500 from Temp Flush File
SQL = "DELETE * FROM tmp_Flush_Tran_Actual" & _
" WHERE ID <=100*" & i
DoCmd.RunSQL SQL
'On Error GoTo ErrorHandler
Dim strTable As String
Dim strWorksheetPath As String
'Location where you want to save the broken out files
strWorksheetPath = "C:\YOUR TEMP FOLDER\TEST\"
strWorksheetPath = strWorksheetPath & "Actual_Transactions" & i & ".xls"
strTable = "tmp_Flush_Tran_Actual" & i
DoCmd.TransferSpreadsheet transfertype:=acExport, spreadsheettype:=acSpreadsheetTypeExcel9, TableName:=strTable, FileName:=strWorksheetPath, hasfieldnames:=True
'ErrorHandlerExit:
' Exit Function
' 'Next i
'
'ErrorHandler:
' MsgBox "Error No: " & Err.Number _
' & "; Description: " & Err.Description
' Resume ErrorHandlerExit
Next i
End Function

Vb.net and MySQL: Unknown column in 'field list'

i hope you can help me. Fist of all, sorry if my English is annoying, i'm not a native speaker.
I'm getting this error and i can't see what i'm doing wrong. I have a program that fills a local MySQL DB with data from another program that uses an OLEB DB.
So it compares the tables and upload new data on demand. But i'm getting this error with only one table using the same Sub that i used with other tables.
Unknown column 'lpedidos.serie' in 'field list'
The problem is that 'lpedidos.serie' exists indeed. So here is the code of the sub, please don't laugh, i know that maybe is extremely inefficient, but i'm just a noob.
Public Sub notIndexedTables(table As DataTable, table2 As DataTable, tableNA As String)
Dim temptable As DataTable
temptable = table.Clone
Dim tablename As String = temptable.TableName
Dim myAdapter As MySql.Data.MySqlClient.MySqlDataAdapter
Dim SQL As String
Dim newconn As New MySql.Data.MySqlClient.MySqlConnection
newconn = mysqlConnection()
newconn.Open()
SQL = "TRUNCATE " & tableNA
myAdapter = New MySql.Data.MySqlClient.MySqlDataAdapter()
Dim command As MySql.Data.MySqlClient.MySqlCommand
command = New MySql.Data.MySqlClient.MySqlCommand(SQL, newconn)
myAdapter.DeleteCommand = command
myAdapter.DeleteCommand.ExecuteNonQuery()
For Each row As DataRow In table.Rows()
Dim columnNumber As Int32 = row.ItemArray.Count
Dim i As Integer = 0
Dim s1 As String = "("
For Each columna In row.ItemArray
i = i + 1
If i = columnNumber Then
s1 = s1 + CStr(table2.Columns.Item(i - 1).ColumnName) & ")"
Else
s1 = s1 & CStr(table2.Columns.Item(i - 1).ColumnName) & ", "
End If
Next
Dim s2 As String = "("
i = 0
For i = 0 To (columnNumber - 2)
s2 = s2 & "'" & CStr(row.Item(i)) & "', "
Next
s2 = s2 & "'" & CStr(row.Item(columnNumber - 1)) & "')"
SQL = "INSERT INTO " & tableNA & " " & s1 & " VALUES " & s2
myAdapter = New MySql.Data.MySqlClient.MySqlDataAdapter()
' myCommand = New MySql.Data.MySqlClient.MySqlCommandBuilder(myAdapter)
command = New MySql.Data.MySqlClient.MySqlCommand(SQL, newconn)
myAdapter.InsertCommand = command
myAdapter.InsertCommand.ExecuteNonQuery()
Next
newconn.Close()
newconn.Dispose()
End Sub
Basically it takes the MySQL table (tableNA), truncates it (this procedure is for tables with no index, there is other procedure for tables with unique index) and fills it with the data from the OLEB table (table) and takes the column names from the temporal copy of the MySQL table (table2) (maybe there is no need to use the table2 in this case... but anyway).
Here is the exception and the value that SQL string takes when the exception is thrown.
And here is a screenshot of the table structure in phpMyAdmin.
When you declare the New MySqlConnection you need to put the connection string in there and specify the database name. Can you show your connection string?
Dim myConnection As New MySqlConnection(myConnString)
myConnection.Open()
If that doesn't solve the problem, then try another column name and make sure it isn't a reserved keyword.

Append Records From Passthrough Query to Local Table

I have an Access Database and I'm using a pass through query to return records from an AS400 table. The connection string and pass through query work fine, but now I'm trying to populate the results of the p-t query into a local table within the db and my code is timing out. This is my first attempt at ADO so I'm disclaiming my code with "I'm not 100% sure what I'm doing!". Could you look at this and see if there is something obvious that I'm doing wrong? Any direction would be appreciated. Thank you in advance.
Sub mod_ADODBConnect()
Const NewTableName = "MyNewTable"
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim db As DAO.Database
Dim sSQL1 As String
Dim sSQL2 As String
sSQL1 = "SELECT ITMNUM, ITMDS, ITPKDS, MJCMCD, SBCMCD, STATUS, PRITIN, OGEXDT from PDBLLIB007.BLPMST07"
sSQL2 = "INSERT INTO ' & NewTableName & ' SELECT [" & sSQL1 & "].* from [" & sSQL1 & "]"
Set cn = New ADODB.Connection
cn.Open "Driver={Client Access ODBC Driver (32-bit)};" & _
"System=DC007; Uid=XXXXX; Pwd=XXXXXX; MgDSN=0; ConnType=2;" & _
"BlockSize=512; MaxFieldLen=2048; LazyClose=1; Prefetch=1; QueryTimeOut=0; Translate=1"
Set rs = New ADODB.Recordset
rs.Open sSQL1, cn, adOpenDynamic, adLockOptimistic
Do While Not rs.EOF
rs.MoveNext
Loop
Set db = CurrentDb
db.Execute ("sSQL2")
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
Set db = Nothing
End Sub
You have a pass-through query which works fine and returns the rows you want. Now you want to store those rows in a new local (Jet/ACE) table. Seems to me a simpler approach would be to use the pass-through as the data source in a new "make table" query.
SELECT * INTO MyNewTable FROM YourPassThruQuery;
Oops, looks like you meant to append those rows to an existing table.
INSERT INTO MyNewTable
SELECT * FROM YourPassThruQuery;
If the table structures don't match, you can use field lists for both tables.
INSERT INTO MyNewTable (fld1, fld2)
SELECT first_field, second_field FROM YourPassThruQuery;