Welcome to MSDN Blogs Sign in | Join | Help

Microsoft Access Team Blog

Get product announcements, tips and tricks, and news directly from the team @ Microsoft.
Accessing external data using the IN clause

Someone sent us a question the other day about one of my favorite dark corners in Access and we thought it might be interesting to dive into this area a little.

Microsoft Access SQL supports two uses of the IN keyword. The most commonly used case is as part of the WHERE clause of a SQL statement to provide a list of values used as criteria. Using the Customers table in the Northwind 2007 sample database as an example, this might look something like:

SELECT [First Name], [Last Name], [State/Province]
FROM [Customers]
WHERE [State/Province] IN ('WA', 'CA', 'NY')

This query returns the names of customers that live in WA, CA, or NY. This keyword provides a nice alternative to the OR clause which would require repeating the field name.

The other use of the IN keyword is as part of the SELECT statement or FROM clause, and is called the IN clause. The IN clause is used to access external data, and can be used in place of linked tables. For example, let's say that you had a SQL Server database that is used as part of an application, but you don't want to maintain a DSN to connect. You could use the IN clause in a query that uses a DSN-less connection to quickly read data from the external table. For example:

SELECT * FROM ExternalTable
IN '' [ODBC;Driver={SQL Server}; Server=ServerName; Database=DatabaseName; Trusted_Connection=Yes]

It is possible to create a linked table that uses a DSN-less connection, but creating the table requires code. Also, unlike a SQL pass-through query, this query is executed by the Access database engine which means that the resultset may also be updateable. Furthermore, there is a certain simplicity or elegance about this technique that I think is cool. Incidentally, there is another syntax for the IN clause, but I prefer this one.

So far so good, but since the IN clause is part of the FROM clause of a query, it can also be used other places where the FROM clause can be used. For example, in a make table query to create a local copy of data in an external table:

SELECT * INTO LocalTable
FROM SourceTable
IN '' [ODBC;Driver={SQL Server}; Server=ServerName; Database=DatabaseName; Trusted_Connection=Yes]

Or, in an append query using the INSERT...INTO statement to move data from the local database into another database. Note that the connection string used in this example is to another Access database.

INSERT INTO DestinationTable (DestinationField)
IN '' [;DATABASE= C:\Users\Rob\Documents\Northwind 2007.accdb]
SELECT SourceField FROM SourceTable

You could even use an append query with multiple IN clauses to concatenate two text files:

INSERT INTO [File2.txt] (Field1)
IN '' [TEXT; FMT=Delimited; HDR=YES; DATABASE= C:\Users\Rob\Documents;TABLE=File2.txt]
SELECT Field1
FROM [File1.txt]
IN '' [TEXT; FMT=Delimited; HDR=YES; DATABASE= c:\Users\Rob\Documents;TABLE=File1.txt];

These are just a few examples of how you could use the IN clause to quickly work with external data. By using different connection strings for the external data sources, you could do some pretty cool stuff.

Posted: Friday, March 27, 2009 11:36 AM by robcooper

Comments

Tony Toews - Access MVP said:

This is a useful technique and there is very little useful examples on this topic in the help files.  So it's very much a matter of trial and error figuring this out.

I use this technique while updating backend MDB files to the latest version.  

When the user selects the BE MDB, or upon startup, the FE MDB first update the backends tables, fields, indexes and relationships to the latest version using DAO collections.

Then if there is any table clean up to be done or records to be inserted in a status table of some sort I then use the IN clause in an Action query.

For example to create a "master" table of service techs from a text field entered on each individal service order in previous versions of my app I used the following:

   ' Append records to ServiceRecords table

   strSQL = "INSERT INTO ServiceTech ( stServiceTech ) " & _

       " IN '" & strDatabasePathandName & "' " & _

       "SELECT srServicePerson FROM ServiceRecords " & _

       " IN '" & strDatabasePathandName & "' " & _

       "GROUP BY srServicePerson " & _

       "HAVING (srServicePerson Is Not Null);"

   CurrentDb.Execute strSQL, dbFailOnError

Note that the strDatabasePathandName is just a share, path and file name or drive letter, path and file name.  No need to use [;DATABASE=...] etc.

I then update the backend version number in a one field, one record table.  For example:

   strSQL = "SELECT zDataVersionNumber FROM zDataVersionNumberApp IN '" & strDatabasePathandName &  "';"

is passed to an OpenRecordset statement with some further logic.  That could've been an Action query too.

# March 28, 2009 12:48 AM

Kevin said:

Very interesting!  I can see some uses here.  I'm building a data sync operation in an app that collects from multiple work PCs and creates a single coordinating database, and the environment does not warrant (allow) a client-server backend.

# March 31, 2009 3:06 PM

Renaud Bompuis said:

Nice article.

Access' ability to easily link to external datasources and manipulate them as if they were its own is really one of its greatest strengths.

# April 5, 2009 10:25 PM
New Comments to this post are disabled
Page view tracker