Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Table-less UNION query in MS Access (Jet/ACE)

Tags:

sql

jet

ms-access

This works as expected:

SELECT "Mike" AS FName 

This fails with the error "Query input must contain at least one table or query":

SELECT "Mike" AS FName UNION ALL SELECT "John" AS FName 

Is this just a quirk/limitation of the Jet/ACE database engine or am I missing something?

like image 255
mwolfe02 Avatar asked Oct 28 '11 18:10

mwolfe02


People also ask

What is union query in MS Access?

Sometimes you might want to list the records from one table or query with those from one or more other tables to form one set of records - a list with all the records from the two or more tables. This is the purpose of a union query in Access.

How do you close a matchup table in Access?

To close the table window, click its Close button. When the table is open, you can click the Views button on the Standard toolbar in the main Access window to switch from Datasheet view to Design view and vice versa.


2 Answers

You didn't overlook anything. Access' database engine will allow a single row SELECT without a FROM data source. But if you want to UNION or UNION ALL multiple rows, you must include a FROM ... even if you're not referencing any field from that data source.

I created a table with one row and added a check constraint to guarantee it will always have one and only one row.

Public Sub CreateDualTable()     Dim strSql As String     strSql = "CREATE TABLE Dual (id COUNTER CONSTRAINT pkey PRIMARY KEY);"     Debug.Print strSql     CurrentProject.Connection.Execute strSql     strSql = "INSERT INTO Dual (id) VALUES (1);"     Debug.Print strSql     CurrentProject.Connection.Execute strSql      strSql = "ALTER TABLE Dual" & vbNewLine & _         vbTab & "ADD CONSTRAINT there_can_be_only_one" & vbNewLine & _         vbTab & "CHECK (" & vbNewLine & _         vbTab & vbTab & "(SELECT Count(*) FROM Dual) = 1" & vbNewLine & _         vbTab & vbTab & ");"     Debug.Print strSql     CurrentProject.Connection.Execute strSql End Sub 

That Dual table is useful for queries such as this:

SELECT "foo" AS my_text FROM Dual UNION ALL SELECT "bar" FROM Dual; 

Another approach I've seen is to use a SELECT statement with TOP 1 or a WHERE clause which restricts the result set to a single row.

Note check constraints were added with Jet 4 and are only available for statements executed from ADO. CurrentProject.Connection.Execute strSql works because CurrentProject.Connection is an ADO object. If you try to execute the same statement with DAO (ie CurrentDb.Execute or from the Access query designer), you will get a syntax error because DAO can't create check constraints.

like image 161
HansUp Avatar answered Sep 19 '22 13:09

HansUp


If you have access to some system tables, you can emulate a dual table this way:

(SELECT COUNT(*) FROM MSysResources) AS DUAL 

Unfortunately, I'm not aware of any system tables that...

  • are always available, readable (MSysObjects might not be accessible to every connection)
  • contain exactly one record, such as Oracle's DUAL or DB2's SYSIBM.DUAL

So you'd write:

SELECT 'Mike' AS FName FROM (SELECT COUNT(*) FROM MSysResources) AS DUAL UNION ALL SELECT 'John' AS FName FROM (SELECT COUNT(*) FROM MSysResources) AS DUAL 

This is what is being implemented as a syntactic element in jOOQ, for instance.

like image 44
Lukas Eder Avatar answered Sep 20 '22 13:09

Lukas Eder