I am having trouble writing a VBA macro within Microsoft Access. What I am trying to do is use SQL to create an output table, but I want to write to multiple columns simultaneously.
This gets me all the values I need for one column:
Docmd.RunSQL “INSERT INTO Output (TargetCol1) SELECT [Field1] FROM [Table1] WHERE [Criteria1] = ‘Value’ GROUP BY Field1”
When I try to run this multiple times to get the values I need for other columns. INSERT INTO writes the data as new records, so I end up with blank spaces, like this:
Field1----Field2
Value----<Null>
Value----<Null>
Value----<Null>
<Null>----Value
<Null>----Value
What I want is:
Field1----Field2
Value---- Value
Value---- Value
Value----<Null>
I tried to create variables and create kind of a nested statement but I receive a ‘Compile error, object required’ on my first line when I try to run what I have written:
Set x = Docmd.RunSQL “INSERT INTO Output (TargetCol1) SELECT [Field1] FROM [Table1] WHERE [Criteria1] = ‘Value’ GROUP BY Field1”
Set y = Docmd.RunSQL “INSERT INTO Output (TargetCol2) SELECT [Field2] FROM [Table1] WHERE [Criteria2] = ‘Value’ GROUP BY Field2”
Docmd.runsql “INSERT INTO Output (TargetCol1, TargetCol2) Values (x,y)”
Why not:
INSERT INTO Output (TargetCol1,TargetCol2) SELECT [Field1,Field2] FROM [Table1] [Criteria1] = 'Value'"
Set is used for objects, and you do not have one in Set x = Docmd.RunSQL. Order by is irrelevant for a table.
The easiest way to set up queries is using the query design window. it will guide you through creating the query and you can then switch to SQL view to get SQL.
I suggest you do not use RunSQL : What's the difference between DoCmd.SetWarnings and CurrentDB.Execute
Related
I am trying to run the following in Access / VBA
DoCmd.RunSQL SQLStatement:="INSERT INTO [Assets All] (RoomID) VALUES (SELECT RoomID from findNewRoomID )"
findNewRoomID is a Query and is part of the Form's Record Source, it only returns one result.
The error message says there is a syntax error in the subquery.
I have also tried with the SQL code of findNewRoomID but it didn't work either.
When using the VALUES clause of an INSERT INTO statement, a comma-delimited list of values should be supplied, and this can only be used to insert a single record into the target table.
If instead you wish to pass append the results of a SELECT query which may return multiple records, you would simply use:
DoCmd.RunSQL "INSERT INTO [Assets All] (RoomID) SELECT RoomID from findNewRoomID"
I have a recordset and a table, both in exactly the same format. What is the syntax to dump everything in the recordset to the table? This seems to be a very simple procedure but somehow I can't find any useful information online.
Edit1: to clarify, the recordset is obtained from Table A, now I want to dump it into Table B (which is empty). Table A and B have exactly the same format.
Edit2: I am working in Access.
here is the code I used to open the recordset:
Set Table_B_rs = CurrentDb.OpenRecordset("Table_B")
I didn't make any changes to the recordset.
Thanks for the help!
You don't do this with recordsets, but with SQL by running an INSERT INTO query.
CurrentDb.Execute "INSERT INTO TableB SELECT * FROM TableA " & _
"WHERE <same conditions you used to open the recordset>"
If there is no condition, it's simply
CurrentDb.Execute "INSERT INTO Table_B SELECT * FROM Table_A"
Is there a way to be prompted before you a run an SQL query in Access, to enter in the table name that you wish to query? For example, lets say the columns will always stay constant. The columns could be called "Fruit" and "Date." But, the table name could change depending on the batch number. Ie. table name could be "BatchNO_1" or "BatchNO_2" or "BatchNO_3" etc. So Lets say i have an SQL like:
select Fruit, Date from BatchNO_1 where Fruit = "Apples"
Is there a way that I can be prompted to enter in the table name and have the SQL use the table name i enter to perform the query?
No. The table name cannot be passed as parameter to a query. You will have to construct the query yourself.
Dim tableName as String, sql As String
tableName = InputBox("Please enter the table name")
If tableName <> "" Then
sql = "SELECT Fruit, Date FROM [" & tableName & "] WHERE Fruit = 'Apples'"
'TODO: execute the query here
End If
For instance, you could change the query text of an existing query like this:
CurrentDb.QueryDefs("myQuery").SQL = sql
Or you could execute the query like this
Dim db As DAO.Database, rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset(sql)
Do Until rs.EOF
Debug.Print rs!Fruit & " " & rs!Date
rs.MoveNext
Loop
rs.Close: Set rs = Nothing
db.Close: set db = Nothing
By putting the batch number in the table name instead of as a column, you are encoding data in the schema. This is not best practice, so in my opinion, the correct answer is to change your database design.
Make a single Batch table with all the columns from your current BatchNo tables, but add a column named BatchNo as part of the primary key. Load all the data from your BatchNo tables into this one, and then delete those tables. Then your query will straightforwardly look like this:
SELECT Fruit, Date
FROM Batch
WHERE
Fruit = "Apples"
AND BatchNo = [Enter Batch No];
Don't put data in table names. That is not the way databases are supposed to be made.
Just to explain a little bit, the reason that your current design violates best practice is due to exactly the problem you are facing now--the shenanigans and weird things you have to do to work with such a design and try to perform operations in a reasonable, data-driven, way.
By having the user enter the table name, you also create the danger of SQL injection if you aren't also careful to compare the user-provided table name to a whitelist of allowed table names. While this may not be such a big deal in Access, it is still heading down the wrong path and is training for something else besides professional database work. If you would ever like to grow your career, it would be regrettable to first have to unlearn a bunch of stuff before you could even start with a "clean slate" to learn the right way to do things.
In building a recordset for inserting records into our SQL Server database, there is a precedent to do a SELECT in that the WHERE clause would return no rows. This blank recordset will then be filled before committed back to the database. The point of this is to get the column definitions for the client.
Example:
SELECT * From TableA where key_column = 0
While doing a trace on the database, I have noticed that this methods executes two statements:
One that gets the column metadata...
SET FMTONLY ON SELECT * From TableA where key_column = 0 SET FMTONLY OFF
... and then original select we intended.
Considering that we only want the metadata, is there a way to only run the first statement when constructing the Recordset from within VB6?
(I am aware that using an INSERT statement instead of a recordset would be the most efficient.)
I have a table with several columns that allow NULLs. How would I go about writing a SQL Query that will allow me to skip that column in an update if the value is "empty". Should I use a boolean flag letting the query know to update that value? I do something similar in a SELECT like this
SELECT * FROM table WHERE (#boolFlag = 1 OR col1 = #col1Val)
But trying to do that for an update has proven to be an exercise in futility. Ideally I'd be able to say skip this value if true, otherwise update over my 20ish columns. Right now I can't pass in DBNull.Value, so instead I'm being forced to insert "" which is converted into whitespace (for instance, my nvarchar(50) has 50 spaces).
I'm using a SQL Server DB/Table and a DataSet in VB.NET, constructing my queries in VS2k8 if that matters.
You could do:
update MyTable
set MyColumn = case when #MyColumnValue = '' then null else #MyColumnValue end
A short form of the above would be:
update MyTable
set MyColumn = case when #MyColumnValue <> '' then #MyColumnValue end