Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Làm cách nào để tạo một Bảng được liên kết ODBC theo cách lập trình đến Dạng xem Máy chủ SQL và nó có thể chỉnh sửa được không?

Không phải vì nó không có DSN, mà vì bạn đã tạo nó qua VBA. Nếu bạn liên kết chế độ xem qua Access GUI, nó sẽ yêu cầu bạn cung cấp khóa chính.

Nhưng thông qua VBA, nó không biết khóa chính, vì vậy chế độ xem được liên kết không thể cập nhật được. Với một bảng, Access sẽ tự động lấy khóa chính thông qua ODBC, vì vậy bảng hoạt động.

Giải pháp: đặt khóa chính sau khi liên kết chế độ xem qua VBA:

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

Nếu bạn có nhiều chế độ xem và liên kết lại chúng thường xuyên (ví dụ:đi từ nhà phát triển đến cơ sở dữ liệu sản xuất), thì việc mã hóa tên và PK của chúng trở nên không thực tế. Tôi đã viết một hàm để truy xuất tất cả các chỉ mục khóa chính từ các chế độ xem được liên kết và tạo lại chúng sau khi liên kết.
Nếu bạn muốn, tôi có thể tìm hiểu nó.

Chỉnh sửa:
Đây là những gì tôi 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

Để liên kết bảng hoặc xem lần đầu tiên , Tôi sử dụng cái này (strTable là tên bảng / chế độ xem):

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

Đối với bảng, khóa chính (PK) được xác định tự động. Đối với một chế độ xem, tôi nhận được cửa sổ hộp thoại Access để chỉ định PK, giống như khi tôi liên kết chế độ xem theo cách thủ công.
Thông tin PK được lưu trữ trong đối tượng TableDef cho chế độ xem được liên kết, vì vậy tôi không bao giờ phải mã hóa nó ở bất kỳ đâu. .

Để lưu trữ thông tin PK cho tất cả các dạng xem được liên kết, tôi có bảng này (đó là bảng cục bộ trong giao diện người dùng Access để đơn giản hóa):

t_LinkedViewPK
    ViewName        Text(100)
    IndexFields     Text(255)

và chức năng này. Tất cả Chế độ xem (và chỉ Chế độ xem) được gọi là "v_ *", vì vậy tôi có thể liệt kê chúng theo tên.
Tôi thực sự không chắc liệu bạn có thể xác định từ một đối tượng TableDef xem nó trỏ đến bảng hay chế độ xem hay không.

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

Khi tôi thực hiện các thay đổi đối với cấu trúc bảng hoặc chế độ xem hoặc thay đổi cơ sở dữ liệu nguồn (điều này được thực hiện bằng cách thay đổi đầu ra của ODBC_String() ), Tôi gọi chức năng này:

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

Lưu ý:
Thay vì bảng t_LinkedViewPK , một đối tượng từ điển có thể được sử dụng. Nhưng trong khi phát triển điều này, sẽ rất hữu ích nếu có nó như một bảng thực tế.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Thư viện gốc sqljdbc_auth.dll đã được tải trong một trình tải lớp khác

  2. datetime2 so với datetimeoffset trong SQL Server:Sự khác biệt là gì?

  3. Thực thi sp_msforeachdb trong ứng dụng Java

  4. @@ LỖI và / hoặc THỬ - CATCH

  5. Làm cách nào để tìm cổng đang chạy của SQL Server?