I need to export; Multiple queries to different tables of ms access database from ms sql.
I know it is possible by taking each query and export it to a single table and repeating the same for different queries.
What I want to know is... can it be done in one stretch?
suppose there are three queries and each query output need to be in different tables ... in that case is it possible to do with a single export?
You can save the individual exports as SSIS packages, then combine them into a single package.
The exports might even be able to run in parallel.
I'm not sure what you mean. You could put all the SQL statements into one command batch rather than executing each one separately, e.g:
insert into Table1 select ...
insert into Table2 select ...
insert into Table3 select ...
Are these passthrough queries or Jet (Access) queries? If they are Jet queries, you should create make table queries and run them as a batch through VBA. The make table queries themselves can be constructed easily enough in VBA, if you prefer. Here is an example that gets the connect string from a linked SQL Server table, but you can fill in your own connection string, it should have the same format as the connect property of a linked table.
Dim db As Database
Dim strSQL As String
Dim strConnect As String
Set db = CurrentDb
strConnect = db.TableDefs("dbo_test").Connect
strSQL = "INSERT INTO NewAccessTable (ID, Descr) " _
& "SELECT ID, Descr FROM [" & strConnect & "].[test] "
db.Execute strSQL, dbFailOnError
Debug.Print db.RecordsAffected
Related
I have an access database for which I need to run a query that is available in postgres DBs, I was wondering if there is a possible that this can be accomplished:
Insert into Table (Col1,Col2...) values(Val1,Val2,...) returning * (ore even just an id defining that specific set of data that was just inserted)?
I'm using c# to communicate to the DB.Anything would help, thank you.
The code I basically use is the following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.OleDb;
namespace Testquery1
{
class Program
{
static void Main(string[] args)
{
string query = "INSERT INTO Table ( Val1, Val2, Val3 ) values(14,2,1)";
Test1 queryselect = new Test1();
queryselect.dataconnection(query);
}
}
class Test1
{
public OleDbConnection connection = new OleDbConnection();
string path = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string fileloc = #"DataBase.accdb";
string provider = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=";
public void dataconnection(string query)
{
connection.ConnectionString = provider + path + fileloc;
Console.WriteLine(connection.ConnectionString);
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = query;
command.ExecuteNonQuery();
connection.Close();
}
}
}
Unfortunately with .net you cannot do a append or make table query between two different connections.
However, you CAN in Access.
If you have a working PostgreSQL SQL query that returns records, then you can simple save that query in Access (as a pass-through query.
You can now use that query in Access and send it to a NEW local table in Access. (Access supports this concept, .net does not)
You can thus either append or “make table” of that data.
And more interesting is you can even append between different connections in Access. So you can append from a PostgreSQL table to say a MySQL, or Oracle or FoxPro table inside of access.
Again, you can’t do this in .net.
So, assume a working raw SQL (PostgreSQL format) query that works in PostgreSQL? Take that SAME working query and save it in Access as a pass-through query.
Then in Access you can append to a table in Access (assuming same table structure with:
VBA (Access code)
Dim strSQL as string
strSQL = "INSERT INTO LocalTable SELECT * from QryPassR"
Currentdb.Execute strSQL
And if you want to MAKE a new table in Access with the SAME structure, so make table (not append), you can go:
Dim strSQL as string
strSQL = " SELECT * INTO LocalTable FROM qryPassR"
Currentdb.Execute strSQL
You can also in VBA code change the PostgreSQL to include criteria for that select.
(air code - does not take into account SQL injection issue).
Dim strCity as string.
strCity = inputbox("What city to pull from PostGres?")
dim strSQL as string
strSQL = "select * from tbleHotels where City = '" = strCity & "'"
With currentdb.QueryDefs("QryPassR"
.SQL = strSQL
End with
strSQL = "INSERT INTO LocalTable SELECT * from QryPassR"
Currentdb.Execute strSQL
‘ above will copy all the records from PostGreSQL of city = Edmonton into the Access table (called local table in this example).
And as noted, you not limited to “LocalTable” being a access table, it could be a FoxPro table, MySQL, SQL server etc. So you not limited to JUST using Access tables in the above with your given SQL. So any linked table you have in Access can be used – including ones that point to other database systems.
If you must use .net, then you have to:
Connect to first database.
Execute query to pull and fill a datatable.
Connect to second database.
Create (open) a data table based on second database.
Loop (iterate) each row from first connection datatable and copy the row into the second datatable (based on 2nd connection).
You have to do a row by row copy. (but there is ImportRow method of the .net datatable, so you don’t have to loop by a column by column copy.
(but you have to loop row by row).
In Access this looping is not required and in fact you can use SQL commands that operate on both tables, including as per above the make table and append, and you can even do relation joins between such tables - even those based on different connections (data sources).
Edit
Based on comments, it looks like the simple question is:
After I insert a row into Access, how can I get the last ID (identity) of that insert?
The follow vb.net code will do this:
Imports System.Data.OleDb
Dim MyCon As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Test2\test44.accdb")
MyCon.Open()
Dim strSQL As String = "insert into tblHotels2 (City) VAlues('Edmonton')"
Dim cmd As New OleDb.OleDbCommand(strSQL, MyCon)
Dim r As Integer
cmd.ExecuteNonQuery()
cmd.CommandText = "select ##IDENTITY"
r = cmd.ExecuteScalar
Debug.Print(r)
Output = last PK id (autonumber)
I have an Access 2016 database that started off as a classic access MDB. Along the way, it was converted to a .accdb, and linked to a backend SQL Server. All of the tables used were converted to linked tables.
There is code that performs code something like this:
sql = "insert into [TableA]..."
CurrentDB.Execute sql
DoCmd.OpenReport(...)
What I'm finding is that intermittently the Insert into the backend SQL doesn't seem to complete before the OpenReport command selects the data from the same table.
Would it be reasonable to solve this by using. Assuming my issue is that the data is not committed to the SQL table in time for the Report Execution to see it, would the following code insure this?
sql = "insert into [TableA]..."
CurrentProject.Connection.BeginTrans
CurrentProject.Connection.Execute sql
CurrentProject.Connection.CommitTrans
DoCmd.OpenReport(...)
If you're using ADO, you can use the RecordsAffected output parameter to determine if a record got inserted.
You can use the following:
sql = "insert into [TableA]..."
Dim recordsAffected As Long
CurrentProject.Connection.Execute sql, recordsAffected
If recordsAffected <> 0 Then
DoCmd.OpenReport(...)
Else
'Nothing got inserted
End If
Or, if you don't like the extra variable, you can consider using a helper function:
Public Function ADOExecute(Query As String) As Long
CurrentProject.Connection.Execute Query, ADOExecute
End Function
sql = "insert into [TableA]..."
If ADOExecute(sql) <> 0 Then
DoCmd.OpenReport(...)
Else
'Nothing got inserted
End If
Note that I highly recommend using a connection to your SQL Server instead of CurrentProject.Connection, which is an ADO connection to Access.
Yesterday I had to run a query in MS Access 2010. One field I needed was not in the tables I usually use (already linked through the ODBC Database) and I didn't know what table it was a part (there are several hundred tables in the Machine Data Sources). Aside from manually importing all the tables and looking in each one for this field is there a way I can search for a field without knowing the table either 1. without importing any tables from the ODBC Databases, or if not 2. importing a handful of possible tables and searching once those tables have been linked into my active MS Access 2010 session?
Install Access Dependency Checker, link all tables and search for column name (enable checkbox for search in linked tables)
You could do this in a Function using ADO schema's.
Try this function in a standard module:
Function ListTablesContainingField(SelectFieldName) As String
Dim cn As New ADODB.Connection
Dim rs As ADODB.Recordset
Dim strTempList As String
Set cn = CurrentProject.Connection
'Get names of all tables that have a column called <SelectFieldName>
Set rs = cn.OpenSchema(adSchemaColumns, _
Array(Empty, Empty, Empty, SelectFieldName))
'List the tables that have been selected
While Not rs.EOF
'Exclude MS system tables
If Left(rs!Table_Name, 4) <> "MSys" Then
strTempList = strTempList & "," & rs!Table_Name
End If
rs.MoveNext
Wend
ListTablesContainingField = Mid(strTempList, 2)
rs.Close
Set cn = Nothing
End Function
I have more than 5000 records in my tblT1
I execute below queries in access 2010 with linked tables on MS Sql server database for my report.
Pass Through Query:
PTQuery1 = "SELECT tblT1.* From tblT1;"
But I need to execute above Pass Through query based on criteria (tempQuotationNo).
My friend suggested me below query:
A Select Query based on Pass Through Query:
Query1 = "SELECT PTQuery1.* FROM PTQuery1 WHERE PTQuery1.QuotationNo = tempQuotationNO;"
tempQuotationNO can be a variable or a field in a form.
As I know both queries load all records of tblT1 to client (second query filter result of PTQuery1 after loading).
Both work fine but I need to reduce the time of loading records to my client.
Is there anybody to suggest a solution for me?
The aim is (first) to filter the records on SQL Server then load the result to FE, based on a field in a form or user defined variable to reduce the time of loading data from SQL Server to client.
Simply modify the PT query like this:
Dim strSQL As String
strSQL = "select * from table where QuotationNo = " & lngQuoteNum
CurrentDb.QueryDefs("MyPass").SQL = strSQL
At this point you can launch your form etc. it will use this NEW sql for the pass though. The above assumes longQuoteNum is a VBA var. If quote number is text, then you need this:
strSQL = "select * from table where QuotationNo = '" & lngQuoteNum & "'"
We need to find a way to programatically ****link all the tables in a SQL Server database to an access db. We will be invoking this access database from a program that uses .net/SQL Server 2008.
While invoking the application we would like to add the linked tables so that the users can just run the reports/modules from access without having to worry about linking the tables. Is there a way we can do this?
Here are some notes.
Dim sLocalName As String
Dim tdf As TableDef
Dim rs As dao.Recordset
''This is a basic connection string, you may need to consider password and so forth
cn = "ODBC;DSN=TheDSNName;Trusted_Connection=Yes;APP=Microsoft Office 2010;DATABASE=TheDatabaseName;"
''All fields from tables
strSQL = "SELECT TABLE_CATALOG, " _
& "TABLE_SCHEMA, " _
& "TABLE_NAME, " _
& "TABLE_TYPE " _
& "FROM [" & cn & "].INFORMATION_SCHEMA.tables " _
& "WHERE TABLE_TYPE = 'BASE TABLE'"
Set rs = CurrentDb.OpenRecordset(strSQL)
Do While Not rs.EOF
sLocalName = rs!TABLE_SCHEMA & "_" & rs!TABLE_NAME
With CurrentDb
If DLookup("Name", "MSysObjects", "Name='" & sLocalName & "'") <> vbNullString Then
If .TableDefs(sLocalName).Connect <> cn Then
.TableDefs(sLocalName).Connect = cn
.TableDefs(sLocalName).RefreshLink
End If
Else
''If the table does not have a unique index, you will neded to create one
''if you wish to update.
Set tdf = .CreateTableDef(sLocalName)
tdf.Connect = cn
tdf.SourceTableName = rs!TABLE_NAME
.TableDefs.Append tdf
.TableDefs.Refresh
''This will produce a message box if the table does not have a unique index
''DoCmd.TransferDatabase acLink, "ODBC Database", cn, acTable, rs!TABLE_NAME, sLocalName
End If
End With
rs.MoveNext
Loop
You'll need an ODBC connection to the SQL database. Once this connection ready, you can use it for all tables that you want to link:
DoCmd.TransferDatabase acLink, _
"ODBC Database", _
myODBCconnection, _
myDatabaseName, _
acTable, _
myTableName
I guess you can declare your ODBC connector "on the fly", as proposed here for example.
To enumerate your tables, you have the following options:
Enumerate them in the code: one transferDatabase line per table
Save the table names in a local table, and browse the table
Save the table names in a file (text, xml) anywhere on the network and browse the file
Access the system table on the server that holds the table list, and browse the table
Use the ADOX object to browse all tables in your database server: be carefull not to include system tables. This solution might be also quite confusing because you'll have to first open an ADODB connection to your database, and you'll then use an ODBC connection to open the tables
In all cases, this procedure shall be launched with the autoexec macro, meaning that links will be created\updated each time the user opens the mdb client.
You would use ADOX to do the actual linking.
As far as enumerating the tables in a database you are connected to, you could do something as simple as running this query against your SQL Server, but there are a lot of ways to skin that cat:
SELECT * FROM INFORMATION_SCHEMA.TABLES
You can achieve the equivalent by using a Linked Server in SQL Server that points to the Access db. This will give you access to all the tables in the Access db so that you can reference them like:
Select ..
From [LinkedServerName]...[AccessTableName]
Btw, a linked server may be overkill for what you want. Look into the OPENROWSET function which effectively let's you pass a connection string.
EDIT: I originally read the question to literally mean "link tables in SQL Server to access" which I translated to mean from SQL to Access. So, given that, my solution would apply. However, if the desire is to go from Access to SQL, then that is different and other solutions presented would be more appropriate.