Problems with field names and appending files in Access SQL - sql

Okay, so I have nearly 200 tables in an Access database. The tables are of plant species abundance data, and I would like to combine them into a master data file. Each table contains basically the same columns of species; however, many are spelled slightly differently.
When I run an SQL query in MS Access it won't let me append the tables with each other because of the field names being spelled just a little different.
Any thoughts that would help?
The query I am running is an append query:
INSERT INTO masterTable SELECT * FROM siteTable
and, as an example, the differences in field names are pretty minor
(e.g. "Spp.A" vs "SppA" or "SpeciesOne" vs "Species1")
Thanks for any help,
Paul

You'll need to use vba for this, you'll also need to change the column names I'm using in the masterTable, which in my example are just column1, column2 & column3, and to set the maximum column index in a couple of places (I've stuck some comments in, so you can see what needs to be changed).
If you dont usually use vba, Create a form with a button, and a click event for the button & put this code in it, then open the form and click the button.
Dim db As Database
Dim tdf As TableDef
Dim ii As Long
dim sql as String
Set db = CurrentDb()
docmd.setwarnings false
For Each tdf In db.TableDefs
'change column list as required:
sql = "INSERT INTO masterTable (Column1, Column2, Column3) SELECT "
'change 2 to maximum column number - 1:
for ii = 0 to 2
sql = sql & tdf.Fields(ii).Name
'change 2 to maximum column number - 1 again:
if ii < 2 then
sql = sql & ","
end if
next
sql = sql & ")"
docmd.runsql sql
Next
docmd.setwarnings true
This should work I think. (I'm hoping there's no syntax errors, as I havent tested it, but the logic isnt exactly rocket science)
Hope this helps

Related

Setting listboxes in MS access form - row by row

I have a requirement in MS Access where a table is displayed as several rows in the form. I have created one form detail record(several fields) that will repeat for each row in the Table1. Lets say I have five columns in the Table1. Based on Column3 value, I would like to have a list of value for Column4 and Column5 during form_load. I have also created a separate Table2 to establish relationship between Column3, Column4 and Column5. I have set up Event procedure to populate the values using sub function. The challenge I have is, not being able to set up different listbox 'value list' for different rows. Any tips on populationg form fields IMRecomExIns and AmendReasonExIns by processing each row in Table1 would be a great help.
Private Sub IMRecomExIns_Click()
Dim CoverType As String
Dim ListRecomm As String
Dim ListAmend As String
Dim db As DAO.Database
Dim tablevar As Recordset
Set db = CurrentDb
Set tablevar = db.OpenRecordset("Table2")
CoverType = "*" & Me.CoverTypeExIns.Value & "*"
ListRecomm = ""
ListAmend = ""
If tablevar.EOF = False And tablevar.BOF = False Then
tablevar.MoveFirst
Do Until tablevar.EOF
If tablevar!CoverType Like CoverType Then
ListRecomm = tablevar!Recommendation
ListAmend = tablevar!AmendReason
tablevar.MoveLast
End If
tablevar.MoveNext
Loop
End If
Me.IMRecomExIns.RowSourceType = "Value list"
Me.IMRecomExIns.RowSource = ListRecomm
Me.AmendReasonExIns.RowSourceType = "Value list"
Me.AmendReasonExIns.RowSource = ListAmend
End Sub
1) I have stored all the value list in a single cell. For example tablevar!Recommendation will have all the values for Me.IMRecomExIns.RowSource, which means the output is will look like "Rec1";"Rec2";"Rec3";etc... Same applies for tablevar!AmendReason "AR1";"AR2';"AR3";ETC... Understand this is not the normalized form of storing data. I want to POC to work before building a full solution with normalized tables.
2) Answered earlier.. the rowsource will be set with all the possible values at the first match, so no point in going all the way to the end of the table
3) CoverTypeExIns is a string, Table 2 have many different possibilities such as "Mortgage Income" and "Family Income", however the Recommendation and Amendreason are same for all "Income" category that comes from Table1. Thats why the wildcard search.
My problem is not with setting the RowSource for a single row, but setting up RowSource for multiple occurrence in of the same IMRecommmendation and AmendReason in MS Access screen.
Here is the design view of the form. This form is linked to MS Access table. For multiple rows the Detail record will repeat itself as many times.
An example of two rows displayed in the screen.
I'm not sure exactly what you are asking/trying to do here.
I can see at several problems with the code that you have:
You are using tablevar.MoveLast in the loop, whic would automatically take you to the end of the recordset.
Also, you are not concatenating (joining together) ListRecomm/ListAmend, you are just setting them equal to a value, so each loop that matches will overwrite any previous value.
Finally, I am not sure what you are doing with trying to find CoverTypeExIns - you are using LIKE, which would indicate that it is text, but not wrapping the value in single quotes. If it is a numeric value, then you should be using "=".
However, rather than opening a recordset, looping it and checking for a match to build up a list of values, it is better to just set the RowSource of listboxes equal to a SQL string (effectively a query).
Something like (assuming CoverType is numeric):
Private Sub IMRecomExIns_Click()
Dim strSQL As String
strSQL = "SELECT Recommendation FROM Table2 WHERE CoverType=" & Me!CoverTypeExIns
Me!AmendReasonExIns.RowSource = strSQL
End Sub
I prefer to declare a string to hold the SQL statement rather than setting the .RowSource directly, as it makes troubleshooting easier.
Regards,
Based on the new information given, below is some VBA code that opens up a recordset based on the information entered in "Cover", and then sets the .RowSource property of the two combo boxes to be the value lists. In my example, don't bother setting the .RowSourceType, as this should be done at design time:
Private Sub IMRecomExIns_Click()
Dim db As DAO.Database
Dim rsData As DAO.Recordset
Dim strSQL As String
Set db = DBEngine(0)(0)
strSQL = "SELECT Recommendation, AmendReason FROM Table2 WHERE CoverType LIKE '*" & Me!cboCover & "*';"
Set rsData = db.OpenRecordset(strSQL)
If Not (rsData.BOF And rsData.EOF) Then
Me!IMRecomExIns.RowSource = rsData!Recommendation
Me!AmendReasonExIns.RowSource = rsData!AmendReason
End If
rsData.Close
Set rsData = Nothing
Set db = Nothing
End Sub
As I have previously stated, you should really normalize the design of your database now, rather than getting in so far that it requires a major re-write.
Regards,

Is it possible to make a dynamic sql statement based on combobox.value in access?

I made a form in access with 2 different comboboxes. The user of
This tool can choose in combobox1: the table (which has to be filtered) and the second combobox2 is the criteria to be filtered( for example Language= “EN”) and the output of this query has to be located in tablex.
The problen what I have is that i cant find a solution for passing the value of the combobox1 to the sql statement. The second one is just like: where [language] = forms!form!combo2.value, but the part where i cant find a solution for is: select * from (combobox1 value)? How can i pass the combobox value as table name to be filtered? Can anyone please help me?
You can't have the table name in the WHERE clause of your query (there might be a hacky way to do it, but it should be discouraged at any case).
If you want to select data from 1 of a number of tables, your best bet is to generate SQL dynamically using VBA. One way to do this (especially if you want/need your query to open in Datasheet View for the end user) is to have a "dummy" query whose SQL you can populate using the form selections.
For example, let's say we have 2 tables: tTable1 and tTable2. Both of these tables have a single column named Language. You want the user to select data from either the first or second table, with an optional filter.
Create a form with 2 combo boxes: One for the tables, and one with the criteria selections. It sounds like you've already done this step.
Have a button on this form that opens the query. The code for this button's press event should look something like this:
Private Sub cmdRunQuery_Click()
Dim sSQL As String
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
If Not IsNull(Me.cboTableName.Value) Then
sSQL = "SELECT * FROM " & Me.cboTableName.Value
If Not IsNull(Me.cboFilter.Value) Then
sSQL = sSQL & vbNewLine & _
"WHERE Language=""" & Me.cboFilter & """"
End If
Set db = CurrentDb
Set qdf = db.QueryDefs("qDummyQuery")
qdf.SQL = sSQL
DoCmd.OpenQuery qdf.Name
End If
End Sub
Note how the SQL is being generated. Of course, using this method, you need to protect yourself from SQL injection: You should only allow predefined values in the combo box. But this serves as a proof of concept.
If you don't need to show the query results, you don't need to use the dummy query: You could just open a recordset based on the SQL and process that.
If you run the code in the afterupdate event of the combobox you can set an SQL statement like this:
Private Sub combobox2_AfterUpdate()
someGlobalVar = "Select * FROM " & me.combobox1.value & " WHERE language = " & _
me.combobox2.value
End Sub
And then call the global with the SQL string wherever you need it.

Access 2010 - How to make multiple queries with changing the criteria automatically

I have a question concerning a "serie of queries". After searching the internet for hours, I am really lost!
I want to make 200 queries with changing criteria (the values from the field "City"). How can I tell Access "please repeat the query on the fields "X", "Y" and "Z" by grouping by the field "City". Is there a simple way to make Access pull the Values of "City" from a list and creating a query having the same name like the Value in "City". And doing that for all 200 Cities?
Unfortunately, I am fairly new to Access and VBA. Any help would be HIGHLY APPRECIATED :)
Thanks in advance
A few options. You could open a recordset containing all your Cities, then loop through it and you get a buncha queries:
dim s as string
dim sql as string
dim r as new adodb.recordset
'populate r with SELECT * FROM tblCities (code not shown here)
s = r![City]
sql = "SELECT * FROM tbl1 WHERE City = '" & s & "';"
debug.print sql
'do whatever you want with the contents of sql

Access SQL How to select randomly a group of contiguous rows

can this be done, say I have rows (1,2,3,4,5) and I want to grab three rows, select one randomly and then get it's neighbors, so maybe the random selection is row (3), I can also grab (2,4) if I wanted its neighbors, do I just pick one at random and then look for the unique key before and after like this or can I do it all in one sql statement.
I was going to use ADO from excel to pull records (so VBA connects to access, opens a recordset with sql instructions and so on).
Hope I was clear!
I would love to just do this all in a SQL statement
I am not sure Access is capable of all the SQL commands such as SQL Server, so this may be a bit of a problem. If you have a primary key though, you can easly generate a Select query in VBA and then pass open recordset with this SQL.
Dim sSQL as String
Dim lRand as Long
Dim rs as ADODB.Recordset 'or DAO.Recordset'
lRand = VBA.Int(VBA.Rnd() * TableRecordCount) ' TableRecordCount is the number of records in the table that you need to get somehow'
sSQL = "SELECT * FROM TableName WHERE (ID>=" & lRand - 1 & " AND ID <=" & lRand + 1
set rs = CurrentDB.OpenRecordset(sSQL, ...)
I am now not absolutely sure of what you want to use and depending on ADODB or DAO choice, you need to open the recordset accordingly with wither Call rs.Open or Set rs = DB.OpenRecordset

Does MS access(2003) have anything comparable to Stored procedure. I want to run a complex query in MS acceess

I have a table, call it TBL. It has two columns,call them A and B. Now in the query I require one column as A and other column should be a comma seprated list of all B's which are against A in TBL.
e.g. TBL is like this
1 Alpha
2 Beta
1 Gamma
1 Delta
Result of query should be
1 Alpha,Gamma,Delta
2 Beta
This type of thing is very easy to do with cursors in stored procedure. But I am not able to do it through MS Access, because apparently it does not support stored procedures.
Is there a way to run stored procedure in MS access? or is there a way through SQL to run this type of query
You can concatenate the records with a User Defined Function (UDF).
The code below can be pasted 'as is' into a standard module. The SQL for you example would be:
SELECT tbl.A, Concatenate("SELECT B FROM tbl
WHERE A = " & [A]) AS ConcA
FROM tbl
GROUP BY tbl.A
This code is by DHookom, Access MVP, and is taken from http://www.tek-tips.com/faqs.cfm?fid=4233
Function Concatenate(pstrSQL As String, _
Optional pstrDelim As String = ", ") _
As String
'example
'tblFamily with FamID as numeric primary key
'tblFamMem with FamID, FirstName, DOB,...
'return a comma separated list of FirstNames
'for a FamID
' John, Mary, Susan
'in a Query
'(This SQL statement assumes FamID is numeric)
'===================================
'SELECT FamID,
'Concatenate("SELECT FirstName FROM tblFamMem
' WHERE FamID =" & [FamID]) as FirstNames
'FROM tblFamily
'===================================
'
'If the FamID is a string then the SQL would be
'===================================
'SELECT FamID,
'Concatenate("SELECT FirstName FROM tblFamMem
' WHERE FamID =""" & [FamID] & """") as FirstNames
'FROM tblFamily
'===================================
'======For DAO uncomment next 4 lines=======
'====== comment out ADO below =======
'Dim db As DAO.Database
'Dim rs As DAO.Recordset
'Set db = CurrentDb
'Set rs = db.OpenRecordset(pstrSQL)
'======For ADO uncomment next two lines=====
'====== comment out DAO above ======
Dim rs As New ADODB.Recordset
rs.Open pstrSQL, CurrentProject.Connection, _
adOpenKeyset, adLockOptimistic
Dim strConcat As String 'build return string
With rs
If Not .EOF Then
.MoveFirst
Do While Not .EOF
strConcat = strConcat & _
.Fields(0) & pstrDelim
.MoveNext
Loop
End If
.Close
End With
Set rs = Nothing
'====== uncomment next line for DAO ========
'Set db = Nothing
If Len(strConcat) > 0 Then
strConcat = Left(strConcat, _
Len(strConcat) - Len(pstrDelim))
End If
Concatenate = strConcat
End Function
I believe you can create VBA functions and use them in your access queries. That might help you.
There is not a way that I know of to run stored procedures in an Access database. However, Access can execute stored procedures if it is being used against a SQL backend. If you can not split the UI to Access and data to SQL, then your best bet will probably be to code a VBA module to give you the output you need.
To accomplish your task you will need to use code. One solution, using more meaningful names, is as follows:
Main table with two applicable columns:
Table Name: Widgets
Field 1: ID (Long)
Field 2: Color (Text 32)
Add table with two columns:
Table Name: ColorListByWidget
Field 1: ID (Long)
Field 2: ColorList (Text 255)
Add the following code to a module and call as needed to update the ColorListByWidget table:
Public Sub GenerateColorList()
Dim cn As New ADODB.Connection
Dim Widgets As New ADODB.Recordset
Dim ColorListByWidget As New ADODB.Recordset
Dim ColorList As String
Set cn = CurrentProject.Connection
cn.Execute "DELETE * FROM ColorListByWidget"
cn.Execute "INSERT INTO ColorListByWidget (ID) SELECT ID FROM Widgets GROUP BY ID"
With ColorListByWidget
.Open "ColorListByWidget", cn, adOpenForwardOnly, adLockOptimistic, adCmdTable
If Not (.BOF And .EOF) Then
.MoveFirst
Do Until .EOF
Widgets.Open "SELECT Color FROM Widgets WHERE ID = " & .Fields("ID"), cn
If Not (.BOF And .EOF) Then
Widgets.MoveFirst
ColorList = ""
Do Until Widgets.EOF
ColorList = ColorList & Widgets.Fields("Color").Value & ", "
Widgets.MoveNext
Loop
End If
.Fields("ColorList") = Left$(ColorList, Len(ColorList) - 2)
.MoveNext
Widgets.Close
Loop
End If
End With
End Sub
The ColorListByWidget Table now contains your desired information. Be careful that the list (colors in this example) does not exceed 255 characters.
No stored procedures, no temporary tables.
If you needed to return the query as a recordset, you could use a disconnected recordset.
Perhaps instead of asking if Jet has stored procedures, you should explain what you want to accomplish and then we can explain how to do it with Jet (it's not clear if you're using Access for your application, or just using a Jet MDB as your data store).
Well, you can use a Recordset object to loop through your query in VBA, concatenating field values based on whatever criteria you need.
If you want to return the results as strings, you'll be fine. If you want to return them as a query, that will be more complicated. You might have to create a temporary table and store the results in there so you can return them as a table or query.
You can use GetString in VBA which will return the recordset separated by any value you like (e.g. comma, dash, table cells etc.) although I have to admit I've only used it in VBScript, not Visual Basic. W3Schools has a good tutorial which will hopefully lend itself to your needs.
You can write your stored procedure as text and send it against the database with:
Dim sp as string
sp = "your stored procedure here" (you can load it from a text file or a memo field?)
Access.CurrentProject.AccessConnection.Execute sp
This supposes you are using ADODB objects (ActiveX data Objects Library is coorectly referenced in your app).
I am sure there is something similar with DAO ...
#Remou on DHookom's Concatenate function: neither the SQL standard nor the Jet has a CONCATENATE() set function. Simply put, this is because it is a violation of 1NF. I'd prefer to do this on the application side rather than try to force SQL to do something it wasn't designed to do. Perhaps ACE's (Access2007) multi-valued types is a better fit: still NFNF but at least there is engine-level support. Remember, the question relates to a stored object: how would a user query a non-scalar column using SQL...?
#David W. Fenton on whether Jet has stored procedures: didn't you and I discuss this in the newsgroups a couple of years ago. Since version 4.0, Jet/ACE has supported the
following syntax in ANSI-92 Query Mode:
CREATE PROCEDURE procedure (param1 datatype[, param2 datatype][, ...]) AS sqlstatement;
EXECUTE procedure [param1[, param2[, ...]];
So Jet is creating and executing something it knows (in one mode at least) as a 'procedure' that is 'stored' in the MDB file. However, Jet/ACE SQL is pure and simple: it has no control-of-flow syntax and a PROCEDURE can only contain one SQL statement, so any procedural code is out of the question. Therefore, the answer to whether Jet has stored procedures is subjective.