sql >> Databáze >  >> RDS >> Sqlserver

Jak programově vytvořit propojenou tabulku ODBC se zobrazením serveru SQL a zajistit, aby byla upravitelná?

Není to proto, že je bez DSN, ale proto, že jste jej vytvořili pomocí VBA. Pokud propojíte pohled přes Access GUI, požádá vás o primární klíč.

Ale přes VBA nezná primární klíč, takže propojené zobrazení není aktualizovatelné. S tabulkou získá Access primární klíč automaticky prostřednictvím ODBC, takže tabulka funguje.

Řešení: nastavte primární klíč po propojení pohledu přes VBA:

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

Pokud máte mnoho pohledů a pravidelně je znovu propojujete (např. přecházíte z vývojářské do produkční databáze), stává se nepraktické pevně kódovat jejich názvy a PK. Napsal jsem funkci pro načtení všech indexů primárního klíče z propojených pohledů a jejich opětovné vytvoření po propojení.
Pokud chcete, mohu to vykopat.

Upravit:
Tohle dělám:

' 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

Chcete-li propojit tabulku nebo zobrazit poprvé , používám toto (strTable je název tabulky/zobrazení):

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

U tabulek je primární klíč (PK) určen automaticky. Pro pohled se mi zobrazí dialogové okno Access pro zadání PK, stejně jako když pohled propojím ručně.
Informace o PK jsou uloženy v objektu TableDef pro propojený pohled, takže je nikdy nemusím nikde napevno kódovat .

Pro uložení informací o PK pro všechna propojená zobrazení mám tuto tabulku (pro zjednodušení je to místní tabulka v rozhraní Access):

t_LinkedViewPK
    ViewName        Text(100)
    IndexFields     Text(255)

a tato funkce. Všechna zobrazení (a pouze Pohledy) se nazývají "v_*", takže je mohu uvést podle názvu.
Vlastně si nejsem jistý, zda z objektu TableDef můžete určit, zda ukazuje na tabulku nebo pohled.

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

Když provádím změny ve strukturách tabulky nebo zobrazení nebo měním zdrojovou databázi (to se provádí změnou výstupu ODBC_String() ), nazývám tuto funkci:

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

Poznámka:
Namísto tabulky t_LinkedViewPK , lze použít objekt slovníku. Ale při vývoji toho bylo velmi užitečné mít to jako skutečnou tabulku.



  1. Rozdělení logické replikace s PostgreSQL 13

  2. Příkazy SQL

  3. Jak udělit přístup k zobrazením v$ (v$session,v$instance)

  4. Příklady převodu ‚date‘ na ‚datetime2‘ v SQL Server (T-SQL)