Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как програмно да създадете ODBC свързана таблица към изглед на SQL сървър и да може да бъде редактирана?

Не защото е без DSN, а защото сте го създали чрез VBA. Ако свържете изгледа чрез GUI на Access, той ви иска първичен ключ.

Но чрез VBA той не познава първичния ключ, така че свързаният изглед не може да се актуализира. С таблица Access получава първичния ключ автоматично чрез ODBC, така че таблицата работи.

Решение: задайте първичния ключ след свързване на изгледа чрез VBA:

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

Ако имате много изгледи и ги свързвате редовно (например преминавате от dev към производствена база данни), става непрактично да се кодират твърдо техните имена и PK. Написах функция за извличане на всички индекси на първичен ключ от свързани изгледи и повторното им създаване след свързването.
Ако искате, мога да го изровя.

Редактиране:
Ето какво правя:

' 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 е името на таблица/изглед):

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

За таблици първичният ключ (PK) се определя автоматично. За изглед получавам диалогов прозорец на Access, за да посоча PK, както ако свържа изгледа ръчно.
Информацията за PK се съхранява в обекта TableDef за свързания изглед, така че никога не ми се налага да я кодирам някъде .

За да съхранявам PK информацията за всички свързани изгледи, имам тази таблица (това е локална таблица във интерфейса на Access за простота):

t_LinkedViewPK
    ViewName        Text(100)
    IndexFields     Text(255)

и тази функция. Всички изгледи (и само Views) се наричат ​​"v_*", така че мога да ги изброя по име.
Всъщност не съм сигурен дали можете да определите от обект TableDef дали той сочи към таблица или изглед.

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() ), наричам тази функция:

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 , може да се използва речников обект. Но докато разработвахме това, беше много полезно да го имам като действителна таблица.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Защо (и как) да разделяте колона с помощта на master..spt_values?

  2. Грешка на SQL Server при команда за актуализиране - Възникна сериозна грешка при текущата команда

  3. Върнете всички външни ключове, които препращат към дадена таблица в SQL Server

  4. Предимства на производителността на SQL Server 2016 Enterprise Edition

  5. Производителност на SQL сървър TOP CPU заявка -1