I need to clear the contents of multiple tables in an Access db using VBA.
Below is the code I am attempting to use, but it throws a "Syntax error in FROM clause." The SQL syntax (DELETE * FROM [table name];) works in a query.
Dim tbl As TableDef
Dim sqlstr As String
DoCmd.SetWarnings False
For Each tbl In CurrentDb.TableDefs
If tbl.Name Like "*_drop" Then
sqlstr = "DELETE * FROM " & tbl.Name
DoCmd.RunSQL sqlstr
End If
Next tbl
I found a similar problem and answer here, but it did not solve my problem.
I have also tried it without the sqlstr and received the same error.
For Each tbl In CurrentDb.TableDefs
If tbl.Name Like "*_drop" Then
DoCmd.RunSQL "DELETE * FROM " & tbl.Name
End If
Next tbl
You confirmed a query like this works without error.
DELETE * FROM [table name];
However the query your code builds does not bracket table name. Therefore, any table name which includes a space or contains nearly any character other than letters, digits, and underscore will result in a DELETE statement which triggers that error. If the table name matches a reserved word, that could also trigger the error. (Unfortunately it's difficult to predict exactly when reserved words will cause trouble.) It's safer to bracket all troublesome words in queries when they are used as field or table names. And for those which are troublesome because they are reserved words, you can alias them instead of bracketing.
But wherever practical, the safest practice is to rename all such objects: avoid reserved words; and use only letters, digits, and underscore.
Meanwhile, code defensively to cope with problem names. Revise the code to always bracket the table name.
sqlstr = "DELETE FROM [" & tbl.Name & "]"
I think you just need DELETE FROM without the *
Related
What is wrong with my logic below, is there any alternative to get calculatable column which will sum Balances for every unique KEY ?
Purpose: To create a summary column, calculation of Balances for each unique Key created ( Sort Code + Source Account) which will be used later to define whether acc type is Dr/Cr.
Code: below code should create summary column , but every time it triggers error depicted in attached screenshot.
***' Creating Sum of Balances based on Key , to differtiate Dr/Cr Account types
DoCmd.RunSQL "ALTER TABLE Output_File ADD Summing varchar(255)"
DoCmd.RunSQL "UPDATE Output_File SET Summing =" _
& "(SELECT SUM(Output_File.CURR_VALUE)" _
& " FROM Output_File GROUP BY Output_File.`UNIQUE KEYS`)"***
Error:
Error
In MS Access SQL, update queries must be updateable or not read-only. Any use of subqueries renders the query read-only. See Allen Browne's Why is my query read-only? One workaround is to use domain aggregates such as DSum available in Access SQL and VBA.
Ideally, too, consider using a saved query and avoid the need of building long SQL statements in VBA and have to worry about line breaks and concatenations. Below assumes UNIQUE KEYS is a number field. If text field, wrap in single quotes. If a date field, wrap in hashtags/pound symbols.
SQL (save as stored query)
UPDATE Output_File o
SET Summing = DSum("CURR_VALUE", "Output_File", "`UNIQUE KEYS` = " & o.`UNIQUE KEYS`)
VBA (reference above saved query)
DoCmd.OpenQuery "mySavedQuery" ' NO NEED TO CLOSE ACTION QUERIES
CurrentDb.Execute "mySavedQuery" ' ALTERNATIVE CALL
First of all, let me preface this with something I almost always say in my few posts so far, which is that I'm not an IT/tech person. I'm an accountant who likes to dabble a little bit in SQL and so forth but with very minimal knowledge of VBA, so I apologize in advance if this is a super-easy question or it's already been covered. But I was not able to find anything directly related to this specific error.
Trying to use MS Access to create a view from SQL that includes a Union and getting the following error: Run-time error '-2147217900 (800040e14)': Unions not allowed in a subquery. Code is as follows:
Sub Create_View()
Dim conn As ADODB.Connection
Set conn = CurrentProject.Connection
conn.Execute "CREATE VIEW Test_VW AS SELECT A.Unit as Unit, A.Spend as Spend, A.Date as Date, A.Type as Type FROM Table1 A UNION ALL SELECT B.Unit as Unit, B.Spend as Spend, B.Date as Date, B.Type as Type FROM Table2 B;"
Application.RefreshDatabaseWindow
End Sub
This is the code as it is right now, but I've also tried UNION instead of UNION ALL, SELECT * FROM both tables as opposed to the individual columns (both tables are only the 4 listed columns, which are also the same data type), and with the columns and tables unaliased.
Something I should point out that maybe could be the issue, but I wouldn't think it is is that the "Tables" in the code are actually views that I created in Access without VBA (as in just regular SQL). These now appear as "Queries" in the database. However, I did write the VBA with the initial SQL that's defining the views, and I returned the same error. So I don't think that's the issue.
EDIT: Also, I should point out that to test, I was able to create a view from the same VBA for the top level query without the UNION.
At any rate, I'm not sure where the subquery is in the SQL, so maybe it's a syntax error?
Any help would be greatly appreciated. Thanks!
That error message, "Unions not allowed in a subquery", is not very helpful in your situation.
Access supports 2 DDL operations related to queries: CREATE VIEW; and CREATE PROCEDURE.
CREATE VIEW can be used for only simple SELECT queries. CREATE PROCEDURE must be used for more complicated SELECT queries (such as UNION) and for "action" queries.
So you could avoid your current error by using CREATE PROCEDURE instead of CREATE VIEW. However you would then encounter a different error, "The SELECT statement includes a reserved word or an argument name that is misspelled or missing, or the punctuation is incorrect", due to unbracketed reserved words used as column aliases. You can drop the unneeded column aliases to avoid that error.
Here's an adaptation of your code which worked for me in Access 2010.
Dim strSql As String
strSql = "CREATE PROCEDURE Test_VW AS" & vbCrLf & _
"SELECT A.Unit, A.Spend, A.Date, A.Type FROM Table1 A" & vbCrLf & _
"UNION ALL SELECT B.Unit, B.Spend, B.Date, B.Type FROM Table2 B;"
CurrentProject.Connection.Execute strSql
QueryDefs can handle UNION. Alias field and table names are not needed.
Sub test()
Dim qdf As DAO.QueryDef
Set qdf = CurrentDb.CreateQueryDef("TestVW", "SELECT Unit, Spend, Date, Type FROM Table1 " & _
"UNION ALL SELECT Unit, Spend, Date, Type FROM Table2;"
Application.RefreshDatabaseWindow
End Sub
Strongly advise not to use reserved words like Date as names.
i am bulk inserting the worksheet to a temp table in SQL, after that i am calling a stored procedure to move data from temp to main table.
for insert i am using the below statement
s = "select * into [" & ThisWorkbook.Sheets("Master Control").Range("F2") & "].[" & Environ("username") & "] FROM [ABC$A13:IU5000] "
cn.Execute s
the problem is that, even after putting the range in the query, it is only picking upto the last column which have data, which is creating problem.
How can i make it to select exactly the range i specified?
I just posted my code to Transfer an Excel Range INTO a Database
This works for me.
SELECT * INTO [TagetTable] FROM [Excel 8.0;HDR=YES;DATABASE=C:\stackoverflow\test-stub.xlsx].[ABC$A13:IU5000]
This is your Query string:
select * into [F2].[best buy] FROM [ABC$A13:IU5000]
Is F2 the name of the database your are trying to query? Your missing the filepath in the FROM Clause
I have been reading up on escaping strings to avoid SQL Injection. I do understand that parameterized queries are the safest way to avoid Injection.
But i do have a question regarding Escaping as means of complimenting Parameterized queries.
Suppose the input field "Name" had the value O'Brian and was escaped using the below routine:
sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'"
So the value now looks like O''Brian. If this were to be inserted in the database using the Insert query, will the inserted value be actually O''BRIAN?
If that is the case, then in order to search the name column for the inserted value O''Brian, will i have to escape it to O''Brian before executing the Select query to match it with the value inserted in the DB?
Back again! So I am currently trying to programmatically have a table (Table2) update after a button is pressed. I would like for Table2 to resemble exactly another table (Table1). I'm going through this effort because Access does not allow double relationships and I have need to create one. I will therefore have two tables containing all the contact info.
I tried deleting Table2 and then creating another copy of Table1 and saving it as Table2. This would have worked is Microsoft Access didn’t throw an error because I am deleting a Table that has established relationships. So I then tried to programmatically delete and then create the appropriate relationships. However, this turns out to be a tedious exercise. A little too tedious for my taste.
My next thought is to create an append query that automatically looks for differences between the two tables and updates Table2 accordingly. The problem is that I have no idea how to structure the SQL statement for such an append query. Also is there an easier way to do this using VBA that I am missing? Thanks in advance for your help!
There is no need to go to all this trouble. You can have double relationships in MS Access. Simply add the table as many times as you need it to the relationship design window, you will get Table1, Table1_1, Table1_2 and so on, but they are all just aliases for Table1. You can now add self-joins and as many relationships as you need.
Like so:
*People*
PersonID *People_1*
ManagerID -- > PersonID
It sounds like you are able to append from Table1 to Table2 without running afoul of any relationship. If that is true, you can empty out Table2, then append all the rows from Table1.
Dim cn As Object
Set cn = CurrentProject.Connection
cn.Execute "DELETE FROM Table2"
If Table2 includes an autonumber field, reset its seed value.
cn.Execute "ALTER TABLE Table2" & vbCrLf & _
"ALTER COLUMN autonum_fld COUNTER(1, 1)"
Then do the append ...
cn.Execute _
"INSERT INTO Table2 (autonum_fld, text_field, long_int_field)" & vbCrLf & _
"SELECT autonum_fld, text_field, long_int_field" & vbCrLf & _
"FROM Table1;"
... or if the two table structures are identical, you don't even have to list the field names ...
cn.Execute "INSERT INTO Table2" & vbCrLf & _
"SELECT *" & vbCrLf & _
"FROM Table1;"
And finally ...
Set cn = Nothing
AFAICT, that could work. However, I don't understand the background details of your question, for example "Access does not allow double relationships". So I may be completely off the mark.