Jet Database and pass-through queries, parameters - oracle

I'm connecting to a Jet 4 DB through ODBC.
The Jet DB uses pass-through queries to an Oracle DB. This works so far (can't access the p-t queries directly, but creating a view on the query does the trick).
I need some subset of the data returned by the p-ts. Parameters would be best, but are not supported.
Two questions:
1) Jet does seem to be able to push some where-clauses to Oracle. Eg I have a passthrough query that returns 100k rows. A view on the p-t with a single flitering clause (eg "district = '1010'") is very fast, so the processing seems to happen on Oracle. Adding more clauses can slow the query down to a crawl, looping for minutes with high CPU utilization. Is there any documentation on what is passed on and what is done on in the Jet side?
2) There are lots of tutorials on how to create dynamic passthrough queries with VBA/Access. Is it possible to do this (or anything to that effect) with Jet accessed through ODBC?
Thanks
Martin
Edit:
Sorry for being so unclear.
I have a reporting tool that accesses a Jet db through ODBC. The Jet db contains some data and several passthrough queries to an Oracle db. A typical use case would be a generating report for a given department and a given date, using data from Jet and Oracle. This works very well in principle.
The problem is that passthrough queries cannot contain any parameters. A passthrough query works like a view, so I can simply execute "select * from pt_query where dep = 'a' and date = somedate". Jet, however, loads all rows from the pt and does a full scan on the client side. This is unusably slow for a 100k-rows view and I need to find a way to avoid that.
For some simple selects, Jet does seem to let Oracle do the hard work and does not load all rows, hence my question 1.
If that doesn't work, I need to find a way to force Jet to load only the data I need from Oracle for a given request.
I know that I can modify pts through Access VBA, but I only connect through ODBC, so I can only pass SQL to Jet, not call the vb api (unless its possible to inline VB in the SQL statement).

It is not impossible that the query is constructed to cause a table scan, and this is causing the problem.
You seem to be working in VBA. It is possible to construct quite a few interesting queries as SQL strings in VBA and save them to new queries, update existing queries, use them for record sources for forms, or open recordsets. You can use DAO or ADO, depending on what you want to do. I have Oracle, so all I can do is suggest ideas using SQL Server, the connection in square brackets can be got by looking at the connection of a linked table (CurrentDb.TableDefs("NameOfTable").Connect):
Dim cn As New ADODB.Connection
''You can use Microsoft.ACE.OLEDB.12.0 or Microsoft.Jet.OLEDB.4.0
scn = "Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source=" _
& CurrentProject.FullName
cn.Open scn
''An insert query, but you can see that is would be easy enough to
''select from two different databases
s = "INSERT into [ODBC;Description=TEST;DRIVER=SQL Server;" _
& "SERVER=ServerName\SQLEXPRESS;Trusted_Connection=Yes;" _
& "DATABASE=test].Table2 (id, atext) select id, atext from table1"
cn.Execute s
Or
''http://www.carlprothman.net/Default.aspx?tabid=87
strConnect = _
"Provider=sqloledb;" & _
"Data Source=myServerName;" & _
"Initial Catalog=Test;" & _
"Integrated Security=SSPI"
With cmd
.ActiveConnection = strConnect
.CommandType = adCmdText
.CommandText = "SELECT ID, aText FROM table2 " _
& "WHERE ID=?"
.Parameters.Append .CreateParameter _
("ID", adInteger, adParamInput, , 1)
.CommandTimeout = 0
Set rs = .Execute
End With

Can you duplicate the PT query in your own db instead of linking to it in another db?
All the sql in the PT query should get executed on the linked server without Jet attempting to parse or execute it. It's in a foreign language from Jet's point of view.
I'll use code like this in the PT:
SELECT * FROM DHSVIEWS.ClaimHeaderV WHERE
DHSViews.claimheaderV.ClaimType = 'p' AND
DHSViews.claimheaderV.FinalVersionInd = 'y' AND
DHSViews.claimheaderV.ReimbursementAmount > 0 AND
DHSViews.claimheaderV.majorProgram = 'HH' AND
DHSViews.claimheaderV.ServiceDateFrom >= [qStart] AND
DHSViews.claimheaderV.ServiceDateFrom <= [qEnd];
and this in VBA:
Set qdef = db.QueryDefs(qryPT)
sqlOld = qdef.sql
iPosStart = InStr(sqlOld, "[")
sqlNew = sqlOld
Do While iPosStart > 0
iPosEnd = InStr(iPosStart, sqlNew, "]")
param = Mid(sqlNew, iPosStart + 1, iPosEnd - iPosStart - 1)
Select Case param
Case "qStart"
paramVal = "'" & rsQuarter("quarterStart") & "'"
Case "qEnd"
paramVal = "'" & rsQuarter("quarterEnd") & "'"
End Select
sqlNew = Mid(sqlNew, 1, iPosStart - 1) & paramVal & Mid(sqlNew, iPosEnd + 1)
iPosStart = InStr(iPosEnd, sqlNew, "[")
Loop
If sqlNew <> sqlOld Then
qdef.sql = sqlNew
End If
db.QueryDefs(rsPTAppend("append")).Execute
If sqlNew <> sqlOld Then
qdef.sql = sqlOld
End If

Related

VBA - Query with multiple AND statement not working

I'm having a hard time trying to gather data from an Oracle DB. I've managed to get the connection going, so the problem lies within the query. At the moment the query dont return anything, and neither VBA complains about it.
Here's the code:
Sub Connect_XXXX()
Dim conn As ADODB.Connection
Set conn = New ADODB.Connection
Dim rs As New ADODB.Recordset
Set rs = New ADODB.Recordset
Dim myQuery As ADODB.Command
Set myQuery = New ADODB.Command
conn.Open "Provider=OraOLEDB.Oracle;" & _
"Data Source=XXXX;" & _
"User Id=YYYY;" & _
"Password=ZZZZ"
myQuery.ActiveConnection = conn
myQuery.CommandText = "SELECT sta.index_id, sta.index_action as Action, sta.ticker, sta.company, sta.announcement_date as A_Date, sta.announcement_time as A_Time, " & _
"sta.effective_date as E_Date, dyn.index_supply_demand as BS_Shares, dyn.net_index_supply_demand as Net_BS_Shares, dyn.est_funding_trade as BS_Value, " & _
"dyn.trade_adv_perc/100 as Days_to_Trade, dyn.pre_index_weight/100 as Wgt_Old, dyn.post_index_weight/100 as Wgt_New, dyn.net_index_weight/100 as Wgt_Chg, " & _
"dyn.pre_est_index_holdings as Index_Hldgs_Old, dyn.post_est_index_holdings as Index_Hldgs_New, dyn.net_est_index_holdings as Index_Hldgs_Chg, sta.index_action_details as Details " & _
"FROM index_analysis.eq_index_actions_dyn dyn, index_analysis.eq_index_actions_static sta " & _
"WHERE (sta.action_id = dyn.action_id) AND (sta.announcement_date=dyn.price_date) AND (sta.announcement_date >= '01-January-2015') AND (sta.announcement_date <= '30-January-2015') " & _
"ORDER by sta.index_id,sta.announcement_date"
Set rs = myQuery.Execute
Sheets("Sheet1").Range("A1").CopyFromRecordset rs
rs.Close
conn.Close
End Sub
I've played around with the query a lot, and I've been able to get some results by removing some of the AND statements after the WHERE and trying with fewer fields on the SELECT statement, but I need them all in order for this results to work for me. The weird thing is that if I run the same query in a problem like Oracle Sql Developer (after connecting to the DB) it shows the results that I want. I could really use some help, Thanks!
If you are going to hard-code the date range, assuming announcement_date is a date, you'd want to compare against dates, not strings. You can use to_date with an explicit format mask to convert a string to a date,
sta.announcement_date >= to_date( '01-January-2015', 'DD-Month-YYYY')
or you can use a date literal which always has the format YYYY-MM-DD
sta.announcement_date >= date '2015-01-01'
My guess is that your code seems to work in SQL Developer because you happen to have configured your NLS_DATE_FORMAT to be 'DD-Month-YYYY' in SQL Developer.
In reality, you should really be using bind variables rather than hard-coding things like the date range. Assuming you bind a date value, the conversion (if any) from a string to a date would happen in VB and wouldn't depend on your session's NLS settings. There are also performance and security reasons to prefer bind variables.

How to use multiple inner joins for visual basic 6

I am looking for a way to use 2 inner joins so I can link 3 databases together.
I currently use this :
rs.Open "select * from School inner join Name on School.ID = Name.ID", db, 3, 3
I need to add the database called Opdracht. After the DB are linked I want to link all the IDs together. Like in the code above but then 3 IDs.
I hope you can help me with this.
The specific syntax will depend on the database / driver you are using but you simply add another JOIN statement. I prefer building a string and assigning the string as it makes the code easier to read.
...
Dim strSQL as String
strSQL = "SELECT * FROM (School " & _
"INNER JOIN Name ON School.ID = Name.ID) " & _
"INNER JOIN Opdracht ON Opdracht.ID = Name.ID"
rs.Open strSQL, db, 3, 3
...

How to increase performance for bulk INSERTs to ODBC linked tables in Access?

I have CSV and TXT files to import. I am importing the files into Access and then inserting the records into a linked Oracle table. Each file has around 3 million rows and the process is taking a long time to complete.
Importing into Access is very fast, but inserting into the linked Oracle table is taking an extremely long time.
Here is the process I am currently using:
DoCmd.TransferText acImportFixed, "BUSSEP2014 Link Specification", "tblTempSmartSSP", strFName, False
db.Execute "INSERT INTO METER_DATA ([MPO_REFERENCE]) SELECT MPO_REFERENCE FROM tblTempSmartSSP;"`
tblTempSmartSSP is an Access Table and METER_DATA is a linked Oracle table
I also tried direct import to linked table and that was also very slow.
How can I speed up the process?
This situation is not uncommon when dealing with bulk INSERTs to ODBC linked tables in Access. In the case of the following Access query
INSERT INTO METER_DATA (MPO_REFERENCE)
SELECT MPO_REFERENCE FROM tblTempSmartSSP
where [METER_DATA] is an ODBC linked table and [tblTempSmartSSP] is a local (native) Access table, the Access Database Engine is somewhat limited in how clever it can be with ODBC linked tables because it has to be able to accommodate a wide range of target databases whose capabilities may vary greatly. Unfortunately, it often means that despite the single Access SQL statement what actually gets sent to the remote (linked) database is a separate INSERT (or equivalent) for each row in the local table. Understandably, that can prove to be very slow if the local table contains a large number of rows.
Option 1: Native bulk inserts to the remote database
All databases have one or more native mechanisms for the bulk loading of data: Microsoft SQL Server has "bcp" and BULK INSERT, and Oracle has "SQL*Loader". These mechanisms are optimized for bulk operations and will usually offer significant speed advantages. In fact, if the data needs to be imported into Access and "massaged" before being transferred to the remote database it can still be faster to dump the modified data back out to a text file and then bulk import it into the remote database.
Option 2(a): Using Python and pandas
pyodbc with fast_executemany=True can upload rows much faster than INSERT INTO … SELECT … on a linked table. See this answer for details.
Option 2(b): Using a pass-through query in Access
If the bulk import mechanisms are not a feasible option, then another possibility is to build one or more pass-through queries in Access to upload the data using INSERT statements that can insert more than one row at a time.
For example, if the remote database was SQL Server (2008 or later) then we could run an Access pass-through (T-SQL) query like this
INSERT INTO METER_DATA (MPO_REFERENCE) VALUES (1), (2), (3)
to insert three rows with one INSERT statement.
According to an answer to another earlier question here the corresponding syntax for Oracle would be
INSERT ALL
INTO METER_DATA (MPO_REFERENCE) VALUES (1)
INTO METER_DATA (MPO_REFERENCE) VALUES (2)
INTO METER_DATA (MPO_REFERENCE) VALUES (3)
SELECT * FROM DUAL;
I tested this approach with SQL Server (as I don't have access to an Oracle database) using a native [tblTempSmartSSP] table with 10,000 rows. The code ...
Sub LinkedTableTest()
Dim cdb As DAO.Database
Dim t0 As Single
t0 = Timer
Set cdb = CurrentDb
cdb.Execute _
"INSERT INTO METER_DATA (MPO_REFERENCE) " & _
"SELECT MPO_REFERENCE FROM tblTempSmartSSP", _
dbFailOnError
Set cdb = Nothing
Debug.Print "Elapsed time " & Format(Timer - t0, "0.0") & " seconds."
End Sub
... took approximately 100 seconds to execute in my test environment.
By contrast the following code, which builds multi-row INSERTs as described above (using what Microsoft calls a Table Value Constructor) ...
Sub PtqTest()
Dim cdb As DAO.Database, rst As DAO.Recordset
Dim t0 As Single, i As Long, valueList As String, separator As String
t0 = Timer
Set cdb = CurrentDb
Set rst = cdb.OpenRecordset("SELECT MPO_REFERENCE FROM tblTempSmartSSP", dbOpenSnapshot)
i = 0
valueList = ""
separator = ""
Do Until rst.EOF
i = i + 1
valueList = valueList & separator & "(" & rst!MPO_REFERENCE & ")"
If i = 1 Then
separator = ","
End If
If i = 1000 Then
SendInsert valueList
i = 0
valueList = ""
separator = ""
End If
rst.MoveNext
Loop
If i > 0 Then
SendInsert valueList
End If
rst.Close
Set rst = Nothing
Set cdb = Nothing
Debug.Print "Elapsed time " & Format(Timer - t0, "0.0") & " seconds."
End Sub
Sub SendInsert(valueList As String)
Dim cdb As DAO.Database, qdf As DAO.QueryDef
Set cdb = CurrentDb
Set qdf = cdb.CreateQueryDef("")
qdf.Connect = cdb.TableDefs("METER_DATA").Connect
qdf.ReturnsRecords = False
qdf.sql = "INSERT INTO METER_DATA (MPO_REFERENCE) VALUES " & valueList
qdf.Execute dbFailOnError
Set qdf = Nothing
Set cdb = Nothing
End Sub
... took between 1 and 2 seconds to produce the same results.
(T-SQL Table Value Constructors are limited to inserting 1000 rows at a time, so the above code is a bit more complicated than it would be otherwise.)
Another possibility for SQL Server if bcp or BULK COPY is not an option:
METER_DATA is an ODBC linked table in Access for dbo.METER_DATA on SQL Server
tblTempSmartSSP is a local Access table containing 10_000 rows
On my (very old) test network, this VBA code takes ~240 seconds (about 4 minutes) to run
Sub upload()
Dim cdb As DAO.Database
Set cdb = CurrentDb
Dim t0 As Single
t0 = Timer
cdb.Execute "INSERT INTO METER_DATA (MPO_REFERENCE) SELECT MPO_REFERENCE FROM tblTempSmartSSP"
Debug.Print Timer - t0
End Sub
Using Python and pandas, this code uploads the same 10_000 rows in about 5 seconds
from time import perf_counter
import pandas as pd
import sqlalchemy as sa
acc_engine = sa.create_engine(
"access+pyodbc://#meter_data"
)
sql_engine = sa.create_engine(
"mssql+pyodbc://scott:tiger^5HHH#mssql_199",
fast_executemany=True,
)
t0 = perf_counter()
df = pd.read_sql_query("SELECT MPO_REFERENCE FROM tblTempSmartSSP", acc_engine)
df.to_sql("METER_DATA", sql_engine, schema="dbo", if_exists="append", index=False)
print(perf_counter() - t0)
Requirements:
Python
pandas
sqlalchemy-access (Disclosure: I am the maintainer of this project.)
Note that other databases supported by SQLAlchemy (e.g., PostgreSQL) may also offer significant performance improvements over an ODBC linked table in Access.
Do you have to import all the columns? Maybe you want to leave out empty columns, if any; and also columns which are not absolutely necessary for business purposes
Sorry, I forgot to include the code:
Option Compare Database
Option Explicit
Public Function Run_Safe_SQL(strSQL)
On Error GoTo Error_Handler
Dim db As DAO.Database
Set db = CurrentDb()
db.Execute strSQL, dbFailOnError
DBEngine.Idle dbRefreshCache
' DoEvents
Exit_Here:
'Cleanup
Set db = Nothing
strSQL = ""
Exit Function
Error_Handler:
MsgBox Err.Description & " " & Err.Number
End Function

VBA : Querying Access with Excel on server

I'm working with Excel project wich helps to calculate the price of any peace of furniture. The first task is to pick all the materials from the database.
This is the code:
Sub Material_search()
Dim cnt As New ADODB.connection
Dim rst As New ADODB.Recordset
Dim rcArray As Variant
Dim sSQL As String
Dim db_path As String, db_conn As String
Dim item As String
item = Replace(TextBox1.Text, " ", "%") ' Search word
sSQL = "Select Data, NomNr, Preke, Matas, Kaina, Tiek from VazPirkPrekes " & _
"Where VazPirkPrekes.PirkVazID IN (SELECT VazPirkimo.PirkVazID FROM VazPirkimo Where VazPirkimo.Sandelys like '%ALIAVOS')" & _
" and Year(VazPirkPrekes.Data)>=2011 and Preke Like '%" + item + "%' and Kaina > 0" & _
" Order by Preke, Data Desc"
db_path = Sheets("TMP").Range("B6").value
db_conn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & db_path & ";"
cnt.Open db_conn
rst.Open sSQL, cnt, adOpenForwardOnly, adLockReadOnly
ListBox1.Clear
If Not rst.EOF Then
rcArray = (rst.GetRows)
rcArray = WorksheetFunction.Transpose(rcArray)
Dim a As Variant
With ListBox1
.ColumnCount = 6
.list = rcArray
.ListIndex = -1
End With
End If
rst.Close: Set rst = Nothing
cnt.Close: Set cnt = Nothing
Label4.Caption = UBound(ListBox1.list) + 1
End Sub
recently I came up with some trouble while querying Access mdb file. The problem is when database file is on local disk, the search works very fast, but when i put database file on server, the search takes 10 times longer, which is not acceptable.
Is there any optimisation for this code ? or is it a server problem
Thanks in advance
That query requires Access' database engine retrieve all 190K rows from both tables. It's not surprising it is slow, and the slowness is compounded when the db engine must retrieve 2 * 190K rows across the network.
If TextBox1.Text contains "foo", this is the statement you're asking the db engine to run:
Select Data, NomNr, Preke, Matas, Kaina, Tiek
from VazPirkPrekes
Where
VazPirkPrekes.PirkVazID IN (
SELECT VazPirkimo.PirkVazID
FROM VazPirkimo
Where VazPirkimo.Sandelys like '%ALIAVOS')
and Year(VazPirkPrekes.Data)>=2011
and Preke Like '%foo%'
and Kaina > 0
Order by Preke, Data Desc
The engine must retrieve all 190K rows from the VazPirkimo table before it can determine which of them include Sandelys values which end with "ALIAVOS". If your selection criterion was for values which start with "ALIAVOS", the engine could use an index on Sandelys to limit the number of rows it must retrieve from VazPirkimo. However, since that approach is probably not an option for you, consider adding a numeric field, Sandelys_group, to VazPirkimo and create an index on Sandelys_group. Give all rows where Sandelys ends with "ALIAVOS" the same Sandelys_group number (1). Then your "IN ()" condition could be this:
SELECT VazPirkimo.PirkVazID
FROM VazPirkimo
Where VazPirkimo.Sandelys_group = 1
The index on Sandelys_group will allow the db engine to retrieve only the matching rows, which will hopefully be a small subset of the 190K rows in the table.
There are other changes you can make to speed up your query. Look at this criterion from your WHERE clause:
Year(VazPirkPrekes.Data)>=2011
That forces the db engine to retrieve all 190K rows from VazPirkPrekes before it can determine which of them are from 2011. With an index on Data, this should be much faster:
VazPirkPrekes.Data >= #2011-01-01# AND VazPirkPrekes.Data < #2012-01-01#
This WHERE criterion will be faster with an index on Kaina:
Kaina > 0
Your ORDER BY begs for indexes on Preke and Data.
Order by Preke, Data Desc
Any or all of those changes could help speed up the query, though I don't know by how much. The killer is this WHERE criterion:
Preke Like '%foo%'
The issue here is similar to the problem with the "Sandelys like" comparison. Since this asks for the rows where Preke contains "foo", rather than starts with "foo", the db engine can't take advantage of an index on Preke to retrieve only the matching rows. It must retrieve all 190K VazPirkPrekes rows to figure out which match. Unless you can use a different criterion for this one, you will be limited as to how much you can speed up the query.
Thanks for the optimization tips, but as I said the problem occurs only when I put data base file on server. And there is not much help from optimization. But I thought about other idea.
The search of empty blank "" returns about 40k records (these records covers everything I need) . So I'm going to put all these records on a distinct sheet on workbook_activate event and later do the query only in that sheet.
Sub Database_upload()
Application.DisplayAlerts = False
On Error Resume Next
Sheets("DATA_BASE").Delete
On Error GoTo 0
Application.DisplayAlerts = False
Sheets.Add
ActiveSheet.name = "DATA_BASE"
Sheets("DATA_BASE").Visible = False: Sheets("DARBALAUKIS").activate
Dim cnt As New ADODB.connection
Dim rcArray As Variant
Dim sSQL As String
Dim db_path As String, db_conn As String
Dim item As String
Dim qQt As QueryTable
item = "" 'search for empty blanks
sSQL = "Select Data, NomNr, Preke, Matas, Kaina, Tiek from VazPirkPrekes " & _
"Where VazPirkPrekes.PirkVazID IN (SELECT VazPirkimo.PirkVazID FROM VazPirkimo Where VazPirkimo.Sandelys like '%ALIAVOS')" & _
" and Year(VazPirkPrekes.Data)>=2011 and Preke Like '%" + item + "%' and Kaina > 0" & _
" Order by Preke, Data Desc"
db_path = Sheets("TMP").Range("B6").value
db_conn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & db_path & ";"
db_conn = "ODBC;DSN=MS Access 97 Database;"
db_conn = db_conn & "DBQ=" & db_path
Set qQt = Sheets("Sheet1").QueryTables.Add(connection:=db_conn, Destination:=Sheets("Sheet1").Range("A1"), Sql:=sSQL)
qQt.Refresh BackgroundQuery:=False
End Sub
Results:
Program takes longer on startup, but the search time is acceptable - for me the problem is solved :)

Linq Compiled Queries and int[] as parameter

I'm using the following LINQ to SQL compiled query.
private static Func<MyDataContext, int[], int> MainSearchQuery =
CompiledQuery.Compile((MyDataContext db, int[] online ) =>
(from u in db.Users where online.Contains(u.username)
select u));
I know it is not possible to use sequence input paramter for a compiled query and im getting “Parameters cannot be sequences” error when running it.
On another post here related , I saw that there is some solution but I couldn't understand it.
Does anyone know to use complied query with array as input paramter?
Please post example if you do.
Like the post that you referenced, it's not really possible out of the box. The post also references creating your own query provider, but it's a bit of overhead and complexity that you probably don't need.
You have a few options here:
Don't use a compiled query. Rather, have a method which will create a where clause from each item in the array resulting in something like this (psuedo-code):
where
online[0] == u.username ||
online[1] == u.username ||
...
online[n] == u.username
Note that you would have to use expression here to create each OR clause.
If you are using SQL Server 2008, create a scalar valued function which will take a table-valued parameter and a value to compare againt. It will return a bit (to indicate if the item is in the values in the table). Then expose that function through LINQ-to-SQL on your data context. From there, you should be able to create a CompiledQuery for that. Note that in this case, you should take an IEnumerable<string> (assuming username is of type string) instead of an array, just because you might have more than one way of representing a sequence of strings, and to SQL server for this operation, it won't matter what the order is.
One solution that I have found myself doing (for MS SQL 2005/2008). And I'm not sure if it is appropriate in all scenarios is to just write dynamic sql and execute it against the datacontext using the ExecuteQuery method.
For example, if I have an unbounded list that I am trying to pass to a query to do a contains...
' Mock a list of values
Dim ids as New List(of Integer)
ids.Add(1)
ids.Add(2)
' ....
ids.Add(1234)
Dim indivs = (From c In context.Individuals _
Where ids.Contains(c.Id) _
Select c).ToList
I would modify this query to create a SQL string to execute against the database directly like so...
Dim str As New Text.StringBuilder("")
Dim declareStmt as string = "declare #ids table (indivId int) " & vbcrlf)
For i As Integer = 0 To ids.Count - 1
str.Append("select " & ids(i).ToString() & " & vbcrlf)
If i < ids.Count Then
str.Append("union " & vbcrlf)
End If
Next
Dim selStatement As String = "select * From " & context.Mapping.GetTable(GetType(Individuals)).TableName & _
" indiv " & vbcrlf & _
" inner join #ids ids on indiv.id = ids.id"
Dim query = declareStmt & str.ToString & selStatement
Dim result = context.ExecuteQuery(of Individual)(query).ToList
So barring any syntax errors or bugs that I coded (the above is more or less psuedo code and not tested), the above will generate a table variable in SQL and execute an inner join against the desired table (Individuals in this example) and avoid the use of a "IN" statement.
Hope that helps someone out!

Resources