kabradley
asked on
DSNless ODBC Connection to SQL Server from Acess for Scalable Updates
Hello Everyone,
I am needing to connect to a SQL server being hosted on a remote webserver from my access database. The goal of logging in is this:
1. Open Access
2. Prompt User for user ID and PW
3. If UID & PW are correct, check program front end version (stored in local table)
4. If version is lower then current version have client's access run a pass through query to grab the data on the SQL server that is new
5. Run an append query on the clients machine based off of the pass through query that updates their tables with the new information. The client does not have permissions to edit the tables that update.
6. Close ODBC Connection
I'm just having a plethora of problems getting this to work. First and foremost is the DSNless connection. I have a module with the following code
Public Sub UseConnectionODBC()
Dim cnn As ADODB.Connection
Set cnn = New ADODB.Connection
cnn.Open _
"DRIVER=SQL Server;" & _
"Server=xxxserversaddressx xx;" & _
"Database=DBname;UID=xxxx; PWD=xxxx"
Debug.Print cnn.ConnectionString
End Sub
I then call this function on the On_Open event of the dashboard/switchboard form that opens with the program. I then tried making a pass through query that has the following sql:
SELECT * From LPID;
The first problem I've run into is that when I try and run this query, Access immediately prompts me for the proper DSN. I don't know why b/c technically by my understanding, I'm currently connected to the SQL Server. (All of the information in the connection function is accurate).
I then tried to query the pass-through query to see if that was the problem. Access wouldn't even let me select the query in the table chooser until I selected the pass-through queries associated DSN.
My two questions are:
1. What am I doing wrong? Why is the query not working when the connection should be established?
AND
2. Is there a better method of updating the client's data? (The clients data will need updates roughly 10 or so times a month)
I am needing to connect to a SQL server being hosted on a remote webserver from my access database. The goal of logging in is this:
1. Open Access
2. Prompt User for user ID and PW
3. If UID & PW are correct, check program front end version (stored in local table)
4. If version is lower then current version have client's access run a pass through query to grab the data on the SQL server that is new
5. Run an append query on the clients machine based off of the pass through query that updates their tables with the new information. The client does not have permissions to edit the tables that update.
6. Close ODBC Connection
I'm just having a plethora of problems getting this to work. First and foremost is the DSNless connection. I have a module with the following code
Public Sub UseConnectionODBC()
Dim cnn As ADODB.Connection
Set cnn = New ADODB.Connection
cnn.Open _
"DRIVER=SQL Server;" & _
"Server=xxxserversaddressx
"Database=DBname;UID=xxxx;
Debug.Print cnn.ConnectionString
End Sub
I then call this function on the On_Open event of the dashboard/switchboard form that opens with the program. I then tried making a pass through query that has the following sql:
SELECT * From LPID;
The first problem I've run into is that when I try and run this query, Access immediately prompts me for the proper DSN. I don't know why b/c technically by my understanding, I'm currently connected to the SQL Server. (All of the information in the connection function is accurate).
I then tried to query the pass-through query to see if that was the problem. Access wouldn't even let me select the query in the table chooser until I selected the pass-through queries associated DSN.
My two questions are:
1. What am I doing wrong? Why is the query not working when the connection should be established?
AND
2. Is there a better method of updating the client's data? (The clients data will need updates roughly 10 or so times a month)
What port is the SQL Server listening on? If you know a specific listening port you can add an ADDRESS=SQLSERVERIPADDRESS :Port; after the PWD ;
ASKER
I'm not sure, I've purchased shared webspace, so when I'm in Management Studio and I connect to the actual 'server' I see many, many databases but, I can of course only access and modify my personal database.
How would I check what port it's operating through? And, is there a way to check while in access whether or not I'm actually connected to the sql server?
How would I check what port it's operating through? And, is there a way to check while in access whether or not I'm actually connected to the sql server?
The host should be able to provide you with information pertaining to the DSN and which ports that SQL Server is listening on. I'll bet that they have ports 1433 and 1434 firewall blocked due the the old Slammer worm problem.
ASKER
Well, I just got off the phone with my webhost and they said that they have the sql server listening on both 1433 and 1434. So, it shouldn't be a port problem since those are the default ports.
On the :
Public Sub UseConnectionODBC()
Dim cnn As ADODB.Connection
Set cnn = New ADODB.Connection
cnn.Open _
"DRIVER=SQL Server;" & _
"Server=xxxserversaddressx xx;" & _
"Database=DBname;UID=xxxx; PWD=xxxx"
Debug.Print cnn.ConnectionString
End Sub
Is there away after running the function to have a message box saying what the current connection is? I guess the key element that I'm looking for initially is whether or not the connection is being made successfully and testing for that. B/c if the connection isn't successful obviously nothing else will be.
On the :
Public Sub UseConnectionODBC()
Dim cnn As ADODB.Connection
Set cnn = New ADODB.Connection
cnn.Open _
"DRIVER=SQL Server;" & _
"Server=xxxserversaddressx
"Database=DBname;UID=xxxx;
Debug.Print cnn.ConnectionString
End Sub
Is there away after running the function to have a message box saying what the current connection is? I guess the key element that I'm looking for initially is whether or not the connection is being made successfully and testing for that. B/c if the connection isn't successful obviously nothing else will be.
ASKER
Alright I was looking on the internet as to other ways of connecting and I ran across this piece of code
Public Sub CreateTable()
Dim strTableName As String, strConnect As String
'This connection string creates a DSN-less connection to the server (called PMSR in this instance)
strConnect = "ODBC;Driver={SQL Server};SERVER=****;DATABA SE=****;UI D=****;PWD =****;"
'What I want the table to be called
strTableName = "tblCurrentProducts"
'Check to see if table exists. If it does, delete it.
If TableExists(CurrentDb, strTableName) Then DoCmd.DeleteObject acTable, strTableName
'And then use the trusty old TransferDatabase method to re-import the table "Products" from the SQL Server :-)
DoCmd.TransferDatabase acImport, "ODBC Database", strConnect, acTable, "LPID", strTableName
End Sub
Private Function TableExists(db As Database, strTableName As String) As Boolean
Dim td As DAO.TableDef
On Error Resume Next
Set td = db.TableDefs(strTableName)
TableExists = Err.Number = 0
End Function
I used it in a module and ran the CreateTable function off of a button on a form. I first ran it with no password in the connection string, only a username. After clicking the command button it was tied to a error message popped up that said it can't connect to the sql server, please enter your password. I clicked ok and then another form popped up with the server name, dB name, username, and a blank field where the password should go. I entered the correct password and clicked ok. After clicking ok the form disappeared and I checked my table roster to see if tblCurrentProducts was created (I didn't previously have this table in access). When I checked it out, sure enough there was the table with the correct information!
So, what this means to me is that, I can in fact connect to the sql server, now I just need to figure out how to run several different pass through queries on startup and update the information in the clients backend and then close the sql connection.
I'm going to try and create the pass through query again and see if it works. I'll post my results.
Public Sub CreateTable()
Dim strTableName As String, strConnect As String
'This connection string creates a DSN-less connection to the server (called PMSR in this instance)
strConnect = "ODBC;Driver={SQL Server};SERVER=****;DATABA
'What I want the table to be called
strTableName = "tblCurrentProducts"
'Check to see if table exists. If it does, delete it.
If TableExists(CurrentDb, strTableName) Then DoCmd.DeleteObject acTable, strTableName
'And then use the trusty old TransferDatabase method to re-import the table "Products" from the SQL Server :-)
DoCmd.TransferDatabase acImport, "ODBC Database", strConnect, acTable, "LPID", strTableName
End Sub
Private Function TableExists(db As Database, strTableName As String) As Boolean
Dim td As DAO.TableDef
On Error Resume Next
Set td = db.TableDefs(strTableName)
TableExists = Err.Number = 0
End Function
I used it in a module and ran the CreateTable function off of a button on a form. I first ran it with no password in the connection string, only a username. After clicking the command button it was tied to a error message popped up that said it can't connect to the sql server, please enter your password. I clicked ok and then another form popped up with the server name, dB name, username, and a blank field where the password should go. I entered the correct password and clicked ok. After clicking ok the form disappeared and I checked my table roster to see if tblCurrentProducts was created (I didn't previously have this table in access). When I checked it out, sure enough there was the table with the correct information!
So, what this means to me is that, I can in fact connect to the sql server, now I just need to figure out how to run several different pass through queries on startup and update the information in the clients backend and then close the sql connection.
I'm going to try and create the pass through query again and see if it works. I'll post my results.
Try hard coding the connect string into the ODBC Connect Str property on the pass through to see if it works
Build the connect string and update all the querydef.connect = your connect string then run the pass throughs
ASKER
Triple Post ftl...
Before trying a pass through query I thought I would try and see whether or not I had to have the connection string in the CreateTable function. I decided to make this function to see:
Public Sub CreateTableNoConnect()
Dim strTableName As String, strConnect As String
'What I want the table to be called
strTableName = "tblCurrentProducts"
'Check to see if table exists. If it does, delete it.
If TableExists(CurrentDb, strTableName) Then DoCmd.DeleteObject acTable, strTableName
'And then use the trusty old TransferDatabase method to re-import the table "Products" from the SQL Server :-)
DoCmd.TransferDatabase acImport, "ODBC Database", , acTable, "LPID", strTableName
End Sub
I then ran the CreateTable function which has the strconnect code. It ran fine of course. I then created another form with a command button that executed the CreateTableNoConnect function. It ran that with no problems! So, the connection was still open and is not needed to be declared every time (until of course the connection is closed). This was good news for me. I then went to the query builder and chose to create a passthrough query. The sql looked like this:
SELECT * FROM LPID;
I then tried to execute it. Immediately upon doing so the DSN box popped up! Asking for which DSN I wanted to use. I don't know why...and I don't know how to circumvent it.
Any suggestions?
Before trying a pass through query I thought I would try and see whether or not I had to have the connection string in the CreateTable function. I decided to make this function to see:
Public Sub CreateTableNoConnect()
Dim strTableName As String, strConnect As String
'What I want the table to be called
strTableName = "tblCurrentProducts"
'Check to see if table exists. If it does, delete it.
If TableExists(CurrentDb, strTableName) Then DoCmd.DeleteObject acTable, strTableName
'And then use the trusty old TransferDatabase method to re-import the table "Products" from the SQL Server :-)
DoCmd.TransferDatabase acImport, "ODBC Database", , acTable, "LPID", strTableName
End Sub
I then ran the CreateTable function which has the strconnect code. It ran fine of course. I then created another form with a command button that executed the CreateTableNoConnect function. It ran that with no problems! So, the connection was still open and is not needed to be declared every time (until of course the connection is closed). This was good news for me. I then went to the query builder and chose to create a passthrough query. The sql looked like this:
SELECT * FROM LPID;
I then tried to execute it. Immediately upon doing so the DSN box popped up! Asking for which DSN I wanted to use. I don't know why...and I don't know how to circumvent it.
Any suggestions?
For every query that you have populate the querydef.connect with your built string after you collect the user login and password then you'll get no popup.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
So Jmoss,
Are all of your queries written in the VB editor?
I guess I'm just really confused as to how to run the pass throughs.
Lets say I create a global variable, that contains the connection info. Upon opening access they enter their UID and PWD. The global connection string now has all the info it needs. What is the next step I need to take? cnn.open? I have to actually connect to the sql database correct?
Are all of your queries written in the VB editor?
I guess I'm just really confused as to how to run the pass throughs.
Lets say I create a global variable, that contains the connection info. Upon opening access they enter their UID and PWD. The global connection string now has all the info it needs. What is the next step I need to take? cnn.open? I have to actually connect to the sql database correct?
Most of my queries are written in code and depend on user selection criteria in a form. A vba module looks at whats populated in the form and builds the querydef.sql. The DSN less querydef.connect string is built when the main form opens. When the user clicks a button on the form, the vba builds the .sql and the pass through is executed. The pass through makes the connection upon execution
ASKER
OK J
I think I've made some definite progress. I just finished testing a login form I made. It requests UID and Pass, after the user has entered that information and clicked "login" on a command button a string is created that connects to the server via oledb. It is working correctly, i.e. if the user enters incorrect information they are not logged in, but are asked to try and input the correct information. If the user enters the correct information then they are logged in and the frmLogin is made invisible. That way if I need to access the UID and PWD I can just do so by accessing the form's controls.
So, now the question is how do I make the pass through?
I just tried this with no luck:
'Make Database declarations
Dim dbs As DAO.Database
Dim strSQL As String
Dim strQueryName As String
Dim qryDef As DAO.QueryDef
Dim strConnect As String
On Error Resume Next
'set variable values
Set dbs = CurrentDb
strQueryName = "qryGeneral"
strConnect = Forms!frmLogin.ODBCConnect
'Delete old query first - we want fresh data!
dbs.QueryDefs.Delete strQueryName
strSQL = "SELECT * FROM tblLPID;"
'Create query definition
Set qryDef = dbs.CreateQueryDef(strQuer yName, strSQL)
qryDef.Connect = strConnect
DoCmd.OpenQuery "qryGeneral"
This was tied to a command button, it was to run that upon being clicked. strConnect is a string that is is getting it's connection string directly from frmLogin. When I tried this, it did not work.
Any clues?
I think I've made some definite progress. I just finished testing a login form I made. It requests UID and Pass, after the user has entered that information and clicked "login" on a command button a string is created that connects to the server via oledb. It is working correctly, i.e. if the user enters incorrect information they are not logged in, but are asked to try and input the correct information. If the user enters the correct information then they are logged in and the frmLogin is made invisible. That way if I need to access the UID and PWD I can just do so by accessing the form's controls.
So, now the question is how do I make the pass through?
I just tried this with no luck:
'Make Database declarations
Dim dbs As DAO.Database
Dim strSQL As String
Dim strQueryName As String
Dim qryDef As DAO.QueryDef
Dim strConnect As String
On Error Resume Next
'set variable values
Set dbs = CurrentDb
strQueryName = "qryGeneral"
strConnect = Forms!frmLogin.ODBCConnect
'Delete old query first - we want fresh data!
dbs.QueryDefs.Delete strQueryName
strSQL = "SELECT * FROM tblLPID;"
'Create query definition
Set qryDef = dbs.CreateQueryDef(strQuer
qryDef.Connect = strConnect
DoCmd.OpenQuery "qryGeneral"
This was tied to a command button, it was to run that upon being clicked. strConnect is a string that is is getting it's connection string directly from frmLogin. When I tried this, it did not work.
Any clues?
ASKER
Ok, J
Scratch that. I didn't do anything different, just clicked the command button again and this time the query came up correctly. Odd... The one thing that I did notice is that I then disconnected from the sql server and then tried clicking the query button. The query came up correctly? So, does access cache some of what is being transfered?
Scratch that. I didn't do anything different, just clicked the command button again and this time the query came up correctly. Odd... The one thing that I did notice is that I then disconnected from the sql server and then tried clicking the query button. The query came up correctly? So, does access cache some of what is being transfered?
Why delete the querydef? You could set it to empty but each time the .sql is updated the old .sql gets overwritten. If the same query is executed each time why bother recreating? If the same set of queries are generated each time why not just build SP instead?
ASKER
The reason for deleting "qryGeneral" is because that query name is used for several different queries in my program. It's essentially just a "holding house" for multiple sql statements.
And you answered my next question with your question. I had seen on the net that several people just use stored procedures on their sql server and just have the pass through execute those. From what I've read this is also a faster, more efficient way of doing things as well so I'm going to try that next.
Thanks!
And you answered my next question with your question. I had seen on the net that several people just use stored procedures on their sql server and just have the pass through execute those. From what I've read this is also a faster, more efficient way of doing things as well so I'm going to try that next.
Thanks!
SPs are faster due to the fact that an execution plan is saved on the server. All you have to do in the pass through is EXEC mySP;
ASKER
Well, I changed my code to this:
strSQL = "EXEC sp_LPID"
Yet it doesnt' run. BUT if, I make a passthrough query with that exact same sql, execute it (and choose a DSN that works) it executes fine. I don't understand why it would work for one, but not the other.
strSQL = "EXEC sp_LPID"
Yet it doesnt' run. BUT if, I make a passthrough query with that exact same sql, execute it (and choose a DSN that works) it executes fine. I don't understand why it would work for one, but not the other.
Does the user have correct permissions to execute the sp? I wouldn't want assume that if you had permission to do the pass through that you would have correct permissions for the SP. Basically, you should be using the same connect string, etc in the pass through for the SP as the one used for the SQL statement
ASKER
I'm using the same user that I was using with the TSQL which happens to be the same user that created the sp. The statement I am using looks like this:
'Make Database declarations
Dim dbs As DAO.Database
Dim strSQL As String
Dim strQueryName As String
Dim qryDef As DAO.QueryDef
Dim strConnect As String
On Error Resume Next
'set variable values
Set dbs = CurrentDb
strQueryName = "qryGeneral"
strConnect = Forms!frmLogin.ODBCConnect
'Delete old query first - we want fresh data!
dbs.QueryDefs.Delete strQueryName
strSQL = "EXEC sp_LPID"
'Create query definition
Set qryDef = dbs.CreateQueryDef(strQuer yName, strSQL)
qryDef.Connect = strConnect
DoCmd.OpenQuery "qryGeneral"
So the only difference is the execute statement.
'Make Database declarations
Dim dbs As DAO.Database
Dim strSQL As String
Dim strQueryName As String
Dim qryDef As DAO.QueryDef
Dim strConnect As String
On Error Resume Next
'set variable values
Set dbs = CurrentDb
strQueryName = "qryGeneral"
strConnect = Forms!frmLogin.ODBCConnect
'Delete old query first - we want fresh data!
dbs.QueryDefs.Delete strQueryName
strSQL = "EXEC sp_LPID"
'Create query definition
Set qryDef = dbs.CreateQueryDef(strQuer
qryDef.Connect = strConnect
DoCmd.OpenQuery "qryGeneral"
So the only difference is the execute statement.
ASKER
Alright, I tried a few different ways and finally got it to work (I think my formatting else where was incorrect) but, never-the-less it's now working. Thanks for the help J!
I just took a sql statement from a user generated query and built an sp from it and also ran the sql statement from query analyzer. The query was a three column search of 8.5 million rows with a 2 column exact match (date) and the third column was wildcard on both ends of a vendor name. the query ran 38 seconds to return all rows, while the sp ran 40 seconds. 58000 rows returned
ASKER
So it seems, the query was faster, but the speed difference was almost negligible.
I think that would be the majority type result unless you strung several more processes into the sp.