1

对文字感到抱歉,尽量简洁

我们正在尝试建立一个流程,让使用访问数据库的最终用户(在不同网络之间移动的笔记本电脑上的远程用户)向我们的 SQL 服务器发送请求,让该服务器执行存储过程。在 SQL Server 收到此请求后,服务器应查找该用户的一系列预期值,然后执行不同的存储过程以启动返回到调用设备的新链接(基于它与 Internet 的连接方式这次),对该机器上的数据运行一系列验证,如果验证成功,它应该更新远程客户端上的表中的数据,然后断开连接。

当我们直接使用 SSMS 从 SQL Server 执行调用过程时,我们已经设置并正常工作(例如:我们登录到运行 SQL Server 的服务器,然后使用 SSMS 执行存储过程),如果我们离开那里的链接我们可以使用 SSMS 读取/编辑/修改远程客户端中的任何数据/表。但是,当从远程客户端调用存储过程时,它们可以工作,除非这些存储过程尝试读取/写入远程链接服务器(例如:添加和删除到数据库的链接的存储过程工作正常,但是看起来的查询at 或编辑远程数据库中的数据会返回一个错误,看起来它与与文件访问相关的权限有关)。

我们的环境:设备在我们的域上,SQLserver 2017 Express,Windows 10,accdb 数据库(2007)

总结:我们正在编写 VBA 代码来在我们的域上执行远程 SQL Server 2017 Express 存储过程,以更新在 Windows 10 计算机上运行的同一个调用 accdb 数据库 (2007) 中的表。结果:我们希望远程机器只在 sql server 上运行存储过程,而不是为了增加安全性和效率而没有特定的表/视图。即访问vba 说我在线,sql server 创建链接并检查更新的联系人、下载和断开连接。过程创建一个链接服务器(sp_addlinkedserver),登录(sp_addlinkedsrvlogin),更新一个表(@sql = 'UPDATE'),删除链接(sp_dropserver)一旦我们有了这个工作,我们计划创建其他存储过程来查询accdb文件并上传新数据到 SQL 服务器。

所以,在我们目前拥有的 SQL 服务器上

CREATE PROCEDURE [dbo].[SQLserverlastconnect] @p_linkservername nvarchar(max) = null, @p_linkdatasrc nvarchar(max) = NULL
AS
DECLARE @sql NVARCHAR(MAX)

EXEC master.dbo.sp_addlinkedserver @server = @p_linkservername, @srvproduct=N'', @provider=N'Microsoft.ACE.OLEDB.12.0', @datasrc= @p_linkdatasrc
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'<servername>\<instance>', @locallogin = NULL , @useself = N'True';

SET @sql = 'UPDATE ' +  @p_linkservername  + '...tbl_Ref_Local SET  tqs_Data =  ''' + CONVERT(varchar(50),FORMAT(CURRENT_TIMESTAMP, 'yyyy-MM-dd hh:mm:ss')) + ''' WHERE tqs_KeyIdentifier = ''LastConnect'''

EXEC(@sql)

EXEC master.sys.sp_dropserver @p_linkservername,'droplogins'  

在 Access 365 中,我们有一个 Sub(尝试了许多更改,包括查找连接字符串的问题)

Sub Test()
    Dim connection As Object: Set connection = CreateObject("ADODB.Connection")
    Dim rs As Object: Set rs = CreateObject("ADODB.Recordset")
    With connection
              .ConnectionString = "DRIVER=SQL Server;Server=<servername>\<Instance>;Trusted_Connection=Yes;APP=2007 Microsoft Office system;DATABASE=SixBit;User ID=sa;Password=********" ‘[we tried to remove User ID/Password and only use a trusted connection]
              .CommandTimeout =0
              .Open
    End With
    Set rs = connection.Execute("EXEC dbo.SQLserverlastconnect @p_linkservername = N'Test7', @p_linkdatasrc = N'\\fileserver\Programming\TQS - Client 0.03.22.accdb'")
‘tried this also Set rs = connection.Execute("INSERT INTO [Test7]...[tbl_Ref_Local] ([tqs_KeyIdentifier],[tqs_Data],[tqs_GUID]) VALUES ('t', 't' ,'t')")
    connection.Close: Set rs = Nothing: Set connection = Nothing
End Sub

我们尝试过的事情:我们已将所有人添加到文件所在的网络共享中,将所有人添加到临时路径,将 SQL 服务器服务“登录身份”从默认更改为域管理员以及“网络服务”。我们没有花太多时间的一个领域是 SQL 服务器上链接服务器属性上的“登录映射”(我们确实尝试过模拟“sa”)这是我们在运行 VBA 时得到的当前消息。尝试设置 NET USE U:,尝试指向另一个未打开的访问数据库(旧版本),因为该消息似乎暗示我们无法在数据库运行时打开该数据库,还尝试了一个文本文件。

最后,我们创建了一个触发器,并且可以让它运行一个 SELECT(很多拳头抽),但不是一个 UPDATE 或 INSERT(悲伤的脸),但这可能向那里的人表明一些东西。

有没有人有任何建议?

4

2 回答 2

0

这似乎是一个坏主意,也是处理此解决方案的方法。

首先,如果客户端以独占方式启动 Access,则 Access 或 SQL 服务器将无法成功链接。

并且您必须确保 SQL 服务器不会尝试打开(链接)独占客户端访问数据库。也许当您从 SSMS 进行测试时,您没有在同一个 accDB 文件打开的情况下启动访问副本。我没有仔细看,但我相信到 Access 的服务器链接的默认设置是独占的(这意味着当 Access 客户端打开相同的文件时,无法打开客户端 accDB 文件。

更糟糕的是,如果您通过客户端中的 SERVER 端更新任何数据,那么任何行都将被拉到 sql server、更新,然后再发送回网络。为什么不将该更新代码移动到本地,并且您不会生成任何网络流量来实现对本地数据的更新。

这种通过“wan”而不是本地 LAN 的更新非常慢。当您使用 SQL 系统进行更新时,实际上您是从本地文件“原始”读取数据,这在 WAN 连接上是一个非常糟糕的主意。如果连接中断,您将损坏并炸毁本地 accDB 文件。

从 Access 到 sql server 的链接表很好,因为“文件”没有被读取或通过网络传输。但是,将 SQL Server 链接到本地​​客户端 accDB 意味着 Windows 文件系统正在通过该 VPN/WAN 连接从 SQL Server 遍历。你“真的”想避免这种情况。这意味着 SQL 服务器正在执行文件打开,并且寡妇文件缓冲和读取发生在服务器端。ole jet/ace 引擎正在服务器端运行,但读取的文件来自客户端。

我在我的这篇文章中解释了为什么这是一个很大的“腐败”问题:

http://www.kallal.ca/Wan/Wans.html

此外,链接服务器的“模型”和“想法”并不是真正的“跳进跳出”模型。因此,链接服务器更像是一种“维护”类型的过程,您可以在其中设置链接服务器,并且它会保持原样。

因此,在某些多用户系统中,动态链接其他服务(或访问文件)并不是链接服务器背后的真正想法和概念。

也不清楚当这样的系统有多个用户时会发生什么?我想可以创建不同的命名链接服务器,但话又说回来,你的 t-sql 代码必须在“许多”不同的链接服务器上运行。(因此必须更改代码)。

这意味着您的 t-sql ether 必须为相同的 t-sql 代码为“许多”不同的链接服务器工作,或者您始终为链接服务器使用相同的名称。如果您使用相同的名称,那么一个客户端将能够操作。

我对这种方法思考得越多,情况就越糟糕。

在我看来,一种更顺畅的方法是让 Access 将表链接到 SQL 服务器。

如果您使用域身份验证连接到 sql server,那么任何使用 Excel 的用户都可以在 VPN 处于活动状态时“轻松”地对该 sql server 进行一些查询。如果他们启动 SSMS,也是如此。

我会考虑:

使用 SQL Server 登录,因此身份验证用户无法使用 Excel、Access 或其他可以轻松访问 SQL Server 的客户端程序(包括运行 SSMS 的本地客户端)从这些表中提取或查看数据。

不要在链接表中包含 UID/密码。这意味着您不必包含(以纯文本形式)用于此过程的 uid/登录。

不清楚 Access 应用程序是否“隐藏”了访问接口,但即使出于某种原因用户绕过了您的应用程序接口,他们也会在尝试打开现有链接表时收到错误消息。(在您的 VBA 代码执行简单登录之前,这些链接将不起作用)。让客户端“登录”不需要创建任何新的客户端链接(也不需要服务器端)。

我会强烈考虑让客户端做/建立连接,我会尝试用客户端代码更新本地客户端表以消除网络流量,但最糟糕的是通过网络“打开”windows文件. 如果该文件是“打开的”,并且您的连接丢失,那么您将打开的 Windows 文件“实时”剪切,并且刷新本地磁盘缓存等简单的操作将失败并丢失。

如果您使用来自客户端的链接,那么您永远不会通过该网络打开 Windows 文件(只有套接字 ODBC 连接)。

就像将访问应用程序拆分为前端,后端可以在稳定的本地 LAN 上正常工作一样,这样的设置在 WAN + VPN 上的效果很差。

总而言之:你可以让你的设置工作,但我不推荐它。

要找什么:

检查 accDB 文件的独占打开/使用(确保访问未启动或在客户端以独占方式打开 accDB 文件)。如果发生这种情况,则 sql 端将无法链接到该文件。

检查并确保在从该服务器端创建到 accDB 文件的 sql 链接时,该 sql 服务器没有尝试“独占”。(这意味着 Access local 无法打开或使用该文件)。

事实上,我们已经“检查”两端是否会导致此设置失败,这已经是一个故障点,我们(您)必须确保正确完成。

如前所述,我不建议通过这样的网络打开 Windows 文件。

所以检查独家问题(两端)。但是,我会考虑让 Access 建立连接客户端,并执行存储过程。如果在该存储过程中发生的最终更新和检查需要一些数据,则在服务器端进行检查,将生成的所需数据拉到客户端,然后执行本地代码进行更新。

因此,虽然我认为这种设置不可靠,但首先我会检查“独占”问题——两端都需要避免以独占方式打开 accDB 文件。

于 2018-09-20T07:21:36.723 回答
0

我使用这个 sub 从 Access 执行 SQL Server 代码(可以是任何东西,包括对存储过程的调用):

Public Sub ExecuteSQLServerCode(SQL As String)

Dim MyAccessDatabase As DAO.Database
Set MyAccessDatabase = CurrentDb()
With MyAccessDatabase.CreateQueryDef("")
    .Connect = CurrentDb.TableDefs("LinkedTable").Connect
    .SQL = SQL
    .ReturnsRecords = False
    .Execute
    .Close
  End With
MyAccessDatabase.Close
Set MyAccessDatabase = Nothing

End Sub

问题是,在我的情况下,我有一个静态链接到 SQL 服务器的表,我可以从中“借用”连接。

还要记住,对于远程连接,您可能必须创建 SQL 服务器用户帐户,因为 AD 身份验证可能不起作用。

一般来说,我会尝试以下步骤:

  1. 从 AD 计算机创建指向网络内表的“永久”链接。
  2. 测试该链接并使其远程工作。
  3. 使用上述方法在本地测试从 Access 执行 SQL Server 代码。
  4. 远程重复步骤 3。
  5. 尝试用本地动态链接替换永久链接的表。
  6. 远程重复步骤 5。
于 2018-09-21T15:27:35.727 回答