Calling from Access To Stored Procedure that Use Linked Server - sql-server-2008

I have Access that is used as Front End (UI) for the users, let's call it Acc1.
Acc1, is linked to tables on SQL Server.
From Acc1 I want to call to Stored Procedure, let's call it SP1.
SP1, is a simple select on a table in Linked Server. The Linked Server is an Access DB that has only tables. Let's call this DB Acc2.
Note: In the future SP1 will query more complex query that will use table from the Acc2 and from the SQL Server database. Right now as first step I want to execute this simple select query.
When I do in SP1 a simple Select query on a table from the SQL Server table, and try to cal it from Acc1, that's work.
When I try to query the linked server table in SP1 and try to call it from Acc1 it fails with error:
When I run this SP1 from SQL Server it is working.
Any ideas why it happened? How can I do it?
Following is the code:
The SP1:
ALTER PROC [dbo].[spSpanDates_BMPWorkFlowSpanCounts]
AS
BEGIN
SELECT *
FROM
[Supplemental_Form_master_tables]...[tblBPMWorkflows]
END
The code in Acc1:
Private Sub Button_BPMStartEndDatesALL_Click()
Dim qdf As DAO.QueryDef, rst As DAO.Recordset
Dim FindRecordCount As Long
Set qdf = CurrentDb.CreateQueryDef("")
qdf.Connect = "ODBC;DRIVER={sql server};DATABASE=PLMScheduling; SERVER=USCLES425\INST2; Trusted_Connection=Yes;"
qdf.sql = "EXEC dbo.spSpanDates_BMPWorkFlowSpanCounts"
qdf.ReturnsRecords = True
Set rst = qdf.OpenRecordset(dbOpenSnapshot)
If rst.EOF Then
FindRecordCount = 0
Else
rst.MoveLast
FindRecordCount = rst.RecordCount
End If
rst.Close
Set rst = Nothing
Set qdf = Nothing
End Sub
I'm using SQL Server 2008 and Access 2010.
Thank you very much for the help!

The answer is very simple. When SP1 run from Acc1, SQL Server uses the permissions of Acc1. So when try to query in SP1 tables from Acc2 with the permissions of Acc1 this fail.

Related

How to execute and query in VBA in MS Access using the ODBC Connector for MySQl?

The following VBA code will allow you to run a sql query in the current access database
I tried this in a MS Access file that is connected to a MySQL database through the ODBC Connector. However this code does not work, presumably because it's not a normal access DB.
How can I query the database using the existing ODBC connection?
EDIT: I always get a "Runtime error 3024 cannot find file"
Try 1
Dim mydb As Database
Dim myrs As DAO.Recordset
Set mydb = CurrentDb
Set myrs = mydb.OpenRecordset("select from blah blah...")
Try 2
Dim dbMine As DAO.Database
Set dbMine = CurrentDb
Dim qr As String
qr = "select count(*) as `result` from floatinp_appdb2.clientes where cliente_email = 'tiagovalente#float-in.pt';"
'debug.print qr
dbMine.Execute qr, dbFailOnError
Requirements are:
Linked table has a PK defined.
So, this should work:
Set myrs = mydb.OpenRecordset("select from blah blah...",dbOpenDynaset, dbSeeChanges)
Also:
any true/false columns (bit fields) should have default value of 0 set. (don't allow nulls for the true/false columns).
You can and should also consider adding a rowversion column, but above should suffice.
Though the error was "runtime error 3024 cannot find file", my mistake was including the database name before the table
e.g. Select * From DB2.Table1

VBA Code for Transferring ACCESS Table to SQL Server

I was trying to Transfer my Access Table Data over to SQL server but I am getting an error which says
Object Variable or With block variable not set
I've already connected my Access database with SQL server but now facing problem transferring data to SQL server with VBA code.
Can you please help me with it?
Here is my code:
Public Sub ADOtest()
Dim ADOConn As New ADODB.Connection
Dim ADOCom As New ADODB.Command
On Error Resume Next
ADOConn.ConnectionString = "Driver={SQL Server};Server=IT-TEMP2-8470P\SQLEXPRESS2014;Database=Discrepancy;Trusted_Connection=True;"
ADOConn.Open
Debug.Print ADOConn.State
Dim db As Database
Dim Discrepancy As Database
Set db = Discrepancy
Dim ID As Variant
db.Execute "INSERT INTO [ODBC;DRIVER=SQL Server;SERVER=IT-TEMP2-8470P\SQLEXPRESS2014;DATABASE=Discrepancy].SFTransfersDB ( ID, TO ) SELECT ID,TO FROM SFTransfersDB"
End Sub
I am getting error at the 2nd last line:
db.Execute "INSERT INTO [ODBC;DRIVER=SQL Server;SERVER=IT-TEMP2-8470P\SQLEXPRESS2014;DATABASE=Discrepancy].SFTransfersDB ( ID, TO ) SELECT ID,TO FROM SFTransfersDB"
It seems you are attempting an ad hoc distributed query. If server permits it, consider executing this statement after your ADO connection. No need for calling Access objects.
ADOConn.Execute "INSERT INTO dbo.SFTransfersDB ([ID], [TO])" _
" SELECT [ID], [TO] FROM OPENDATASOURCE('Microsoft.ACE.OLEDB.12.0', " _
"'Data Source=""C:\Path\To\Access\Database.accdb""')...SFTransfersDB;"
You declare two Database variables, but don't initialize them (you don't set them to anything):
Dim db As Database
Dim Discrepancy As Database
So this
Set db = Discrepancy
is the same as
Set db = Nothing
and so when you try to use db, you get the error that db is not set, which it isn't.
Thanks for your suggestions.
I got it correct after all.
I used "Set db = CurrentDb" and it worked perfect.

Safe MySQL queries in vbscript

Im doing some MySQL operations in vbscript and currently Im doing (not true vbscript code as I dont know the syntax off the top of my head):
Dim whereclause=textboxtext
$DBExecute("connectionstring","delete from table where column='"+query+"'")
Obviously this is VERY unsafe and almost destructive. Is there a MySQL function I can pass in that query to make it safer?
There is no magic fairydust function to automatically make your statements harmless. A user that has permission to delete records will always be able to delete records.
If you're concerned about the way you build the statement (using string concatenation), now that's a whole other story. SQL injection can be mitigated via prepared statements (or parameterized queries, as Microsoft calls them):
value = "..."
connectionString = "..."
Set conn = CreateObject("ADODB.Connection")
conn.Open connectionString
Set cmd = CreateObject("ADODB.Command")
Set cmd.ActiveConnection = conn
cmd.CommandText = "DELETE FROM table WHERE column=?"
Set p = cmd.CreateParameter("#p", 200, 1, 255, value)
cmd.Parameters.Append p
cmd.Execute

Bulk Insert from VBA into SQL Server

I'm using SQL Server 2008 R2 and I've created a User Defined Type:
create type dbo.UDT as table (FirstName varchar(50) null, LastName varchar(50) null)
I've create a stored procedure that has this UDT as a parameter:
create procedure dbo.InsertIntoMyTableUsingUDT (#udt dbo.UDT readonly)
as
begin
set nocount on;
insert into dbo.MyTable (FirstName, LastName)
select FirstName, LastName from #udt;
return;
end
I would like to use VBA's ADO (ADO.COM/OLE DB) to bulk upload 10,000+ records using this stored procedure.
I've tried passing an ADODB.Recordset as a parameter in an ADODB.Command:
<code that creates ADODB.Recordset 'rst' here...>
Dim com as ADODB.Command
Set com = new ADODB.Command
With com
.ActiveConnection = "Provider=SQLOLEDB.1;Data Source=localhost;Initial Catalog=TestDB;Integrated Security=SSPI;"
.CommandText = "dbo.InsertIntoMyTableUsingUDT"
.CommandType = adCmdStoredProc
.Parameters.Refresh
.Parameters(1).Value = rst '<----the ADODB.Recordset created above
.Execute
End With
but I get the runtime error:
Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.
Checking the parameter's type in the Immediate Window I get:
?com.Parameters(1).Type
143
which I can't see in MSFT's list of OLE DB DataTypeEnums:
http://msdn.microsoft.com/en-gb/library/windows/desktop/ms675318(v=vs.85).aspx
So I tried passing in a 2-dimensional array instead of the ADODB.Recordset but then I got the error:
Bad variable type.
Both attempts failed and it's got me stumped.
I know it can be done in VB.NET using ADO.NET and the SqlParameterCollection.AddWithValue method.
I would like to know if there is a way of doing it in VBA using ADO.COM. Has anyone done it?
Alternatively, is there a different way of achieving the same thing (bulk upload rather than calling an ADODB.Command 10,000+ times in a loop)?
Cheers

Access & SQL-Server: Resetting Autonumber field with table wipe

I am trying to keep a copy of an activity table synchronized between a SQL Server Express table and the production Access version. In other tables, I am able to wipe the contents of the SQL Server table, and insert the whole mess back in to capture all of the changes. However, when I attempt to do that with this table - I get the information - but the Autonumber field increments from the last unused number from the previous iteration. After a dozen or so 'sync' operations, I am dangerously close to running out of autonumbers for this field.
I have tried issuing the 'DBCC CHECKIDENT' from the Microsoft Access front end application, which throws an error that the statement didn't start with SELECT, DELETE, PROCEDURE, DROP, ALTER or something like that. This command DOES work when issued from the SQL Server management console (a tool I do have access to in the current test environment, but will NOT when the application goes production).
I then tried the 'TRUNCATE TABLE' query using the DoCmd.RunSQL command and it threw the error that the operation isn't supported on linked tables (approximately). This table is linked to the Microsoft Access front-end (the back end table is on SQL Server Express).
So, for a quick summary:
Front End is an Microsoft Access VBA application
Data is stored on SQL Server Express on a remote machine
Data tables are linked in the front end application
I will NOT be able to use SQL Server Management Console commands when this application goes production, it needs to run it's housekeeping on it's own.
DoCmd.RunSQL and CurrentDB.Execute do not seem to allow the use of the TRUNCATE TABLE -or- the 'DBCC CHECKIDENT' command.
Both of the aforementioned functions -DO- work when issued from the SQL Server Management Console - see above as to why this isn't a viable option.
-ALL- other tables behave the way I'd expect them to besides this one, resetting their indentity fields as appropriate.
-- Edited 08/08/2011 # 15:08 --
Alright - I have tried a number of attempts at a VBA-based pass-through query, all resulting in an ODBC -- call failed error. Here is the code for the module I created to handle pass-throughs (borrowed the code from dbforums.com):
Function RunPassThrough(ByVal ConnectionString As String, ByVal SQL As String, Optional ByVal QueryName As String)
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Set dbs = CurrentDb
Set qdf = dbs.CreateQueryDef
With qdf
.Name = QueryName
.Connect = ConnectionString
.SQL = SQL
.ReturnsRecords = (Len(QueryName) > 0)
If .ReturnsRecords = False Then
.Execute
Else
If Not IsNull(dbs.QueryDefs(QueryName).Name) Then dbs.QueryDefs.Delete QueryName
dbs.QueryDefs.Append qdf
End If
.Close
End With
Set qdf = Nothing
Set dbs = Nothing
End Function
As such, I need to specify a connection string to the database; all of the following have failed:
strConnect = "ODBC;DRIVER={SQL Server};SERVER=ENV980-067\ENVIRON_TEST;DATABASE=instkeeper_test;Uid=<my username>;Pwd=<my password>;"
Result: Run-time error ODBC -- call failed (error #3146)
strConnect = "ODBC;DRIVER={SQL Server};SERVER=ENV980-067\ENVIRON_TEST;DATABASE=instkeeper_test;TRUSTED_CONNECTION=YES;"
Result: Run-time error ODBC -- call failed (error #3146)
strConnect = "ODBC;DSN=instkeeper_beta;"
Result: Asks me for the Data Source Name, once specified with the Data Source administration panel, I get Run-time error ODBC -- call failed (error #3146)
strConnect = "ODBC;Server=ENV980-067\ENVIRON_TEST;Database=instkeeper_test;User ID=<my user name>;Password=<my password>;Trusted_Connection=False;"
Result: Run-time error ODBC -- call failed (error #3146)
-- Edited 08/08/2011 # 16:41 --
MORE failures on iterations of the connection strings, I am officially out of ideas on how to make this beast work. After trying the previous - now any pass-throughs made with the interface fail after asking for a DSN. No repair is possible, they have to be restored to call on the linked tables and ran through JET.
strConnect = "ODBC;DATA SOURCE=instkeeper_test;"
Result: Run-time error ODBC -- call failed (error #3146)
strConnect = "ODBC;DRIVER=SQL Server;SERVER=ENV980-067\ENVIRON_TEST;"
Result: Run-time error ODBC -- call failed (error #3146)
strConnect = "ODBC;DRIVER=SQL Server;Server=ENV980-067\ENVIRON_TEST;Database=instkeeper_test;User ID=<my user name>;Password=<my password>;"
Result: Run-time error ODBC -- call failed (error #3146)
In the SQL Server side, you can
Use another DBCC command
DBCC CHECKIDENT ('MyTable', RESEED, 1)
Or use TRUNCATE TABLE...
If the table contains an identity column, the counter for that column is reset to the seed value defined for the column. If no seed was defined, the default value 1 is used.
So you'd run
TRUNCATE TABLE MyTable
I went through all of my code, and checked with a local VBA expert who pointed out that I had made an error in the naming of my tables while attempting to do a pass-through query. I, basically, was referring to the table by the name it possess as a link in my front-end, and not the actual table name it possesses in SQL Server on the back end.
The following connection string, once this was corrected, worked:
strConnect = "ODBC;DRIVER={SQL Server};SERVER=ENV980-067\ENVIRON_TEST;DATABASE=instkeeper_test;TRUSTED_CONNECTION=YES;"
This, then, allowed me to execute the TRUNCATE TABLE command on the remote table, and execute a DoCmd.RunSQL statement to repopulate the table from the production source.
The end result is that when the option is selected to update the Activity, it will purge the contents of the remote table, then read the contents of the production table into the test table for use while resetting the autonumber.
I found out an easy way of doing that trought a SQL query written in Access, at the SQL View!
Check it out at:
http://answers.microsoft.com/en-us/office/forum/office_2003-access/reset-autonumber-in-access-table-automatically/66cbcfed-5cbe-40f6-b939-9aea8bbea2de
Write this:
ALTER TABLE YourTable ALTER COLUMN YourField COUNTER(1,1)