Run-time error 3027. База данных доступна только для чтения.

Работа VB и СУБД (Access, MSSQL, MySQL, Oracle и пр.)
Правила форума
При создании новой темы не забывайте указывать используемую СУБД.
lomaster
Начинающий
Начинающий
 
Сообщения: 21
Зарегистрирован: 02.11.2004 (Вт) 13:36

Run-time error 3027. База данных доступна только для чтения.

Сообщение lomaster » 17.11.2004 (Ср) 10:13

Никакак не могу сделать UPDATE базы данных :(
Код: Выделить всё
Sub Database_Update()

    Dim db As Database
    Dim ws As Workspace
    Dim rst As Recordset
    Dim sConnection As String
    Dim sAdr As String
    Dim i As Integer
    Dim iReplaceCount As Integer

    Set ws = DBEngine.CreateWorkspace("myName", "UID", "", dbUseODBC)
   
    sConnection = "ODBC;DSN=ORA;UID=lomaster;PWD=123;SERVER=oracle;"
    Set db = ws.OpenDatabase("", False, False, sConnection)
    Set rst = db.OpenRecordset("select code, adr from person where em = '28'")

    i = 1
    iReplaceCount = 0
    With rst
        Do
            sAdr = .Fields("adr").Value
            If IsNumeric(Left$(sAdr, 6)) Then
                .Edit
                .Fields("ps_adr_1").Value = Right$(sAdr, Len(sAdr) - 7)
                iReplaceCount = iReplaceCount + 1
            End If
            .MoveNext
            i = i + 1
        Loop While Not .EOF
    End With
   
    rst.Update
    rst.Close
    db.Close
    ws.Close
   
    MsgBox "Обработано записей: " & i - 1 & vbNewLine & "Изменено полей: " & iReplaceCount
End Sub

Возникает ошибка в строчке с .Edit
Run-time error '3027'
Обновление невозможно. База данных или объект доступны только для чтения.

Как побороть ???
Пробовал подключить другую базу (не Oracle, а просто DBF) - результат аналогичный :(
Что я делаю не так ???

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 17.11.2004 (Ср) 17:53

Работать с Огакулом через DAO - это сильно... Ни разу такого не видел.

В том же ADO в свойствах соединения указывается тип твоего доступа - от полного Read-Only до эксклюзивного делаю-что-хочу. Покопай справку по своим методам (если я ничего не напутал) .OpenDatabase() и .OpenRecordset(). Не нравятся мне эти сплошные False в параметрах первого...

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 17.11.2004 (Ср) 18:10

а если быть точнее, то тебе нужно открывать свой рекордсет в режиме dynamic, а то по-молчанию кажется он открывается в режиме snapshot, который только для чтения

lomaster
Начинающий
Начинающий
 
Сообщения: 21
Зарегистрирован: 02.11.2004 (Вт) 13:36

Сообщение lomaster » 17.11.2004 (Ср) 22:26

2Ennor
Не нравятся мне эти сплошные False в параметрах первого...

Не... Тут как раз и надо False
2Konst_One
нужно открывать свой рекордсет в режиме dynamic

Попробовал дописать dbOpenDynaset - нулевой эффект :(

Проблему с UPDATE я всетаки решил :) - иначе бы с работы уволили - (дело было срочное и важное).
Сделал так - вместо строчек с .Edit написал так
Код: Выделить всё
strSQL = "UPDATE person SET ps_adr_1 = '" & sAdr & "' WHERE ps_code = '" & sCode & "' AND em = '28'"
db.Execute strSQL

И хотя в таком варианте каждое найденное значение (а их несколько тысяч) инициирует новый sql-запрос к БД, отработало на удивление быстро :)

Правда, как мне кажется, первоначальный вариант (с .Edit) смотрится как то логичнее и отрабатывать, наверное, должен еще быстрее...
Хотя, с другой стороны, как этот Recordset обновленные данные назад в базу возвращает?

Да и не работает с этим .Edit ни в какую...
Если кто ТОЧНО знает КАК ответьте - хоть и проблема решена по другому - интересно все таки...

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 18.11.2004 (Чт) 8:10

И хотя в таком варианте каждое найденное значение (а их несколько тысяч) инициирует новый sql-запрос к БД, отработало на удивление быстро


Вообще-то при использовании Edit/Update запрос тоже создается...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

lomaster
Начинающий
Начинающий
 
Сообщения: 21
Зарегистрирован: 02.11.2004 (Вт) 13:36

Сообщение lomaster » 18.11.2004 (Чт) 12:11

Методом научного тыка перебрал все возможные параметры и получил вполне рабочий код :)
Привожу полностью - (мож кому сгодится).
Не смущайтесь то, что Оракл - в большинстве случаев отработает и на любой другой базе (только строчку ODBC - подключения подправить).
Код: Выделить всё
Option Explicit

Sub Database_Update()

    Dim db As Database
    Dim ws As Workspace
    Dim rst As Recordset
    Dim sConnection As String
    Dim sChangeData As String
    Dim sCode As String
    Dim iNumRec As Long
    Dim iReplaceCount As Integer
    Dim strSQL As String
    Dim sFieldName As String
    Dim sIndexKeyFieldName As String
    Dim sIndexKey As String
       
    Set ws = DBEngine.CreateWorkspace("myName", "UID", "", dbUseODBC)

    sConnection = "ODBC;DSN=ORA;UID=myname;PWD=mypassword;SERVER=oracle;"
    Set db = ws.OpenDatabase("", False, False, sConnection)

   strSQL = "SELECT * FROM person WHERE company = '568'"
    Set rst = db.OpenRecordset(strSQL, dbOpenDynaset, dbExecDirect, dbOptimisticValue)

    sFieldName = "ps_name"
    sIndexKeyFieldName = "number"
    iNumRec = 1
    iReplaceCount = 0
    With rst
        Do
         sChangeData = .Fields(sFieldName).Value
         If sChangeData = "Старые данные" Then
            sChangeData = "Новые данные"
'-------------------------------------------------
' 1-й вариант
            .Edit
            .Fields(sFieldName).Value = sChangeData
            .Update
'-------------------------------------------------
' или 2-й вариант (возможно даже быстрее чем 1-й)
            sIndexKey = .Fields(sIndexKeyFieldName).Value
            strSQL = "UPDATE person SET " & sFieldName & " = '" & sChangeData & "' WHERE " & sIndexKeyFieldName & " = " & sIndexKey
            db.Execute strSQL
'-------------------------------------------------
            iReplaceCount = iReplaceCount + 1
         End If
            iNumRec = iNumRec + 1
            .MoveNext
        Loop While Not .EOF
    End With
   
    rst.Close
    db.Close
    ws.Close
   
    MsgBox "Обработано записей: " & iNumRec - 1 & vbNewLine & "Изменено полей: " & iReplaceCount
End Sub

snov
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 176
Зарегистрирован: 28.11.2003 (Пт) 10:12
Откуда: Челябинск

Сообщение snov » 25.11.2004 (Чт) 8:40

lomaster писал(а):Методом научного тыка перебрал все возможные параметры и получил вполне рабочий код ...
' или 2-й вариант (возможно даже быстрее чем 1-й)
...

Ты уж в этом не сомневайся


Вернуться в Базы данных

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

    TopList