Access Upsizing - свойство «Атрибуты» уже существует для «таблицы» - PullRequest
0 голосов
/ 27 февраля 2020

Я пытаюсь использовать мастер увеличения Access для перемещения данных с Access на SQL Сервер. В настоящее время я нахожусь на этой ошибке, но не могу выяснить, откуда происходит свойство;

Property 'Attributes' already exists for 'table'.

SQL, которое он пытается запустить:

EXEC sp_addextendedproperty N'Attributes', N'2', N'user', N'dbo', N'table', N'table', N'column', N'ID'

Но Таблица в Access не содержит столбец ID, и я не вижу ничего в свойствах таблицы, чтобы указать, почему она пытается добавить свойство для SQL Сервер.

В руководстве по выбору мастера я выбрал не импортировать какие-либо дополнения, такие как индексы, триггеры и т. д. c.

Любые идеи, почему мастер делает это и как остановить его при попытке создать свойства?

В качестве альтернативы, есть ли какие-либо другие инструменты, которые могли бы перемещать данные из Access в MS SQL, сохраняя при этом внешние объекты Access на месте и работая?

1 Ответ

2 голосов
/ 27 февраля 2020

У мастера изменения размера были недостатки с самого начала, и он был удален из последних версий Access. Я рекомендую не использовать его.

Лично у меня есть форма, которая обрабатывает меня. Это форма с двумя текстовыми полями с именами ConStr и adoString (первое содержит строку подключения для использования Access, включая префикс ODBC;, второе содержит либо строку ODB C, либо строку OLEDB для ADO для use), кнопка с именем ToSQL и список с именем lstTables. Он содержит следующий код:

Для заполнения локальных таблиц при загрузке:

Private Sub Form_Load()
    lstTables.RowSourceType = "Value List"
    Dim iterator As Variant
    For Each iterator In CurrentDb.TableDefs
        If Not iterator.NAME Like "MSys*" And Not iterator.NAME Like "~*" Then
            lstTables.AddItem iterator.NAME
        End If
    Next iterator
End Sub

Чтобы переместить таблицы на сервер SQL:

Private Sub ToSQL_Click()
    Dim i1 As Variant
    Dim td As DAO.TableDef
    Dim NewTd As DAO.TableDef
    Dim db As DAO.Database
    Set db = CurrentDb
    'Iterate through all selected tables
    With lstTables
        For Each i1 In .ItemsSelected
            Set td = db.TableDefs(.ItemData(i1))
            'Add a primary key if none exist
            'AddPK td 'Not providing this one as it's not part of normal upscaling
            'Move the table to SQL server
            DoCmd.TransferDatabase acExport, "ODBC Database", _
            conStr _
            , acTable, .ItemData(i1), .ItemData(i1)
            'Rename the local table to name_local
            td.NAME = .ItemData(i1) & "_local"
            'Change the remote table to the schema specified
            'ADOChangeSchema GetDefaultSchema(), "mySchema", .ItemData(i1) 'Not providing this one as it's not part of normal upscaling
            'Set the primary key in SQL server
            ADOAddPrimaryKey GetDefaultSchema(), .ItemData(i1), GetPKName(td)
            'Create a new linked table, linking to the remote table
            Set NewTd = db.CreateTableDef(.ItemData(i1), 0, GetDefaultSchema() & .ItemData(i1), conStr)
            db.TableDefs.Append NewTd
        Next i1
    End With
End Sub

И некоторые вспомогательные функции:

Public Sub ADOAddPrimaryKey(SchemaName As String, tableName As String, FieldName As String)
On Error GoTo SetNotNull
    Dim conn As Object
    Set conn = CreateObject("ADODB.Connection")
    Dim cmd As Object
    Set cmd = CreateObject("ADODB.Command")
    conn.Open adoString
    cmd.ActiveConnection = conn
    cmd.CommandText = "ALTER TABLE " & SchemaName & ".[" & tableName & "] ADD CONSTRAINT [" & tableName & "_PK] PRIMARY KEY CLUSTERED([" & FieldName & "]);"
    cmd.Execute
    Exit Sub
SetNotNull:
    If Err.Number = -2147217900 Then
        cmd.CommandText = "ALTER TABLE " & SchemaName & ".[" & tableName & "] ALTER COLUMN [" & FieldName & "] INTEGER NOT NULL"
        cmd.Execute
        cmd.CommandText = "ALTER TABLE " & SchemaName & ".[" & tableName & "] ADD CONSTRAINT [" & tableName & "_PK] PRIMARY KEY CLUSTERED([" & FieldName & "]);"
        cmd.Execute
    Else
        Err.Raise Err.Number
    End If
End Sub

Public Function GetDefaultSchema() As String
    Dim conn As Object
    Set conn = CreateObject("ADODB.Connection")
    Dim rs As Object
    conn.Open adoString
    Set rs = conn.Execute("SELECT SCHEMA_NAME()")
    GetDefaultSchema = rs.Fields(0)
End Function

Public Function GetPKName(td As DAO.TableDef) As String
'Returns the name of the first field included in the primary key (WARNING! Doesn't return all fields for composite primary keys!)
    Dim idx As DAO.Index
    For Each idx In td.Indexes
        If idx.Primary Then
            GetPKName = idx.Fields(0).NAME
            Exit Function
        End If
    Next idx
End Function

Эта форма сохраняет только данные и первичный ключ и делает несколько предположений (слишком ленив, чтобы их избежать), таких как: имена таблиц не содержат квадратных скобок, нет составные первичные ключи, схема таблицы безопасна для использования в операторах SQL, нет полей вложений или многозначных полей и нет отношений (была версия, в которой сохранились отношения, но ... я, честно говоря, не знаю, где сейчас).

Также оставляет переименованную копию локальной таблицы. Затем оригинальная версия тестирует случайные строки размером 1 КБ, чтобы проверить, является ли содержимое идентичным, но я для краткости опускаю это.

Вы можете использовать это как отправную точку, так как может потребоваться настройка в соответствии с вашими c потребности.

...