I created a new view in my SQL backend. I would like to view it in Access front end. When I open the linked table manager to add it to Access, it does not appear. I refreshed/closed/reopened. For clarity, the database where the new view exists is already linked and many of its tables/views do show in the linked table manager but not the new one I just made.
I opened the linked table manager, expanded all tables in the linked sql server, and my table does not show.
Verify that the new view has the same permissions as the views that already show up in Access. If permissions are different, modify the permissions on your view that is not showing up.
Run a small function:
Public Function LinkNewTable( _
ByVal TableName As String, _
ByVal SourceTableName As String) _
As Boolean
Const Master As String = "SomeCurrentlyLinkedTable"
Const Schema As String = "dbo"
Dim Database As DAO.Database
Dim Table As DAO.TableDef
Dim Connect As String
Dim Success As Boolean
Set Database = CurrentDb
Set Table = Database.TableDefs(Master)
Connect = Table.Connect
Table.Close
Set Table = Database.CreateTableDef(TableName)
Table.SourceTableName = Schema & "." & SourceTableName
Table.Connect = Connect
Database.TableDefs.Append Table
Database.TableDefs.Refresh
Success = Not CBool(Err.Number)
Set Table = Nothing
LinkNewTable = Success
End Function
Related
I'm trying to selectively import data from SQL Server tables to MS Access tables.
As far as I understand, import full tables can be done quite easy with DoCmd commands.
Unfortunately, the data I need are stored in large tables and I only need a parcel of them.
So far, I was able to import the data and store them at a recordset.
Now I want to create a table to store at MS Access, but VBA is complaining of type mismatch (run-time error 3421).
So far my code is like that - first part: connection to SQL Server database and data acquisition
Sub Test()
Dim Table As String, SQL As String, SQLTable As String
Dim server As String, Database As String, GetClientDB As String
'CaseID = 0
'SolutionID = 498232069
Table = "PrSale"
SQL = PrSale(SolutionID, CaseId)
SQLTable = TableSQL(Table, SolutionID, CaseId)
server = ServerID
Database = DatabaseID
GetClientDB = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=" + Database + ";Data Source=" + server
Set DBConnection = New ADODB.Connection
DBConnection.CursorLocation = adUseServer
DBConnection.ConnectionString = GetClientDB
DBConnection.Open
Dim myview As ADODB.Recordset
'myview.Open SQLTable, DBConnection, adOpenStatic
Set myview = DBConnection.Execute(SQLTable)
Second part - table creation and fields definition:
Call DeleteIfExists(Table)
'Cria a tabela na base de dados
Dim tdf As DAO.TableDef
Set tdf = CurrentDb.CreateTableDef(Table)
'Lê os campos da tabela original e replica na tabela local
For Each viewfld In myview.Fields
Dim fld As DAO.Field
Dim mytype As Integer
Select Case viewfld.Type
Case 200 'VarChar
mytype = dbText
Case 3 'integer
mytype = dbInteger
Case 202 'VarWChar
mytype = dbText
Case 5 'Double
mytype = dbDouble
Case 2 'smallint
mytype = dbInteger
Case Else
mytype = dbText
End Select
If Table = "PMPERIOD" Then
If viewfld.Name = "StartDate" Or viewfld.Name = "StopDate" Then
mytype = dbDate
End If
End If
If Table = "PMSELL" Then
If viewfld.Name = "GRPNUM" Then
mytype = dbText
End If
End If
Set fld = tdf.CreateField(viewfld.Name, mytype)
tdf.Fields.Append fld
Next
CurrentDb.TableDefs.Append tdf
Third part - table fulfillment using data stored at myview recordset:
If myview.EOF Then
GoTo Skip_
Else
End If
myview.MoveFirst
Do While Not myview.EOF
'Preenche as tabelas com os dados do Recordset
Dim myrecordset As DAO.Recordset
Set myrecordset = CurrentDb.OpenRecordset(Table)
myrecordset.AddNew
For Each viewfld In myview.Fields
myrecordset.Fields(viewfld.Name).Value = viewfld.Value
Dim j As Integer
j = 10
Next
myrecordset.Update
myview.MoveNext
Loop
Skip_:
End Sub
As far as I was able to debug, until the second part things seems to be right, although I was not able to verify the fields type. The table is created at the MS Access database with correct labels, but than it crashes with the error 3421! :(
How can I verify the type of the fields in tdf?
Do you have any clue what is going on?
Best regards
Just setup a table link to the sql server table.
then fire up the Access query builder.
Now create a blank new query, drop in the linked table to sql server.
Now in the ribbon, change the query to a make table query.
You Have this:
So, you can pick the field names, set critera, and when you run that query, it will create a local table.
So, you don't need code to filter
You don't need code to pick some columns
You don't need code to re-name the colum name(s) in the target table.
Just setup a linked table to sql server.
then drop in that linked table into the query builder.
On ribbon, choose "make table"
At this point, you can pick some, or all of the columns.
At this point you can type in criteria for some of the columns to limit the data.
run the query - you are done. There is no need to write code, or even mess with connection strings here.
SETUP:
I am using a SQL Server database linked to a MS Access file so I can use Access forms.
I am using unbound forms with custom queries since I am dealing with several tables (If there is a more efficient way I am all for it).
In SQL Server I have setup a database role with permissions for the table, I have double checked that I have allowed the role to update the table.
ISSUE:
Whenever I use my update query in Access using a QueryDef (shown below) it runs successfully, but does not actually update the table.
DETAILS:
I was having an issue with my insert query as well, however that was only because I had not updated the query with new columns I had added in the database. I also made sure that I did the same for the update query.
Additionally I know that the update query works since I am able to update the entry directly from SSMS.
Since this seemed similar to another access/sql-server question I had, Found Here. I made sure to try the solution for that one, refreshing the table link. However, it made no difference.
CODE:
Query:
UPDATE con_people
SET people_first_name = #firstName,
people_last_name = #lastName,
people_title = #title,
people_group = #group,
people_email = #email,
people_shift = #shift,
people_hiredate = #hireDate,
people_location = #location,
people_reportsTo = #reportsTo,
people_versionCount = people_versionCount + 1,
people_datelastupdated = #dateUpdated,
people_isActive = #isActive
WHERE people_employeeID = #empID;
QueryDef:
Public Function UpdatePeople(firstName As String, _
lastName As String, _
title As Integer, _
group As Integer, _
Email As Variant, _
isActive As Boolean, _
Shift As Integer, _
Location As Integer, _
HireDate As Variant, _
ReportsTo As Variant, _
employeeID As Integer)
OtherFunctions.Initialize
Dim QDF As DAO.QueryDef
If FindQuery("UpdatePeople") = True Then OtherFunctions.dbs.QueryDefs.Delete "UpdatePeople"
Set QDF = OtherFunctions.dbs.CreateQueryDef("UpdatePeople", SQLUpdatePeople)
QDF.Parameters("#firstName").Value = firstName
QDF.Parameters("#lastName").Value = lastName
QDF.Parameters("#title").Value = title
QDF.Parameters("#group").Value = group
QDF.Parameters("#email").Value = Email
QDF.Parameters("#isActive").Value = isActive
QDF.Parameters("#empID").Value = employeeID
QDF.Parameters("#shift").Value = Shift
QDF.Parameters("#hireDate").Value = HireDate
QDF.Parameters("#location").Value = Location
QDF.Parameters("#reportsTo").Value = ReportsTo
QDF.Parameters("#dateUpdated").Value = ConvertTimeUnix.ConvertDateToUnix(Now())
QDF.Execute
If FindQuery("UpdatePeople") = True Then OtherFunctions.dbs.QueryDefs.Delete "UpdatePeople"
End Function
Any help is appreciated,
Thanks.
Thanks to a comment by #Andre I was able to find the source of the issue.
I was using the wrong data type when I was updating the entry. The SQL-Server was expecting an INT (for a foreign key) when I was providing it a boolean (SQL-Server BIT).
Details About the solution:
Links provided by Andre: Error Object - Data Access Object and Determine real cause of ODBC failure (error 3146) with ms-access?.
For more information on the DAO.Error object please reference those.
Here is an example of how it is used:
Dim myerror As DAO.Error
For Each myerror In DBEngine.Errors
With myerror
If .Number <> 3146 Then 'prevents the system from returning the basic error.
MsgBox "Error #:" & .Number & ", Description: " & .Description & ", Source: " & .Source
End If
End With
Next
Once I ran it, this was returned, allowing me to find the root cause:
Error #:547,
Description: [Microsoft][ODBC SQL Server Driver][SQL Server]The UPDATE statement conflicted with the FOREIGN KEY constraint "FK_people_isActive". The conflict occurred in database "continuousimprovement", table "dbo.con_isactive", column 'isActive_id'.,
Source: ODBC.QueryDef
Again, Thank you Andre.
Right now I'm downloading data from a database using ADODB to an Excel table. However I want users to be able to refresh the table so it's updated from my database.
I've been experimenting with creating a new table from an external source and arrived to this code:
Public Sub CreateLiveTable(sql As String, Location As Range, TableName As String)
With Location.Parent.ListObjects.Add(SourceType:=xlSrcExternal, Source:="OLEDB; " & DB_CONNECTION, Destination:=Location).QueryTable
.CommandType = xlCmdSql
.CommandText = sql
.BackgroundQuery = True
.ListObject.DisplayName = "asdfas"
.SourceConnectionFile = "C:\Users\lisandro.h.vaccaro\Documents\My Data Sources\172.19.179.43 Forecasting CostRates.odc"
.Refresh BackgroundQuery:=True
End With
End Sub
However I haven't been able to connect my existing table to SQL Server. I can't just delete and create it again as there are a lot of formulas and named ranges pointing to it that would be broken if I deleted it.
How can I connect my existing table to my database?
I am beginner to the VBA. Please help.
I have a database named as "Master" saved on shared network folder and it has table named as "logs" .
I have few users who have different data base with the table “logs” and this table structure is like the same as in the table “log” in the database “Master”.
Those users makes entries to their database table “logs” everyday. I want that in the “Master” database, I will create a table named as “UserDb” which will keep address path of all the users database files and I will create a form with the button “Sync”.
I need that once I click on the “Sync” button then it should read path of the user data base from the table “UserDb” and insert all the today’s date entries from all the user’s data base table “logs” to the “Master” database table “logs”.
In the table “Logs” columns names are UserName, Application, TeamName, StartTime, StopTime, LoginDate.
Here's something that you can start with:
Function ConToDataBase(DBPath As String) As Variant
Dim Con As ADODB.Connection
Dim Rs As ADODB.Recordset
Dim SQL As String
SQL = "SELECT * FROM Logs"
Set Con = New ADODB.Connection
With Con
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data source=" & DBPath & ";"
.Open
End With
Set Rs = New ADODB.Recordset
Rs.Open SQL, Con
Dim Var As Variant
Var = Rs.GetRows
ConToDataBase = Var
Set Rs = Nothing
Con.Close
End Function
Make sure to add the reference Microsoft ActiveX Objects 2.8 from Tools > References so that you can ADODB objects.
The function will return a variant containing the logs table. You can take it from there.
I'm sure my question has been answered many times on the internet, but I couldn't find exactly what I was looking for.
I'm working on VB.NET and my database is a SQL Server Compact .SDF file. The following is my method of opening the database.
Private Shared Sub OpenDatabase(ByVal tablename As String)
If _DBLoaded Then Return
'// open database connection
conn = New SqlCeConnection("Data Source = giadatabase.sdf")
conn.Open()
'// create command for making extracting data
cmd = conn.CreateCommand
cmd.CommandText = "SELECT * FROM [" & tablename & "]"
'// setup database adapter
da = New SqlCeDataAdapter(cmd)
'// create command for inserting/updating database
cb = New SqlCeCommandBuilder(da)
'// load dataset
ds = New DataSet()
da.Fill(ds)
'// get the relevant table
dt = ds.Tables(0)
_DBLoaded = True
End Sub
I run this sub when my application starts. I believe that database needs to be opened just once. Constantly reopening of database will cause performance problems to my application (correct me if I'm wrong).
For loading data in my list object I use the following:
Public Shared Function GetList() As List(Of DatabaseListObject)
OpenDatabase("TestTable")
'// Make a list of items in database
Dim ret As New List(Of DatabaseListObject)
For Each dRow As DataRow In dt.Rows
ret.Add(New DatabaseListObject(dRow("ID"), dRow("LongName"), dRow("ShortName")))
Next
Return ret
End Function
So my GetList function ensures database is already open, and database is always opened once a lifetime of my application. My list object is filled with data from the above function.
This is how I make changes to my database:
Public Shared Function AddItem(LongName As String, ShortName As String) As DatabaseListObject
'// Make changes
Dim row = dt.NewRow()
row("LongName") = TimeOfDay.ToString
row("ShortName") = ShortName
dt.Rows.Add(row)
da.Update(ds, dt.TableName)
Dim newcmd = conn.CreateCommand
newcmd.CommandText = "SELECT ##IDENTITY;"
Dim newID As Integer = newcmd.ExecuteScalar()
Dim item As New DatabaseListObject(newID, LongName, ShortName)
Return item
End Function
Now I assume database is correctly updated from the above code. The ID column in my table is the autonumber. Problem occurs when I call the GetList function after adding a row. System throws error that the newly added row's ID column is NULL. Whereas it should be automatically added number. When I restart the application, i.e. the database is opened from scratch, then the GetList shows the autonumber properly.
Obviously the table's ID column is not getting filled-in with the autonumber when I'm adding a new row. So I need suggestions here. Should I always open the database from scratch whenever I call the GetList (which will be called frequently in my app). If not the entire database then which codes should be called at least to properly refresh the table without causing much performance problems to the application.
SELECT ##IDENTITY will only Work on the same open Connection object, and the DataAdapter opens and Closes its own connection, you must use plain ADO.NET (cmd.ExecuteNonQuery) or implemet extra code as described here: http://blogs.msdn.com/b/bethmassi/archive/2009/09/15/inserting-master-detail-data-into-a-sql-server-compact-edition-database.aspx