【问题标题】:How to append data from a SQL Server table to an Access table?如何将 SQL Server 表中的数据附加到 Access 表中?
【发布时间】:2019-01-18 16:57:45
【问题描述】:

我正在尝试在 MS Access 中编写查询以打开与本地 SQL Server 的连接,然后将选择表导入 MS Access。

我的代码一直运行到Cn.Execute 语句。我明白了

运行时错误“-2471765 (80040e37)”[Microsoft][ODBC SQL Server Driver][SQL Server] 无效的对象名称“dbo_SQLServertable”。

我需要导入其他表,因此我需要一个在我更改表名时可以使用的代码。

Private Sub Command28_Click()    
        
    Dim Cn As ADODB.Connection
    Dim Server_Name As String
    im Database_Name As String
    Dim User_ID As String
    Dim Password As String
    Dim SQLStr As String
    Dim rs As ADODB.Recordset
    Set rs = New ADODB.Recordset
    
    Server_Name = "" ' Enter your server name here
    Database_Name = "Test" ' Enter your database name here
    User_ID = "" ' enter your user ID here
    Password = "" ' Enter your password here
       
    Set Cn = New ADODB.Connection
    Cn.Open "Driver={SQL Server};Server=" & Server_Name & ";Database=" & Database_Name & ";"
    
    Cn.Execute "INSERT INTO Access Table SELECT dbo_SQLServerTable.* FROM dbo_SQLServerTable;"
    
    Set rs = Nothing
    Cn.Close
    Set Cn = Nothing

我进行了更改并收到一条新的错误消息

运行时错误 '-2147216900 (80040e14)' [Microsoft][ODBC SQL Server Driver][SQL Server] 无法将值 NULL 插入列 'DiagnosisOrdinal',表 'Office.dbo.Test' 列不允许空值。插入失败。

我的插入语句似乎仍在引用(或尝试引用)SQL 服务器中的表。 'Office' 是我从中提取的数据库名称。

我是否必须关闭连接,然后将数据粘贴到我的本地 Access 表中?如果我想对多个表执行此操作,我是否必须重新打开和关闭连接?

我将执行语句从

Cn.Execute "INSERT INTO Access Table SELECT dbo_SQLServerTable.* FROM dbo_SQLServerTable;"

Cn.Execute "INSERT INTO Test(VisitID, Provider) SELECT VisitID, Provider FROM dbo.SQLServerTable;"

【问题讨论】:

  • 表名真的是“dbo_SQLServerTable”吗?可能应该是“dbo.SQLServerTable”。这是第一个错误。可能您会收到另一条关于 "Access Table" 的错误消息。将表格放入括号中,如[Access Table]。
  • 另外,如果您没有在插入语句中提供要插入的列,则意味着 [Access Table] 和 SQLServerTable 表具有相同的表结构。这是正确的吗?
  • 目标表是否存在于Access中,或者您打算访问以从sql中创建表?
  • 我首先从 SQL Server 手动导入该表,因为我不想在我的 VBA 代码中列出所有字段。我以为我可以只运行“SELECT *”,但也许不是这样
  • 你可以。基本问题仍然存在,您是要创建新表还是追加到现有表中?

标签: sql sql-server ms-access vba


【解决方案1】:

我能想到的最少代码是使用传递查询。

设置对相关服务器数据库的 PT 查询。

那么您在 access 中创建新表的代码如下所示:

Sub TestImport()

  Dim strSQL     As String
  
  With CurrentDb.QueryDefs("qryPassR")
     .SQL = "select * from tblHotels"
  End With
  
  Dim strLocalTable  As String
  
  strLocalTable = "zoo"
  
  CurrentDb.Execute "select * into " & strLocalTable & " FROM qryPassR"
  
End Sub

上面当然假设您在创建 PT 查询时设置了与 sql server(一个数据库)的连接。上述方法很好,因为您不会在代码中乱用连接字符串。

但是,鉴于您需要(想要)指定数据库(以及可能的服务器),那么上面就变成了这样:

Sub TestImport2()

  Dim strSQL           As String
  Dim strServer        As String
  Dim strDatabase      As String
  Dim strUser          As String
  Dim strPass          As String
  
  strServer = ""
  strDatabse = ""
  strUser = ""
  strPass = ""
  
  Dim strLocalTable       As String
  Dim strServerTable      As String
  
  With CurrentDb.QueryDefs("qryPassR")
     .Connect = dbCon(strServer, strDatabase, strUser, strPass)
     .SQL = "select * from " & strServerAble
  End With
  
  CurrentDb.Execute "select * into " & strLocalTable & " FROM qryPassR"
  
End Sub

上面使用了一个“方便”的函数来创建你的连接字符串。

那个函数如下:

Public Function dbCon(ServerName As String, _
                     DataBaseName As String, _
                     Optional UserID As String = "", _
                     Optional USERpw As String, _
                     Optional APP As String = "Office 2010", _
                     Optional WSID As String = "Import") As String

   ' returns a SQL server conneciton string
   
  dbCon = "ODBC;DRIVER=" & SQLDRIVER & ";" & _
          "SERVER=" & ServerName & ";" & _
          "DATABASE=" & DataBaseName & ";"
          If UserID <> "" Then
             dbCon = dbCon & "UID=" & UserID & ";" & "PWD=" & USERpw & ";"
          End If
          dbCon = dbCon & _
          "APP=" & APP & ";" & _
          "WSID=" & WSID & ";" & _
          "Network=DBMSSOCN"

End Function

编辑

Poster 要求解决方案将数据附加到 EXISTING 表中。

在这种情况下,只需更改以下内容:

  CurrentDb.Execute "select * into " & strLocalTable & " FROM qryPassR"

  CurrentDb.Execute "INSERT INTO " & strLocalTable & " SELECT * FROM qryPassR"

【讨论】:

  • 嗨 Albert,我尝试运行代码,但它说您的“方便”函数 sytanx 无效。我确信我试图错误地使用它。作为参考,我试图将 VB 放在一个按钮后面,以允许最终用户通过单击、清除数据库、重新导入,然后允许他们使用新数据来“刷新”数据。该代码在私人按钮子中不起作用吗?此外,您能否提供更多关于直通查询的参考?我从来没有和那些合作过!
  • 当然,但是您需要将 dbCon() 函数放置在标准代码模块(而不是表单模块)中。我想您可以将第二个函数 dbCon() 放在表单代码模块中,但该函数可能会在您的代码中“到处”使用。
  • 要创建 PT 查询,请启动访问查询生成器。创建一个新查询,然后在功能区中点击传递图标。此时您可以保存查询,因为我们正在查询中设置 sql。如果您没有“经常”更改源数据库的要求,那么您将不会在代码中设置 PT 查询的连接(就像我们正在做的那样)。 PT 查询的连接将设置为与链接表的连接相同。我假设您有一些链接到 sql server 的表 - 因此您可以在重新链接代码中包含 PT 查询。
  • 要设置 PT 查询的连接,点击功能区中的属性表按钮。然后在工作表中,选择 ODBC connect str。点击 [...] 将启动您用于所有链接表的相同 ODBC 连接管理器。但是,如前所述,您的情况是“罕见的”,因为您的 PT 查询源会经常更改 - 这不是大多数应用程序的正常用例。
  • Albert,非常感谢您的帮助。我已将此答案标记为正确。最终,我确定我只需要连接到一台服务器,因此我能够在直通查询中设置连接。奇迹般有效!最后一个问题,我假设 PT 查询创建了一个临时连接,是吗?似乎 PT 作为一个名字意味着......再次非常感谢!
【解决方案2】:

您不希望 SELECT 中的表前缀来自 SQL 表。只需执行SELECT * FROM dbo_SQLServerTable; 最佳实践,但最好不要使用SELECT *,而是指定列以防表架构发生变化。

【讨论】:

  • 还有 @ZekiGumus 对 Access 表名的评价。
  • 我的访问表中已经有了相同的表结构?不过,似乎我仍然需要拼出所有字段?
  • 这不是必需的,只是需要注意的事情。有时列名会被切换并使用 SELECT * 最终会导致错误,或者更糟糕的是,会将内容放入错误的列中。
【解决方案3】:

有一些针对这个特定问题的建议

  1. 通过查询
  2. 来自 SQL Server 的链接表。您将不得不设置一个不太难的 dsn 文件。
  3. 或者直接在SQL Server中处理Insert into Access from SQL Server
  4. 通过 VBA 进行 ODBC 连接(您在做什么,看起来最复杂)

所有这些方法都可以正常工作。我建议使用链接表,这样你就不会重复数据,但那是你的一个想法,因为我不知道项目的要求。

【讨论】:

    【解决方案4】:

    dbo_SQLServerTable 是 Access 表名,而不是 SQL Server 表名。因为您已经创建了链接表 dbo_SQLServerTable,所以可以使用以下 VBA 代码。

    Currentproject.connection.execute "INSERT INTO MyAccessTable(fld1, fld2, fld3) SELECT fld1, fld2,fld3 FROM dbo_SQLServerTable"
    

    无需在 VBA 代码中创建连接对象。 Currentproject.connection 始终可供引用。

    【讨论】:

    • 感谢您的回复!那么如果这是我运行的唯一 SQL Server 实例,那么前面的所有代码行都可以取出来吗?
    • 是的。那是对的。链接表使您可以访问 SQL 服务器表。您可以使用我的代码,也可以创建一个 Append 查询,在 Access 中称为 Action Query。
    • 这里的重点是如果表已经链接,那么你可以执行追加查询。但是,您的问题表明有问题的 sql 表没有链接。因此,您可以在代码中创建到 SQL 服务器表的链接表,也可以使用 PT 查询。一旦设置了链接表(或 PT 查询),您就可以执行简单的追加查询。如果您要用于附加到本地表的相关 sql 表已经存在,那么您可以使用 CurrentProject.Conneciton 而无需使用 PT 方法。
    猜你喜欢
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多