creating queries during runtime in msaccess - ms-access

i have to create reports with certain data from an access database. i want to automate this process by the use of visual basic. i have created queries to achieve this but the problem is each time i have a different database(with same structure).
queries that i have has "create table", due to which i am unable to fire those queries from VB6 directly. Is there any way i can solve this problem?

You can use the IN clause in SQL queries to reference different MDB files. For example:
"SELECT srpID, srpServiceRecordID, srpInvoiceDate, srpInvoiceNumber, srpParts " & _
"FROM ServiceRecordParts IN '" & strDatabasePathandName & "';"

You can run a CREATE TABLE SQL DDL statement (not a query!) against the Access database engine from VB6 by using a data access technology. ADO is best for DDL (e.g. richer syntax than DAO).
You can create a new table, including data, using
SELECT * INTO MyTableClone FROM MyTable;
but it will not copy any constraints e.g. all columns will be nullable :(
You can also use SQL DDL to create a VIEW or a PROCEDURE depending on what you mean by 'query'.

You can run both queries and SQL from VBA. Here are a few notes.
Dim db As Database
Dim strSQL As String
Dim qdf As QueryDef
''Execute
Set db = CurrentDb
strSQL = "SELECT EmpID, EmpName INTO NewT FROM tblT WHERE EmpName Is Not Null"
''This will fail if the table already exists
''Only Action queries can be Executed
db.Execute strSQL, dbFailOnError
Debug.Print db.RecordsAffected
''This is not such a good approach
''Open query, will give warning
''that the table is about to be deleted.
DoCmd.OpenQuery "qryUpdate"
''Also not so good
''Open query, skip warning
DoCmd.SetWarnings False
DoCmd.OpenQuery "qryUpdate"
''This line is very important indeed
''never set warnings off, unless you
''set then on again
DoCmd.SetWarnings True
''Use query
Set qdf = db.QueryDefs("qryUpdate")
''The table in this SQL already exists, so
''a small diversion
db.Execute "DROP TABLE NewT", dbFailOnError
''Back on track
qdf.Execute dbFailOnError
Debug.Print qdf.RecordsAffected
''Change query SQL
qdf.SQL = strSQL
''Use SQL from query
strSQL = qdf.SQL
''The table in this SQL already exists, so
''a small diversion
db.Execute "DROP TABLE NewT", dbFailOnError
''Back on track
db.Execute strSQL, dbFailOnError
Debug.Print db.RecordsAffected
Your database will need a lot of compacting if you regularly add and delete tables and queries, so it is usually best to avoid this.

Related

Aceess make table from a DNS-Less connection

I'm using the below code to create a DNS-Less connection to an Oracle DB and this code works fine. Some information has been removed due to its sensitive nature. Again the posted code is working. I'm looking to add the ability to make a table within access. How do I take the query results and place them into a table?
Dim tdf As TableDef
Dim DB As Database
Set DB = CurrentDb
'Rem create link to groups def
Set tdf = DB.CreateTableDef("Sale")
tdf.Connect = "ODBC;Driver={Microsoft ODBC for Oracle};Server=" & ServerName & ";UID=" & UID & ";Pwd=" & PWD & ""
tdf.SourceTableName = "SBOMAST_OWN.SALE"
DB.TableDefs.Append tdf
DB.Close
Set DB = Nothing
Assuming you want to make the table from scratch, you will want to use a make table query, which in VBA, takes the form of SELECT * INTO Target FROM Source. I know with ODBC, you can put the connection string directly into the Target and Source values, eliminating the need for a recordset. Your query would become:
"SELECT * INTO NewAccessTable FROM (" & strConnectionString & ") OracleDBTable"
Check out this article for more information: http://support.microsoft.com/kb/200427

MSAccess: Get ItemIDs from Recordsetclone into New Table?

I have an AccessDB app where I need to grab the ItemIDs for the current user-applied filter into a new table to use downstream. Using the subform datasheet .recordsetclone property I can see the desired recordset, .recordcount reports the correct number of records. Otherwise, the following does not produce the desired temp table and AccessVBA does not complain.
Dim db As DAO.Database
Dim rstItemIDs As DAO.Recordset
Dim strSQL as String
Set db = CurrentDb
set rstItemIDs = Forms!Mainform![Data subform].Form.RecordsetClone
msgbox rstItemIDs.recordcount 'reports the correct result
strSQL = "SELECT rstItemIDs.ItemID INTO tempTable FROM rstItemIDs;"
db.Execute strSQL
Is it possible to construct a SQL Select query against a dao.recordset?
Thanks for any pointers you can provide.
Access SQL will not accept either a DAO or ADODB Recordset as the data source for a query.
However, I'm puzzled that Access does not complain when you try. With every attempt I made to reproduce your sample code, I got error #3078, "The Microsoft Access database engine cannot find the input table or query 'rstItemIDs'. Make sure it exists and that its name is spelled correctly."
Even DoCmd.SetWarnings False did not suppress that error message.
If you're interested in alternatives, you could persist tempTable (instead of creating a new version each time), then delete its contents and move through rstItemIDs adding each value to the second recordset. Although that is a RBAR (row by agonizing row) method, it may not be too painful with a small recordset.
A set-based approach could be to create a query based on your form's .RecordSource and .Filter properties. For example, with my form's .RecordSource as SELECT * FROM foo and the current form .Filter as id>10, this would give me a SELECT which returns the form's filtered records:
Replace(Me.RecordSource, ";", "") & vbcrlf & "AND " & Me.Filter

access 2010 bloat with forms based on pass through queries

My access 2010 database has super massive bloat. It has gone from 44mb to 282mb in just a few runs of the VBA. Here is what I have set up:
Local tables - these calculate statistics on forms and generally don't move around too much.
Pass through queries - my personal suspect. While viewing a form, if the user clicks on a record I run a pass through query using the record the user clicked on. So user clicked on "joe", pass through query runs with sql string = "select * from sqlserver where name= " &[forms]![myform]![firstname]
After this query runs, my vba DELETES the pass through query, then recreates it after another record is selected. so the user goes back to the list of names, and clicks BRIAN. then my vba deletes the pass through query and creates another one to select all records named brian from sql server, using the same code as above.
Forms - my forms are using the pass through queries as sources.
Is what I'm doing not very smart? How can I build this better to prevent access from exploding in file size? I tried compact and repair, as well as analyze DB performance in access 2010. Any help at all is appreciated, I've been googling access2010 bloat and have read about temptables as well as closing DAO (which I am using, and which I did explicitly close). Thanks!
Here is some code for 1 of the forms i'm using -
Private Sub name_Click()
'set dims
Dim db As DAO.Database
Dim qdExtData As QueryDef
Dim strSQL As String
Dim qdf As DAO.QueryDef
'close form so it will refresh
DoCmd.Close acForm, "myform", acSaveNo
'delete old query so a new one can be created with the same name
For Each qdf In CurrentDb.QueryDefs
If qdf.Name = "QRY_PASS_THROUGH" Then
DoCmd.Close acQuery, "QRY_PASS_THROUGH", acSaveNo
DoCmd.SetWarnings False
DoCmd.DeleteObject acQuery, "QRY_PASS_THROUGH"
DoCmd.SetWarnings True
Exit For
End If
Next
Set db = CurrentDb
'sql for the data
strSQL = "select fields from (table1 inner join table2 on stuff=stuff and stuff=stuff) left join table3 on stuff=stuff and stuff=stuff where flag='P' and table.firstname = " & [Forms]![myform]![firstname]
Set qdExtData = db.CreateQueryDef("QRY_PASS_THROUGH")
'how you connect to odbc
qdExtData.Connect = "ODBC;DSN=server;UID=username;PWD=hunter2;"
qdExtData.SQL = strSQL
DoCmd.OpenForm ("names")
Forms!returns!Auto_Header0.Caption = "Names for " & Me.name & " in year " & Me.year
qdExtData.Close
db.Close
qdf.Close
Set db = Nothing
Set qdf = Nothing
End Sub
There no reason I can think of to not bind the form to a view and use the “where clause” of the open form command. It would eliminate all that code.
You could then simply use:
strWhere = "table.FirstName = '" & me.FirstName & "'"
Docmd.OpenForm "Names”,,,strWhere
Also, it makes little or no sense that a C + R does not return free space. Something else here is seriously wrong.
Also, you really don’t need to delete the query each time. Just assume that the pass-through ALWAYS exists and then use this:
strSQl = “your sql goes here as you have now”
Currentdb.Querydef("MyPass").SQL = strSQL
Docmd.Openform “your form”
The above is all you need. I count about 3 lines of code here that will replace all what you have now. Note that of course the connection string info is saved with the pass-though and does not need to be set or messed with each time.
I would also do a de-compile of your database. I have a short cut setup on all my dev machines so I can just right click to de-compile. Here is some info on de-compile:
http://www.granite.ab.ca/access/decompile.htm
So really, I don’t know why you not using the where clause of the open form? Just bind the form to a SQL view without any conditions. Then use the open form command – you only pull records down the network pipe that match your criteria.
And note how you can stuff your SQL directly into the .SQL property of the query def as above shows – again no need for that delete code and this also means you don’t mess with connection info in code either. Again about 3 lines in total.

Access variable Field Names

In MS Access 2010, I am building an update query (using the Query Designer).
I would like to pass the name of the column to update as a variable, at run time.
I have tried writing the SQL and running the query in VBA. This seemed like the easiest way... however the SQL to complete the update becomes quite messy. I would prefer to do this in the query builder GUI .
Is it possible?
I have so far tried entering field names into the query builder:
expr1:[field_name]
Although Access prompts me for "Field_name" This results in "Cannot update 'field_name'; field not updateable.
Also, I tried this method:
Expr1: "'" & [field_name] & "'"
which results in "'" & [field_name] & "'" is not a valid name; check for punctuation.. etc
Below is a screen capture the query I am trying to build.
Access' db engine will not allow you to use a parameter as the name of the target field for your UPDATE statement.
If you try a user-defined function instead of a parameter to provide the field name, the result will be the same ... no joy.
It seems the db engine will not resolve object names when it executes a SQL statement. That limitation applies not just to field names, but table names as well. IOW, the following query will fail with an error message that it "cannot find the input table or query 'give me a table name'".
SELECT *
FROM [give me a table name];
While that isn't exactly the same as your situation, I suspect the reason may be. The db engine is too limited about resolving object names when it plans/executes queries.
Perhaps the best method is to use SQL, build your prompts and then assign these values to variables in VBA, then just add the variable value into your SQL.
So something along these lines. Your using Update query but same logic
Dim SQL as string
dim **FieldName** as string
SQL = "Select [table]![" & Chr(34) & **FieldName** & Chr(34) & "] from ........"
Check Here for SQL building tips
I use this method frequently - I know it's a very old post, but hope this helps someone - building on what David said:
Sub CreateQuery
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Dim strSQL As String
Set dbs = CurrentDb
Set qdf = dbs.CreateQueryDef("NameOfNewQuery")
strSQL = "Select " 'notice the space
strSQL = strSQL & "FROM " 'notice the sapce
strSQL = strSQL & "WHERE;"
qdf.SQL = strSQL
qdf.Close
Set qdf = Nothing
Set dbs = Nothing
End Sub

Errors on Opening Recordset MSAccess

I am using the following code in Access to try to open a recordset:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("fieldHistory")
I consistently get the error "Too few parameters."
fieldHistory is a query with the SQL code as follows:
SELECT Date, User, Type
FROM Inventory
WHERE ((Inventory.Type) In ("Insert","EditTo"));
I have looked into this some - I have found that if I use the code db.OpenRecordset("Select * from Inventory") I do not get an error.
Also, I found this forum which seemed to be on to something but I couldn't understand how to create the appropriate querydef objects to create my query.
http://access.mvps.org/access/queries/qry0013.htm
Thank you very much!
Date, User, and Type are all special words or reserved words in MS Access. DO NOT use them for your field names.
You may have some success by enclosing each of them in brackets but I highly recommend you change the field names instead.
Create a new database.
Open the new database and make sure you have DAO included in the references.
Insert a new standard module, making sure to include Option Explicit in the Declarations section.
Then paste in this code and run it.
Public Sub CreateTableZack()
Dim strSql As String
strSql = "CREATE TABLE tblZack (" & vbNewLine & _
vbTab & "id COUNTER CONSTRAINT pkey PRIMARY KEY," & vbNewLine & _
vbTab & "foo_text TEXT(255)," & vbNewLine & _
vbTab & "date_assigned DATETIME);"
Debug.Print strSql
CurrentProject.Connection.Execute strSql
End Sub
Assuming the table is created successfully, create qryZack with this as its SQL:
SELECT *
FROM tblZack;
Then try your code to open a DAO recordset based on qryZack.
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("qryZack")
Does it work?
If not, your Access installation may be hosed ... you may need to repair or reinstall it. You could also try this on another machine which has Access available, if you can.
If it works with the new database, but not your old one, the old one may be corrupted. Make a backup copy first, then try Compact & Repair.
Another issue is your field names. Date, User and Type are all Access reserved words. See Problem names and reserved words in Access. I can't say those names are causing problems here, but using reserved names for database objects (tables, fields, queries, etc.) can have dramatic consequences ... like it confuses the crap out of Access. So I fastidiously avoid them.
Edit: You should also check the references in your old database. Missing/broken references also confuse the crap out of Access.