How to delete all rows from table before starting inserting them?
Two things. First, DAO vs ADO is almost irrelevant. They are both available to Access up through Windows 7 and AFAIK there are no plans to remove them. Either should be OK to use in Access.
Secondly, you can just do this:
Public Sub Example()
With Access.CurrentDb
.Execute "DELETE Table2.* FROM Table2;"
.Execute "INSERT INTO Table2 ( fld1, fld2 ) SELECT Table1.ID, Table1.MyField FROM Table1;"
End With
End Sub
You could just to this:
Public Sub Example()
With Access.DoCmd
.RunSQL "DELETE Table2.* FROM Table2;"
.RunSQL "INSERT INTO Table2 ( fld1, fld2 ) SELECT Table1.ID, Table1.MyField FROM Table1;"
End With
End Sub
But the Execute method throws more informative error messages (and if you still care, is DAO).
If you are programming vba I assume that you are working with Adodb or simply ADO.
Therefore in order to delete a table records you can use a command object to do that.
Dim cnn as Connection
Dim cmd as Command
Set cnn=new Connection()
cnn.ConnectionString="ConnectionString"
cnn.Open()
Set cmd=new Command()
cmd.ActiveConnection=cnn
cmd.CommandText="DELETE FROM MyTable"
cmd.Execute()
cnn.Close()
Updated:
In order to use ADO objects you should add a reference to ADODB library
DAO Recordsets don't have an effective way to empty the table, as far as I know. If it's a small table, you can probably delete record-by-record, but I would find that silly. I just use DoCmd.RunSQL to run a DELETE query. I would typically set SetWarnings to False temporarily, of course.
Since this is separate from DAO, I would see that operation through before opening the recordset properly.
Please try this:
Do While Not rs.EOF
rs.Delete
rs.MoveNext
Loop
Related
I have an Access DB, it's a local development copy, not production, and corrupted during (ironically) compact and repair, a large amount of data. Unfortunately I did a lot of work on it and I do have a backup plan but it failed me..
When I start it up it gives me useless error messages like:
'Id' is not an index in this table.
'ParentIdName' is not an index in this table.
I suppose these indexes are part of the hidden MSys* tables in the DB. I managed to read those and they're mostly empty while my older healthy backup has a lot of data in these tables.
First I tried to restore the healthy tables into the destroyed ones using VBA and an ADO connection (made a copy beforehand), I get a lot of errors saying I don't have write permissions on the tables.
Next attempt, still ongoing, is to recover the query definitions (90%+ of my changes) through the same ADO connection (tried ADOX and DAO too).
The most successful attempt was ADO:
Sub DebugPrintQueryDefsADO()
Dim dmgDB As DAO.Database
Dim dmgQD As DAO.QueryDef
Set dmgDB = DBEngine.OpenDatabase("C:\Database.accdb", , True)
For Each dmgQD In dmgDB.QueryDefs
If Left(dmgQD.Name, 1) <> "~" Then ' ~ Query defs seem to be the form views'
Debug.Print "---------------------------------"
Debug.Print dmgQD.Name
Debug.Print "---------------------------------"
Debug.Print dmgQD.SQL
End If
Next dmgQD
Set dmgQD = Nothing
Set dmgDB = Nothing
End Sub
This actually works! As long as the Query definition evaluation runs fine first. Which in my case cannot be true for most QD's since the tables are imported when required and then deleted. This means that the fields defined in the QD's cannot be found because the tables aren't there. Then Access presents me an error:
3258: The SQL Statement could not be executed because it contains ambiguous outer joins. To force one of the joins to be performed first, create a separate query that performs the first join and then include that query in your SQL statement.
Go home Access, you're drunk.
Next quest was to figure out how to not evaluate the SQL statement (I only need the SQL statement, not the result). I found that there is a property: Querydef.Prepare in this Access 2007 doc: http://msdn.microsoft.com/en-us/library/office/bb208511(v=office.12).aspx
According to the documentation (of Access 2007, I have 2010), I should set
Querydef.Prepare = dbQUnprepare. But that does not work..
So long problem short..
Is anyone aware of a way to fix the corrupted DB?
OR..
Does anyone know how to retrieve my SQL statements from the query definitions without the need to evaluate them?
Thanks!
One option you could try would be
Application.SaveAsText acQuery, "QueryName", "C:\path\QueryName.txt"
At least in some cases it dumps the SQL string at the beginning of the file (with some arbitrary breaks and escaped characters, just to keep things interesting). For example:
dbMemo "SQL" ="SELECT YEAR(Assigned.[Date]) AS Yr, MONTH(Assigned.[Date]) AS Mo, SUM(Assigned.["
"Hours Worked]) AS Hrs\015\012FROM Assigned INNER JOIN Projects ON Projects.[Proj"
"ect Name] = Assigned.[Project Name]\015\012WHERE Projects.Billable\015\012GROUP "
"BY YEAR(Assigned.[Date]), MONTH(Assigned.[Date]);\015\012"
dbMemo "Connect" =""
dbBoolean "ReturnsRecords" ="-1"
dbInteger "ODBCTimeout" ="60"
dbBoolean "OrderByOn" ="0"
dbByte "Orientation" ="0"
dbByte "DefaultView" ="2"
dbBinary "GUID" = Begin
0x1304ebdf78bef2459211d478954077cd
End
dbBoolean "FilterOnLoad" ="0"
dbBoolean "OrderByOnLoad" ="-1"
dbLongBinary "DOL" = Begin
0x0acc0e5500000000534cc617867b4d43b98002a1b002c8eb00000000c732603a ,
0xa958e4400000000000000000410073007300690067006e006500640000000000 ,
0x00006b84dfe37aec2248a1ccfe3e157361df0000000040b3affda358e4400000 ,
0x000000000000500072006f006a006500630074007300000000000000d5b092f5 ,
0x1c13394884636d668e066e66070000001304ebdf78bef2459211d478954077cd ,
0x59007200000000000000efa363bc29cbfc478a958e7b935d03da070000001304 ,
0xebdf78bef2459211d478954077cd4d006f00000000000000b1174c1abe1d3d4c ,
0xb9a1a7e5915a2e47070000001304ebdf78bef2459211d478954077cd48007200 ,
0x7300000000000000b2e4aa9aab3a9e479c47b2772754fce107000000534cc617 ,
0x867b4d43b98002a1b002c8eb4400610074006500000000000000404c3a80ef29 ,
0xa4498e153e354319e84c07000000534cc617867b4d43b98002a1b002c8eb4800 ,
0x6f00750072007300200057006f0072006b0065006400000000000000a3a95acb ,
0xe7ec994bab8df870ce5b3d98070000006b84dfe37aec2248a1ccfe3e157361df ,
0x500072006f006a0065006300740020004e0061006d006500000000000000f5cb ,
0xefb11bcf5e4da4b2806eed09a70207000000534cc617867b4d43b98002a1b002 ,
0xc8eb500072006f006a0065006300740020004e0061006d006500000000000000 ,
0x453445bf7e67b54ead2c9317ca29d906070000006b84dfe37aec2248a1ccfe3e ,
0x157361df420069006c006c00610062006c006500000000000000000000000000 ,
0x000000000000000000000c000000050000000000000000000000000000000000
End
dbByte "PublishToWeb" ="1"
Begin
Begin
dbText "Name" ="Yr"
dbLong "AggregateType" ="-1"
dbBinary "GUID" = Begin
0xd5b092f51c13394884636d668e066e66
End
End
Begin
dbText "Name" ="Mo"
dbLong "AggregateType" ="-1"
dbBinary "GUID" = Begin
0xefa363bc29cbfc478a958e7b935d03da
End
End
Begin
dbText "Name" ="Hrs"
dbLong "AggregateType" ="-1"
dbBinary "GUID" = Begin
0xb1174c1abe1d3d4cb9a1a7e5915a2e47
End
End
End
You can use Access Fix from AccessFix.com, if you have a copy of the database, which just got corrupted, and you didn't try anything on it that may have changed the data. Like, if you tried to compact and repair, your objects are gone after that. I use it at work and it fixes dbs for me in most cases. I would also try http://allenbrowne.com/tips.html, can't quite remember, but he had a set of steps there that you can use to recover the entire database from text. I think he explained it in his tips and tricks book, with Dough Steele, also
I'm having trouble with an update query in Access.
I'm trying to do two things, add a field to a table, and change all values in another field to the same value.
ALTER TABLE 103 ADD COLUMN test TEXT;
UPDATE 103 SET [103].Workcenter = "103";
When I run these two lines independently, they work fine, but when I put them in the same query I get "Syntax Error in ALTER TABLE" statement. Does anyone know why I can't do this?
It would also be great if I could add a column and update all values in that field to a default value. I've tried DEFAULT in the ALTER TABLE command but it's not working either.
Thanks in advance for suggestions!
AS ron tornambe said, you can't have more than a single command in an Access Query. They do not support batching.
VBA code is your friend when doing alterations on tables: The Data Definition Language used in Access is more limited than what is available from VBA when directly manipulating the database objects.
For instance, to do exactly what you seek:
Public Sub AddFieldAndUpdate()
' Initialise '
Dim db As DAO.Database
Dim tb As DAO.TableDef
Dim fd As DAO.Field
Set db = CurrentDb()
' Get the 103 table '
Set tb = db.TableDefs("103")
' Create a new 'test' field, 128 char long '
Set fd = tb.CreateField("test", dbText, 128)
' Set the Default value for the new field '
fd.DefaultValue = "000"
' Add the new field to the 103 table
tb.Fields.Append fd
' Now do the update
db.Execute "UPDATE 103 SET [103].Workcenter = '103';", dbFailOnError
Debug.Print "Number of Updated records: " & db.RecordsAffected
' Cleanup
Set fd = Nothing
Set tb = Nothing
Set db = Nothing
End Sub
This is the jest of it, although you probably want to do more than that, for instance, set indexes, default formatting, etc as required.
Some table design features are only available when using the DAO object model to modify the TableDef. Others are only available when executing a DDL statement from an ADO connection.
Your table design change involves features which are available with either method. Use whichever you wish, but I would personally choose this way:
Dim strDdl As String
strDdl = "ALTER TABLE 103 ADD COLUMN test TEXT(128) DEFAULT ""000"";"
CurrentProject.Connection.Execute strDdl
I have the following 'set recordset' line that I cannot get working. The parameters seem correct according to all available help I can find on the subject.
The error displays :
"Run-time error '3061'. Too few parameters. Expected 1."
Here is the line of code:
Set rs = dbs.OpenRecordset("SELECT Centre_X, Centre_Y FROM [qry_all_details]
WHERE ID = " & siteID & ";", dbOpenSnapshot)
Where rs is the recordset (Dim rs As Recordset) and dbs = CurrentDb()
Any help would be appreciated.
I have tried removing the WHERE cause with no effect, and also using single quotes between double quotes, but no joy.
Many thanks.
"Run-time error '3061'. Too few parameters. Expected 1."
I believe this happens when the field name(s) in your sql query do not match the table field name(s), i.e. a field name in the query is wrong or perhaps the table is missing the field altogether.
you have:
WHERE ID = " & siteID & ";", dbOpenSnapshot)
you need:
WHERE ID = "'" & siteID & "';", dbOpenSnapshot)
Note the extra quotations ('). . . this kills me everytime
Edit: added missing double quote
(For those who read all answers). My case was simply the fact that I created a SQL expression using the format Forms!Table!Control. That format is Ok within a query, but DAO doesn't recognize it. I'm surprised that nobody commented this.
This doesn't work:
Dim rs As DAO.Recordset, strSQL As String
strSQL = "SELECT * FROM Table1 WHERE Name = Forms!Table!Control;"
Set rs = CurrentDb.OpenRecordset(strSQL)
This is Ok:
Dim rs As DAO.Recordset, strSQL, val As String
val = Forms!Table!Control
strSQL = "SELECT * FROM Table1 WHERE Name = '" & val & "';"
Set rs = CurrentDb.OpenRecordset(strSQL)
My problem was also solved by the Single Quotes around the variable name
I got the same error message before.
in my case, it was caused by type casting.
check if siteID is a string, if it is you must add simple quotes.
hope it will help you.
My problem turned out to be, I had altered a table to add a column called Char.
As this is a reserved word in MS Access it needed square brakcets (Single or double quote are no good) in order for the alter statement to work before I could then update the newly created column.
Make sure [qry_all_details] exists and is runnable. I suspect it or any query it uses, is missing the parameter.
I got the same error with something like:
Set rs = dbs.OpenRecordset _
( _
"SELECT Field1, Field2, FieldN " _
& "FROM Query1 " _
& "WHERE Query2.Field1 = """ & Value1 & """;" _
, dbOpenSnapshot _
)
I fixed the error by replacing "Query1" with "Query2"
In my case, I got this error when I tried to use in a query a new column, which I added to MySQL table (linked to MS Access), but didn't refresh it inside MS Access.
To refresh a linked remote table:
Open "Linked Table Manager" ("External Data" tab on ribbon);
Select a checkbox near the table you want to refresh;
Press "OK" button.
In my case I was receiving this error when running a query from VBA with this command:
CurrentDb.Execute "qryName"
Double clicking on the query to execute it, worked fine, no error.
Changing the code to the following also worked fine, no error.
DoCmd.OpenQuery "qryName"
Hope this helps someone else who is unexpectedly getting this error.
If someone could explain why the first command caused the error I'd love to know.
Does the query has more than the parameter siteID, becouse if you want to run the query one parameter still isn't filled witch gives you the error
In my case, I had simply changed the way I created a table and inadvertently changed the field name I tried to query. Make sure the field names you reference in the query actually exist in the table/query you are querying.
This Message is also possible to pop up, if there is a typo in the fields on which you define a join
Thanks for John Doe's solution that helped a lot. Mine is very similar with some difference, using TempVars
Instead of :
strSQL = "SELECT * FROM Table1 WHERE Name = Forms!Table!Control;"
I used:
strSQL = "SELECT * FROM Query1" , Query1 being common for other usage
Query1 as:
"Select Field1, Field2 from Table1 where Id= [TempVars]![MyVar]
And similarly, removing [TempVars]![MyVar] from view solved the problem.
In My case I had an INSERT INTO TableA (_ ,_ ,_) SELECT _ ,_ ,_ from TableB, a run-time error of 33061 was a field error. As #david mentioned. Either it was a field error: what I wrote in SQL statement as a column name did not match the column names in the actual access tables, for TableA or TableB.
I also have an error like #DATS but it was a run-time error 3464.
If I want to code the following in VBA how do I do it
QUERY1:
SELECT field1, Min(field4) AS MinField4, Max(field5) AS MaxField5
FROM Table1
GROUP BY field1;
SELECT Query1.field1, Table1.field2, Table1.field3, Query1.MinField4,
Query1.MaxField5
FROM Query1 INNER JOIN Table1 ON (Query1.field1 = Table1.field1) AND
(Query1.MinField4 = Table1.field4) AND
(Query1.MaxField5 = Table1.field5);
I know for executing the SQL I store it as as string and write run SQL.
but how do I code storing query1 as a persistent object that can be referenced in other SQL statements?
Here some code that will fill up a dataset with your results
Dim cnn As ADODB.Connection
Dim recordset As ADODB.Recordset
Dim strSQL As String
Set cnn = CurrentProject.Connection
strSQL = "SELECT blah ..."
recordset.Open strSQL, cnn, adOpenKeyset, adLockOptimistic, adCmdText
'do what you want now.
oh yeah its been a while but you probably want to clean up too
Set recordset = Nothing
'etc..
I take it your question is "How do I create a new query in Microsoft Access using code?"
There are two solutions:
Microsoft Access will accept the DDL statement CREATE VIEW. So you can construct that statement in code and then execute it against the database via OLE DB e.g. ADO in VBA code.
The database object in MS Access contains a collections property called QueryDefs and you can access that to manipulate (and create) queries stored in the database.
you could just create a query and paste that SQL into the SQL View (available from the query design window).
I am using Access 2007 and have some linked tables to a mySQL database. I am using DAO to insert a record into a mySQL linked table and trying to retrieve the inserted PK using Select ##identity, but that select is returning 0.
Dim sql As String
Dim oDB As Database
Set oDB = CurrentDb
sql = "INSERT INTO Quotes ( CustomerID ) SELECT 1 AS Expr1;"
oDB.Execute sql
If oDB.RecordsAffected <> 1 Then
MsgBox "cannot create new quote"
Exit Function
End If
Dim rsNewID As DAO.Recordset
Set rsNewID = oDB.OpenRecordset("SELECT ##IDENTITY") ' Create a recordset and SELECT the new Identity
Dim intNewID As Long
intNewID = rsNewID(0).Value ' Store the value of the new identity in variable intNewID
'This value is 0, why?
I've seen another question like this, that has not been satisfactorily answered for me
SELECT LAST_INSERT_ID()
fredrik gets partial credit, for the mySQL statement. It's important to note that I am using DAO, so statements are processed by the JET engine and it does not support this statement. This needs to be run as a pass through query in Access in order to work though. After I made a pass through query with fredrik's select statement, that did the trick. I called this Access passthrough query from my DAO code and it worked.
I have not used mysql. So, translate what I say for mysql.
Is CustomerID an identity column (i.e. does it generate ID on its own)?
If so, use the function that returns the last generated ID.
##Identity function is what people use in SQL Server. I don''t know of equivalent in mysql.
See this
Looking at the code above, you need not open the 2nd recordset. The rsNewID1 should help you get the last inserted ID.
Hope this helps.