I am working with an excel file that holds macros. In these macros, a connection to a SQL Server database is created and data is loaded from the sheets in the Excel file into the tables in the database.
This file is used by multiple users.
Currently, we have an issue where writing data into the db works for some users while other users get the following Run-time error:
[Microsoft][OBDS SQL Server Driver][SQL Server]Invalid object name
"TableName".
The connection to SQL Server in the macro is specified as following:
'Setting the connection
Set oConn = New ADODB.Connection
Set Rs = New ADODB.Recordset
oConn.ConnectionString = "driver={SQL server};" & _
"server=" & ServerName & ";authenticateduser=TRUE;database=" & DatabaseName
oConn.Open
The table definitely exists in the db and as mentioned, other users don't receive that error message.
What could be the issue that makes the connection work for some users while others get the error?
Related
I have a MS Access application that has been in use for at least 10 years. Recently I moved my work to a new development machine with Office 365 and SQL Server Express 2019 installed. The machine OS is Windows 10 Pro. In my old machine my application would run just fine. There is a query using a stored procedure that retrieves a piece of data from a table in the SQL Server backend. I call this procedure using a ADODB recordset based on the stored procedure output. All my calls use a connection string based on an ODBC DNS. This connection string works fine on the new machine when relinking tables to the SQL Server backend, but when I use it in the ADODB connection I get an error "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified". On the old Windows 7 development machine this ran fine. It also runs on the client's machines which are Windows 10 and Office 365. The code that raises the error follows. The error occurs at the open connection line. The connection string is: ODBC;DSN=VROM;Trusted_Connection=Yes;APP=2019 Microsoft Office system;DATABASE=VROM1.
Set con = New ADODB.Connection
con.ConnectionString = DLookup("Link", "tblLinkData", "Use = True")
con.Open
Set rs = New ADODB.Recordset
My question "Is there a setting in SQL Server that could be causing this error?". As far as I can tell both systems are set up the same, but there is obviously something different between the two. Is there another reason this could be working on one system and not another?
Hum, where to start?
Ok, first up, if you using the ODBC panel to create a ODBC connection, then you NEVER were actually using a ADO connection in that DSN config = ODBC!!!!
That means you been feeing ADO a ODBC connection string. you can do this, but at least lets be aware of what is going on.
Next up:
Are you running the SQL browser service? You MUST do that now!. Don't know if you installed a later version of SQL SERVER, but a few versions ago you will find now that you MUST run the browser service.
This one:
The reason of course is that you can (may) have multiple instances of sql server running, and the default instance (SQLEXPRESS) now MUST BE specified. As noted older instances did NOT have this requirement. And to "resolve" the multiple instances, you now must run the SQL browser service. As noted, this was NOT a requirement in the past - it is now. That browser service is what connects the IP/server name to the instance, and you now in most cases have to run this.
There are exceptions, but you don't want much pain.
Next up:
For a VERY long time, it is recommended for Access linked tables you use a DSN-less connection. that way then at deployment time to all workstations, you don't need to setup a DSN on each workstation.
And if you link Access tables using a FILE dsn (not system or user), then upon the table link process, access BY DEFAULT converts all table links to DSN-less. That means once you linked, then you could even delete the DSN - you do NOT need it anymore.
Again: this ONLY holds true if and when you create a FILE dsn, and use that to link the tables. So, that takes care of the DSN-less linked tables.
Note that if you were to modify the DSN, you would have to link, since I just told you by default access creates + uses dsn-less links (assuming you used a FILE dsn to link).
now, you CAN of course use that SAME dsn for ADO, but that means you are feeding ADO a ODBC driver connection!!!
If you want to create a real ADO connection, then you would/could/should say use this:
Dim strCon As String
strCon = "Provider=SQLOLEDB;;Initial Catalog=TEST4; " & _
"Data Source =.\SQLEXPRESS;Trusted_Connection=yes"
Dim conn As New ADODB.Connection
conn.ConnectionString = strCon
conn.Open
Dim rst As New ADODB.Recordset
rst.Open "SELECT * from tblHotels", conn
Do While rst.EOF = False
Debug.Print rst!HotelName
rst.MoveNext
Loop
Now now how I used a "." for localhost. That could be replaced with (local), or in fact the computer (server) name say like this:
strCon = "Provider=SQLOLEDB;;Initial Catalog=TEST4; " & _
"Data Source =ALBERTKALLAL-PC\SQLEXPRESS;Trusted_Connection=yes"
Next up, make sure you enabled the TC/IP connections.
here:
However, since your case all along you actually been using ODBC driver with ADO, then I would not rock the boat.
But, check your settings as per above.
Since linked tables, and quite much everything else is DAO + odbc?
then I would probably not introduce ADO into that application for JUST calling + using sql server store procedures.
I as a general rule would say use this;
with currentdb.tabledefs("qryPT")
.sql = "exec MyProcName"
.execute
end with
Or, if it is to return data, then I would use this:
dim rst as DAO.RecordSet
with currentdb.tabledefs("qryPT")
.sql = "exec MyProcName"
set rst = .OpenRecordSet()
end with
So, I am hard pressed to find a reason to use ADO. Now of course since you been using ADO, then I guess I would continue to do so.
but, check the browser settings. And if the tables were linked using a FILE dsn, then they are dsn-less.
You could try feeding the ADO connection a existing connection from a existing linked table.
eg:
strCon = CurrentDb.TableDefs("dbo_tblHotels").Connect
strCon = Mid(strCon, 6)
Dim conn As New ADODB.Connection
conn.ConnectionString = strCon
conn.Open
Skipping the first 6 chars skips this part:
ODBC;DRIVER=SQL Server;SERVER=ALBERTKALLAL-PC\SQLEXPRESS;
UID=AlbertKallal;Trusted_Connection=Yes;APP=Microsoft Office 2010;
DATABASE=Test4;Network=DBMSLPCNM
So once again we are feeding ADO ODBC connection string.
(of course above connection string is one line).
Thank you for your help as always!
I have built an Access database that we intend to distribute to ~100 end users. I am currently running a pilot program for 5 users. I have migrated the tables to SQL 2014 Server but currently the back end of the pilot program is in a shared network folder (location unknown to them). I distributed the Access front end (accde file type) by saving the file on that shared Network and instructing the end users to save a copy to their desktop. The pilot is working fine, if not a little slow.
The issue that I am having is this:
I am able to set up an ODBC Connection on my machine and am able to connect to the SQL Server backend through that connection. However, I am not sure how to get my end users Access to the tables on the server. Do I need to create a user name for each user on the server and give them read and write access? Do I also need to create an ODBC connection on each machine that we plan to install the Front End on? I would prefer to not have to create an ODBC connection on each machine, is it possible to work around this? Thank you!
Access Version: 2013
SQL: 2014
Working on SSMS 2014
-Charlie
A few things:
When you create a linked table, simply use the ribbon import and link – and then ODBC database. Just choose a file DSN. The reason for this is that access by DEFAULT will use a DSN-less connection. In simple terms, this means when you link the tables, then you can distribute your applcatation to each workstation and there no need to setup a SYSTEM/Machine DSN.
So just keep in mind that use the default file DSN – once Access creates the link to SQL server, then such links are DSN-less, and you don’t need any setup on each workstation.
As for creating users on SQL server? Well, you likely don’t need to unless you want some kind of special security for each user. If you using SQL logon, then MAKE sure that during the above linking process you “check” the save password option. Once again, since by default the linked tables are DSN-less, then every user will in fact be using the one and same SQL User/password and thus this will be transparent to each user (they will not have to log on).
If you using windows authentication for SQL logons, then security is setup with the windows system and not SQL server. In this case then each users windows logon will be used to control (permit) use of the SQL server. If you not using a domain controller, then you be using SQL logons, and likely just the one logon that you are using will suffice. Often even in a corporate environment because I don’t want to call up the IT admin folks for each logon and permissions to SQL server, then I still OFTEN choose SQL logons. Thus “once” the IT admin folks give me enough rights to the SQL server, then I am free to create my own logons, or just use the “one same” logon for everyone and thus don’t have to waste time bothering the IT folks.
A few additional final points:
Ignore suggesting to use all kinds of ADO and VBA code and connection strings etc. – they are not required. In fact in most cases you want to AVOID ADO code in your application. And oleDB is being depreciated for SQL server (which ADO tends to rely on).
You STILL as a matter of good deployment want to place the front end program you have on each workstation. Just like you install word on each workstation, or your accounting packages, now that YOU ARE developing software, then you install your software on each workstation like the IT industry done for the last 30 years. You can certainly share data on a shared folder, but you install the actual application (word, Excel, or in this case YOUR applcatation on EACH workstation. And you should compile the accDB to an accDE before any deployment.
So you don’t really need any special code on start up to “connect” or “link” to SQL server if your deployment to such users is on your same network. If you are developer or consultant “offsite”, then you likely need to add some code on start up to re-link to THEIR sql server that no doubt would be different than the one your developing with offsite. So some ability to re-link to a “different” SQL server then the one your are developing with would be required if you not able to develop on site, or that the SQL server you working with is a “copy” or “test” version of the Actual production SQL server being used.
You do not need an ODBC connection on every machine. You can create the connection by using ODBC connection strings via DoCmd.TransferDatabase. This is persistent, so you can just execute the connection/updates on your development copy of the front end and the connection will exist and persist in any end user copies of that that you make.
You do have to deal with the authentication issue. Depending on your security situation you can create a single "database user" and include the username and password to the above connection. If you are in a AD environment you can use that for authentication. Or you create individual SQL accounts for each user or user group. No matter what you do the users will be able to see and edit the tables if Access is to have read/write permission to them. You can secure individual tables by using views to link them to Access instead of the tables themselves.
I would advise against having users make a local copy of the front end. That makes it a nightmare to make sure your users are using the latest version of your front end. Encourage them to make a shortcut instead. Unless you have per-user local temp tables or code that dynamically edits forms/reports there is not much reason not to have everybody using the same front end file. Even in that case create a deployment batch file that creates/overwrites the front end copy for each user.
Sample code that links to SQL server database:
Public Sub LoadDatabase()
Dim MyDB As DAO.Database
Set MyDB = CurrentDb
Dim d As DAO.Recordset
Set d = MyDB.OpenRecordset("SELECT TableName FROM tblLinkTables")
d.MoveFirst
Do While Not d.EOF
DoCmd.DeleteObject acTable, d!TableName
DoCmd.TransferDatabase acLink, "ODBC Database", "ODBC;Driver={SQL Server};Server=MYSQLSERVERNAME;Database=MyDatabaseName;Uid=DatabaseUser;Pwd=DatabaseUserPassword", acTable, d!TableName, d!TableName, False, True
d.MoveNext
Loop
d.Close
Set d = Nothing
End Sub
where the list of tables to link exists on a local table called tblLinkTables with a single field TableName for each table to be linked. This is a very simplified version. The one I actually use has the capability to have different local table names than the SQL tables and also link views and create primary keys (optionally) for them.
The following is one example of how you can obtain a connection to SQL Server. It supports using either a Trusted Connection (where the windows user is authorized access, or you can specify a sqlserver defined userid and password.
' The following are some of the parameters the connection will use.
Global gv_DBS_SQLServer As ADODB.Connection
Global gvstr_SQLServer_Name As String
Global gv_SQLServer_DSN As String
Global gvstr_SQLServer_Database As String
'Call the GetConnection Function
' Pass Name of Server; Database Name; Connection Variable; adUseServer; True if using Password; False if not using a Trusted Connection;
' Sample
If GetConnection(gvstr_SQLServer_Name, gvstr_SQLServer_Database, _
gv_DBS_SQLServer, adUseServer, True, False) = False Then
MsgBox "Unable to connect to SQL Server", vbOKOnly, "No Connection"
End If
Public Function GetConnection(ByVal strDSN As String, _
ByVal strDatabase As String, _
ByRef cnLocal As ADODB.Connection, _
ByVal CursorLoc As CursorLocationEnum, _
ByVal UsePassword As Boolean, _
ByVal blnTrusted As Boolean) As Boolean
Dim strConnectString As String
Dim strDisplay As String
On Error GoTo ERROR_HANDLER
GetConnection = False
Retry_Connection:
If cnLocal Is Nothing Then Set cnLocal = New ADODB.Connection
If cnLocal.State = adStateOpen Then
Debug.Print "Connection already open -- -will not reopen!!"
GetConnection = True
GoTo Proc_Exit
End If
With cnLocal
Debug.Print "Use TRUSTED CONNECTION (ABOVE)"
If blnTrusted = True Then
strConnectString = "Driver={SQL Server};" & _
"Server=" & strDSN & ";" & _
"Database=" & strDatabase & ";" & _
"Trusted_Connection=yes"
Else
strConnectString = "Driver={SQL Server};" & _
"Server=" & strDSN & ";" & _
"Database=" & strDatabase & ";" & _
"User Id=UUUUUUU;Password=" & DecryptString("PPPPPPPP") & ""
strDisplay = "Driver={SQL Server};" & _
"Server=" & strDSN & ";" & _
"Database=" & strDatabase & ";" & _
"User Id=UUUUUU;Password=PPPPPPP"
End If
Debug.Print "Will use Conn String: " & strDisplay
.ConnectionString = strConnectString
.CursorLocation = CursorLoc
.Open
End With
GetConnection = True
Proc_Exit:
Exit Function
ERROR_HANDLER:
Debug.Print Err.Number & vbCrLf & Err.Description
Err.Source = "Module_Connect: "
DocAndShowError
Resume Proc_Exit
Resume Next
Resume
End Function
I'm trying to get this open source code to work in order to start building the basics for my own program. The general idea was just to create a small application that can access and manipulate SQL records, simple, right? Turns out I can't event get the testing going. I keep getting an error on runtime/debug.
The error:
An unhandled exception of type 'System.Data.SqlClient.SqlException'
occurred in System.Data.dll
Additional information: A network-related or instance-specific error
occurred while establishing a connection to SQL Server. The server was
not found or was not accessible. Verify that the instance name is
correct and that SQL Server is configured to allow remote connections.
(provider: Named Pipes Provider, error: 40 - Could not open a
connection to SQL Server)
Here's the code that's not working
Module modConn
Public connDB As New SqlClient.SqlConnection
Public comDB As New SqlClient.SqlCommand
Public rdDB As SqlClient.SqlDataReader
Public Item As ListViewItem
Public SQL As String
Public Sub conecDB()
Dim strServer As String = "127.0.0.1" 'This is the server IP/Server name.
Dim strDbase As String = "Members_Details" 'Database name
Dim strUser As String = "CENSORED" 'Database user
Dim strPass As String = "CENSORED" 'Database password
If connDB.State <> ConnectionState.Open Then connDB.ConnectionString = "Server=" & strServer.Trim & ";Database=" & strDbase.Trim & ";User ID=" & strUser.Trim & ";Password=" & strPass
If connDB.State <> ConnectionState.Open Then connDB.Open
End Sub
The error is referring to the last line connDB.Open.
I've verified the SQL server is running. It's accepting all protocols (TCP/IP, Named Pipes & Shared Memory). The server is MS Server Express + SQL Server Management Studio... And I'm able to sign in and manipulate the database using the SQL Server Managment Studio by using the same login credentials as the program, so I'm pretty sure it's the programs code that's wrong.
My guess is that the area of the code that it brings everything together is wrong; perhaps a character or something -- I'm referring to
If connDB.State <> ConnectionState.Open Then connDB.ConnectionString = "Server=" & strServer.Trim & ";Database=" & strDbase.Trim & ";User ID=" & strUser.Trim & ";Password=" & strPass
If connDB.State <> ConnectionState.Open Then connDB.Open
Any help would be greatly appreciated. I'm relatively new to programming and this is more of a challenge then anything else. Please, in your replies try to keep it structures similarly to what I've got already, if you can.
I'm using Visual Basic Studio on .net 4.5. Thanks in advance!
thanks for your usual fast replies. I've managed to work a solution out when I decided to dig deeper into Mitch Wheat's recommendation to verify the configuration of the SQL Server. It turns out the issue was with the SQL Server configuration. This excellent site had a solution to that as well, thanks! Much appreciated!
The solution to me problem was this. (Link)
I have to connect a Word Document to a SQL Server with VBA in order to read and write records. Now, I'M really confused as of the many different ways to connect to a database. There's ADO, ODBC and so on. I've seen very different ways of connecting a SQL Server database.
A co-worker wants me to use ODBC.
So: What is the best way to connect to a SQL Server database using ODBC in Office VBA?
An example for a SELECT and INSERT statement would also be appreciated.
Edit: Isn't there something like "System.Data.SqlClient.SqlConnection" and "System.Data.SqlClient.SqlCommand" in VB .Net/C#?
This example uses ODBC:
'Microsoft ActiveX Data Objects x.x library
Dim cn As New ADODB.connection
Dim rs As New ADODB.recordset
cn.Open "DRIVER={SQL Server};SERVER=srv;" & _
"trusted_connection=yes;DATABASE=test"
rs.Open "SELECT * FROM table_1", cn
This example uses OleDb
'Microsoft ActiveX Data Objects x.x library
Dim cn As New ADODB.connection
Dim rs As New ADODB.recordset
cn.Open "Provider=sqloledb;Data Source=srv;" & _
"Initial Catalog=Test;Integrated Security=SSPI;"
rs.Open "SELECT * FROM table_1", cn
See also: http://www.connectionstrings.com/sql-server-2008
The reason your co-worker probably wants you to use ODBC is that your company delivers standardized ODBC connections for every single workstation.
The good thing here is that you don't have to worry about connection properties except login/password, because it's all set. Imagine ODBC acting between a software (word) and a server, it makes things alot easier when it comes to changes in your company. (Server address may change and IT is able to change settings of ODBC without the end user even knowing about it)
Beste would be to talk to your co-worker and ask about his concerns. Another reason could be that ODBC might be faster than the ado one. I made this experience, too.
I am using SQL Server Workgroup Edition on Windows Server 2003 R2
My classic ASP pages access my production database using a system DSN. All working here.
Code like this...
<%
dbName= "ProdDB"
userID = "PublicUser"
pwd = "PublicUserPW"
Set objConn = Server.createObject("ADODB.Connection")
objConn.connectionString = "DSN=MySystemDSN"
objConn.open dbName, userID, pwd
%>
For development and testing, I created a copy of ProdDB in Enterprise Manager by
Backing up ProdDB
Restoring from the ProdDB backup set to a new database called TestDB
My understanding was that the restored database would contain an exact copy of the data as well as users, roles etc. Comparing both databases in Enterprise Manager seemed to back up this assumption.
So... I assumed I can access the test copy using the same credentials and only change the dbName, like so...
<%
dbName= "TestDB"
userID = "PublicUser"
pwd = "PublicUserPW"
Set objConn = Server.createObject("ADODB.Connection")
objConn.connectionString = "DSN=MySystemDSN"
objConn.open dbName, userID, pwd
%>
However, now my page returns
[Microsoft][ODBC Driver Manager] Data
source name not found and no default
driver specified
I have even tried creating a new System DSN, with a default database pointing at TestDB. Still no joy.
I'm sure I'm doing something simple and silly. Any assistance gratefully received.
The documentation for the open method says it's declared:
connection.Open ConnectionString, UserID, Password, Options
So it looks like you're passing in TestDB as the connection string. I usually call open without specifying any arguments. Grab a connection string from connectionstrings dot com, and:
objConn.ConnectionString = "Data Source=localhost;Initial Catalog=testdb;" & _
"User Id=myUsername;Password=myPassword;"
objConn.Open