如何以编程方式创建到SQL Server视图的ODBC链接表并使其可编辑? [英] How to programmatically create an ODBC Linked Table to a SQL Server View and have it be editable?

查看:80
本文介绍了如何以编程方式创建到SQL Server视图的ODBC链接表并使其可编辑?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用向导创建到SQL Server的DSN连接时,可以将其链接到视图.在这种情况下,Access会将其识别为可编辑表.

When I create a DSN connection to SQL Server using the wizard, I am able to link it to a view. In this case, Access recognizes it as an editable table.

但是,如果我使用无DSN连接到使用vba代码的视图( https://support.microsoft.com/zh-cn/kb/892490 ),它作为不可更新的表链接.

But if I use a DSN-less connection to a view using vba code (Method 1 from https://support.microsoft.com/en-us/kb/892490), it is linked as a table that is NOT updatable.

我不知道为什么会有区别,但是如何连接到SQL Server中的视图(作为表或Access中的查询)并使其可更新?

I don't know why there is a difference, but how can I make a connection to a view in SQL Server (either as a table or a query in Access) and have it be updatable?

当我使用SQL Server中的表而不是视图建立无DSN的连接时,它在Access中是可更新的.我猜想我的问题与没有唯一ID的视图有关,但是我很困惑为什么DSN连接可以更新而没有DSN的视图不能更新.

When I make a DSN-less connection using a table in SQL Server rather than a view, it is updatable in Access. I would have guessed my problem has to do with views not having a unique ID, but I'm confused why a DSN connection can be updatable while DSN-less cannot.

推荐答案

不是因为它没有DSN,而是因为它是通过VBA创建的.如果通过Access GUI链接视图,它将要求您提供主键.

It's not because it's DSN-less, but because you created it via VBA. If you link the view via the Access GUI, it asks you for the primary key.

但是通过VBA,它不知道主键,因此链接的视图不可更新.对于表,Access会通过ODBC自动获取主键,因此该表可以工作.

But via VBA, it doesn't know the primary key, so the linked view is not updateable. With a table, Access gets the primary key automatically via ODBC, so the table works.

解决方案::通过VBA链接视图后,设置主键:

Solution: set the primary key after linking the view via VBA:

S = "CREATE INDEX PrimaryKey ON MyViewName (MyPrimaryKeyField) WITH PRIMARY"
DB.Execute S

如果您有很多视图,并定期重新链接它们(例如,从开发人员转到生产数据库),则对它们的名称和PK进行硬编码就变得不切实际.我编写了一个函数,用于从链接的视图中检索所有主键索引,并在链接后重新创建它们.
如果您愿意,我可以进行挖掘.

If you have many views, and re-link them regularly (e.g. going from dev to production database), it becomes impractical to hardcode their names and PKs. I wrote a function to retrieve all primary key indexes from linked views, and re-create them after linking.
If you want, I can dig it up.

修改:
这就是我要做的:


This is what I do:

' This function returns the full DSN-less connect string
Private Function ODBC_String() As String
    ' In the real world there are several constants and variable in there
    ODBC_String = "ODBC;DRIVER={SQL Server};SERVER=aaa;DATABASE=bbb;UID=ccc;PWD=ccc;LANGUAGE=us_english;TRUSTED_CONNECTION=No"
End Function

首次链接表或视图,我使用了此方法(strTable是表/视图的名称):

To link a table or view the first time, I use this (strTable is the table/view name):

DoCmd.TransferDatabase acLink, "ODBC", ODBC_String(), acTable, strTable, strTable, False, True

对于表,主键(PK)是自动确定的.对于视图,我将获得访问"对话框窗口以指定PK,就像我手动链接视图一样.
PK信息存储在TableDef对象中的链接视图中,因此我不必在任何地方对其进行硬编码.

For tables, the primary key (PK) is determined automatically. For a view, I get the Access dialog window to specify the PK, same as if I link the view manually.
The PK information is stored in the TableDef object for the linked view, so I never have to hardcode it anywhere.

要存储所有链接视图的PK信息,我有此表(为简单起见,它是Access前端中的本地表):

To store the PK information for all linked views, I have this table (it's a local table in the Access frontend for simplicity):

t_LinkedViewPK
    ViewName        Text(100)
    IndexFields     Text(255)

和此功能.所有视图(仅 视图)都称为"v_ *",因此我可以按名称列出它们.
我实际上不确定是否可以从TableDef对象确定它是否指向表或视图.

and this function. All Views (and only Views) are called "v_*", so I can list them by name.
I'm actually not sure if you can determine from a TableDef object whether it points to a table or view.

Private Sub StoreViewPKs()

    Dim TD As TableDef
    Dim idx As index
    Dim FD As Field
    Dim RS As Recordset
    Dim S As String

    ' DB is a global Database object, set to CurrentDB
    DB.Execute "Delete * From t_LinkedViewPK"
    Set RS = DB.OpenRecordset("t_LinkedViewPK")

    For Each TD In DB.TableDefs
        If TD.Name Like "v_*" Then
            ' Views must have exactly one index. If not: panic!
            If TD.Indexes.Count <> 1 Then
                MsgBox "View " & TD.Name & " has " & TD.Indexes.Count & " Indizes.", vbCritical
                Stop
            End If

            Set idx = TD.Indexes(0)
            ' Build field list (the index may contain multiple fields)
            S = ""
            For Each FD In idx.Fields
                If S <> "" Then S = S & ", "
                S = S & FD.Name
            Next FD

            RS.AddNew
            RS!ViewName = TD.Name
            RS!IndexFields = S
            RS.Update
        End If
    Next TD

    RS.Close

End Sub

当我更改表或视图结构或更改源数据库时(通过更改ODBC_String()的输出来完成),我调用此函数:

When I make changes to table or view structures, or change the source database (this is done by changing the output of ODBC_String()), I call this function:

Public Function Sql_RefreshTables()

    Dim TD As TableDef
    Dim S As String
    Dim IdxFlds As String

    DB.TableDefs.Refresh

    ' save current Indizes for Views (recreated after .RefreshLink)
    Call StoreViewPKs

    For Each TD In DB.TableDefs
        If Len(TD.Connect) > 0 Then
            If Left(TD.Connect, 5) = "ODBC;" Then

                Debug.Print "Updating " & TD.Name
                TD.Connect = ODBC_String()
                TD.RefreshLink

                ' View?
                If TD.Name Like "v_*" Then
                    IdxFlds = Nz(DLookup("IndexFields", "t_LinkedViewPK", "ViewName = '" & TD.Name & "'"))
                    If IdxFlds = "" Then Stop

                    ' Create PK
                    S = "CREATE INDEX PrimaryKey ON " & TD.Name & " (" & IdxFlds & ") WITH PRIMARY"
                    DB.Execute S
                End If

            End If
        End If
    Next TD

    DB.TableDefs.Refresh

End Function

注意:
代替表t_LinkedViewPK,可以使用字典对象.但是在进行开发时,将其作为实际表非常有用.

Note:
Instead of the table t_LinkedViewPK, a dictionary object could be used. But while developing this, it was very useful to have it as an actual table.

这篇关于如何以编程方式创建到SQL Server视图的ODBC链接表并使其可编辑?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆