我正在使用Access前端表单转换Access应用程序以使用SQL Server后端。听起来很有趣我知道。
此应用程序需要对同一服务器上的2个SQL Server数据库进行数据访问。有许多内联sql查询字符串尝试在单个ADODB连接上同时连接到两个数据库。这是失败的,因为我期待记录但没有返回。
解决此问题的最佳方法是什么?有没有办法使用这些sql字符串或必须将它们都转换为存储过程?谢谢你的帮助。
以下是一些代码:
Dim conn As ADODB.Connection
Set conn = New ADODB.Connection
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
With conn
.Provider = "sqlncli11"
.ConnectionString = "Server=[MY_SERVER];Database=[MY_DATABASE];User Id=sa; Password=password;"
.Open
End With
Dim str As String
str = "SELECT TABLE_DB1.Parent_Item_No FROM TABLE_DB1 INNER JOIN [DB2].[dbo].TABLE_DB2 ON (TABLE_DB1.Comp_Item_No = " & _
"TABLE_DB2.item_no) AND (TABLE_DB1.Loc = TABLE_DB2.loc) " & _
"GROUP BY TABLE_DB1.Parent_Item_No " & _
"HAVING (((TABLE_DB1.Parent_Item_No)='" & str_Assembly & "'));"
With rst
.Open str, conn, adOpenKeyset, adLockOptimistic ' this fails to return records
If .RecordCount > 0 Then
'Do Stuff
Else
'Do Other Stuff
End If
End With
答案 0 :(得分:1)
您只需查看RecordCount
。看看这个:slxdeveloper.com/page.aspx?action=viewarticle&articleid=33有些记录集类型没有填充RecordCount属性(尽管adOpenKeyset应该)。如果您使用While Not .EOF和.BOF会发生什么?您的代码中RecordCount的实际值是多少?
答案 1 :(得分:0)
是否可以从SQL运行保存到访问文件的查询?我只有将数据直接导入访问权限。我在设置ODBC数据库并转到数据时确实取得了成功 - >获取外部数据 - >来自其他来源 - >来自微软查询
我自己成功使用的另一种方法是使用microsoft的power query add-on。 https://www.microsoft.com/en-us/download/details.aspx?id=39379
尽管如此,我最常做的还是使用SQL导入/导出工具。我没有屏幕截图或具体说明,因为我现在没有工作,但这可以直接写入文本文件,Access数据库,所有内容。我太爱了。获得正确的驱动程序肯定是一个循环。如果您使用的是64位并且遇到问题,那么这就是您需要的驱动程序。 http://www.microsoft.com/en-us/download/details.aspx?id=13255 我所做的是:
我个人仍然使用导入导出工具进行各种大小的传输,因为它很难获得所有正确的驱动程序并让SQL变得像我想要的那样。 (并且没有管理员权限我厌倦了问我的老板)。
我希望其中一个解决方案能为您提供帮助!
答案 2 :(得分:0)
我已经勾勒出更合适的解决方案和快速解决方案......
更合适的修复方法是数据层模式。这个修复有很多,它可能需要一些应用程序结构更改。这在另一个问题中进行了深入讨论: Data Access Layer design patterns
一个非常简单的解决方法是使用Access Linked表。链接表的工作方式与普通的Access表类似,只是数据在SQL Server上存储和更新。它基本上是一个内置的SQL Server数据访问层。它不是一个优雅的解决方案,但它可以立即启动并运行。更多信息可以在这里找到: https://support.office.com/en-us/article/Import-or-link-to-SQL-Server-data-a5a3b4eb-57b9-45a0-b732-77bc6089b84e#bm2
使用链接表要注意的是,某些访问查询和表单在过滤之前会检索所有记录,并且可以锁定表,这样如果您拥有大量数据和大量用户,最终可能会遇到一些性能问题。
答案 3 :(得分:0)
考虑使用SQL Server SYNONYM
功能将一个数据库中的对象的别名添加到另一个数据库中。然后只需更新所有查询即可使用一个数据库。
此外,您可以将两个数据库与每个数据库合并,或者将其中一个数据库合并到一个新模式中以使它们分开。如果数据库中有大量存储过程,视图和函数,这可能很难。这可能是一个可怕的答案,但也可能确实这两个数据库本来就不应该是分开的。
答案 4 :(得分:0)
在INNER JOIN
中,您使用DatabaseName.Schema.
:
... FROM TABLE_DB1 INNER JOIN [DB2].[dbo].TABLE_DB2 ...
但是你没有在发生TABLE_DB2
的其他地方这样做。
所以你要么改变这个:
ON (TABLE_DB1.Comp_Item_No = TABLE_DB2.item_no) AND (TABLE_DB1.Loc = TABLE_DB2.loc)
......对此:
ON (TABLE_DB1.Comp_Item_No = [DB2].[dbo].TABLE_DB2.item_no) AND (TABLE_DB1.Loc = [DB2].[dbo].TABLE_DB2.loc)
或(我更喜欢)您可以在FROM
子句中为表名使用别名:
... FROM TABLE_DB1 t1 INNER JOIN [DB2].[dbo].TABLE_DB2 t2...
...然后你在其他地方使用别名:
str = "SELECT t1.Parent_Item_No FROM TABLE_DB1 t1 INNER JOIN [DB2].[dbo].TABLE_DB2 t2 ON (t1.Comp_Item_No = " & _
"t2.item_no) AND (t1.Loc = t2.loc) " & _
"GROUP BY t1.Parent_Item_No " & _
"HAVING (((t1.Parent_Item_No)='" & str_Assembly & "'));"
如果通过ADO连接到SQL Server,则直接连接到一个数据库 - 连接字符串中的数据库:
.ConnectionString = "Server=[MY_SERVER];Database=[MY_DATABASE];User Id=sa; Password=password;"
因此,在您的情况下,您要连接的数据库名为MY_DATABASE
。您通过ADO执行的任何SQL都将转到该数据库。
如果您需要从同一服务器上其他数据库获取数据,则需要在{strong>所有位置使用DatabaseName.Schema.
作为名称的前缀
所以我们假设我们有:
MY_TABLE
MY_DATABASE
OTHER_TABLE
中的表OTHER_DATABASE
dbo
(SQL Server中的默认值) 使用上面的连接字符串(连接到MY_DATABASE
),您可以按如下方式加入它们:
select *
from MY_TABLE
inner join OTHER_DATABASE.dbo.OTHER_TABLE
on MY_TABLE.SomeColumn = OTHER_DATABASE.dbo.OTHER_TABLE.OtherColumn
where OTHER_DATABASE.dbo.OTHER_TABLE.EvenAnotherColumn = 'foo'
请参阅?在我使用OTHER_TABLE
的任何地方,我都用OTHER_DATABASE.dbo.
作为前缀。
PS:
使用sa
用户连接到具有应用程序的数据库是bad practice。 sa
用户拥有最高权限
您应该使用Windows身份验证或为您的应用程序创建专用的SQL用户。
答案 5 :(得分:0)
考虑将SQL存储在传递查询中而不是VBA代码中。您可以使用传递查询的querydef对象的.sql属性副本来应用过滤器,并使用它们在运行时在表单中输入的条件对其进行修改。