корректировка данных через запрос на выборку
Модератор: Naeel Maqsudov
Добрый день всем!
Подскажите пожалуйста как сделать возможной корректировку данных в запросе на выборку (собственно говоря это нужно для корректировки данных в форме, созданной на основе запроса на выборку, упомянутого выше).
Спасибо.
Подскажите пожалуйста как сделать возможной корректировку данных в запросе на выборку (собственно говоря это нужно для корректировки данных в форме, созданной на основе запроса на выборку, упомянутого выше).
Спасибо.
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
Некоторые запросы в MSAccess являются обновляемыми, для этого они должны быть гомогенными (по одной таблице), не должны использовать Group by, Union, Distinct.
Гетерогенные (с несколькими таблицами в предложении from) запросы в Oracle8 могут быть обновляемыми, если обновляется таблица "созраняющая ключи", а вот как обстоит с этим дело а Access я уже не помню. Чтобы говорить предметно, приведите пожалуйста текст запроса.
В некоторых случаях можно вместо гетерогенного запроса построить гомогенный, дающий тот же результат. Для этого вместо объединения Join использовать подзапрос в предложении select.
Т.е. нельзя сказать что это нерешаемая в принципе задача, но нужно обсуждать конкретныю ситуацию.
Гетерогенные (с несколькими таблицами в предложении from) запросы в Oracle8 могут быть обновляемыми, если обновляется таблица "созраняющая ключи", а вот как обстоит с этим дело а Access я уже не помню. Чтобы говорить предметно, приведите пожалуйста текст запроса.
В некоторых случаях можно вместо гетерогенного запроса построить гомогенный, дающий тот же результат. Для этого вместо объединения Join использовать подзапрос в предложении select.
Т.е. нельзя сказать что это нерешаемая в принципе задача, но нужно обсуждать конкретныю ситуацию.
первый запрос отрабатывает нормально и является обновляемым вот его код:
SELECT операции.*
FROM код_курс INNER JOIN (код_операц INNER JOIN ((Paprkind INNER JOIN (CLCOUN INNER JOIN ФИО ON CLCOUN.Код_страны = ФИО.код_стран) ON Paprkind.код_докум = ФИО.документ) INNER JOIN (системы_переводов INNER JOIN ((nopT INNER JOIN (пункты INNER JOIN номер_реестра ON пункты.код_пункта = номер_реестра.пункт) ON nopT.nop = номер_реестра.операционист) INNER JOIN (классиф INNER JOIN (класс_вал INNER JOIN (карты INNER JOIN (BNKSEEK INNER JOIN операции ON BNKSEEK.NEWNUM = операции.БИК) ON карты.код_карта = операции.код_карта) ON класс_вал.код_вал = операции.код_вал_операции) ON классиф.Код = операции.код) ON номер_реестра.счетчик_реестров = операции.реестр) ON системы_переводов.код_системы = операции.система_перевод) ON ФИО.счетчик = операции.[н-физ]) ON код_операц.код_операции = классиф.код_выд_получ) ON код_курс.код_курс = код_операц.код_курс;
______________________________
второй запрос точно такой же + одна таблица, после добавления которой, запрос и перестаёт быть обновляемым. Эта "неудачная" таблица - "КУРСЫ"
вот текст запроса:
SELECT операции.*
FROM (код_курс INNER JOIN (код_операц INNER JOIN ((Paprkind INNER JOIN (CLCOUN INNER JOIN ФИО ON CLCOUN.Код_страны = ФИО.код_стран) ON Paprkind.код_докум = ФИО.документ) INNER JOIN (системы_переводов INNER JOIN ((nopT INNER JOIN (пункты INNER JOIN номер_реестра ON пункты.код_пункта = номер_реестра.пункт) ON nopT.nop = номер_реестра.операционист) INNER JOIN (классиф INNER JOIN (класс_вал INNER JOIN (карты INNER JOIN (BNKSEEK INNER JOIN операции ON BNKSEEK.NEWNUM = операции.БИК) ON карты.код_карта = операции.код_карта) ON класс_вал.код_вал = операции.код_вал_операции) ON классиф.Код = операции.код) ON номер_реестра.счетчик_реестров = операции.реестр) ON системы_переводов.код_системы = операции.система_перевод) ON ФИО.счетчик = операции.[н-физ]) ON код_операц.код_операции = классиф.код_выд_получ) ON код_курс.код_курс = код_операц.код_курс) INNER JOIN курсы ON (курсы.код_вал = класс_вал.код_вал) AND (курсы.код_курс_реестр = номер_реестра.счетчик_реестров) AND (код_курс.код_курс = курсы.код_курс);
___________________________
причём оба запроса отрабатывают нормально, выходные данные совпадают. Если во второй select добавить поле "СУММА" из таблицы "КУРС", то в зависимости от отобранных записей по таблице "ОПЕРАЦИИ" выдаётся абсолютно корректное значение курса для каждой записи. Всё отлично.
НО почему второй запрос не обновляемый? Вернее почему после добавления таблицы "КУРСЫ" запрос перестаёт быть обновляемым?
SELECT операции.*
FROM код_курс INNER JOIN (код_операц INNER JOIN ((Paprkind INNER JOIN (CLCOUN INNER JOIN ФИО ON CLCOUN.Код_страны = ФИО.код_стран) ON Paprkind.код_докум = ФИО.документ) INNER JOIN (системы_переводов INNER JOIN ((nopT INNER JOIN (пункты INNER JOIN номер_реестра ON пункты.код_пункта = номер_реестра.пункт) ON nopT.nop = номер_реестра.операционист) INNER JOIN (классиф INNER JOIN (класс_вал INNER JOIN (карты INNER JOIN (BNKSEEK INNER JOIN операции ON BNKSEEK.NEWNUM = операции.БИК) ON карты.код_карта = операции.код_карта) ON класс_вал.код_вал = операции.код_вал_операции) ON классиф.Код = операции.код) ON номер_реестра.счетчик_реестров = операции.реестр) ON системы_переводов.код_системы = операции.система_перевод) ON ФИО.счетчик = операции.[н-физ]) ON код_операц.код_операции = классиф.код_выд_получ) ON код_курс.код_курс = код_операц.код_курс;
______________________________
второй запрос точно такой же + одна таблица, после добавления которой, запрос и перестаёт быть обновляемым. Эта "неудачная" таблица - "КУРСЫ"
вот текст запроса:
SELECT операции.*
FROM (код_курс INNER JOIN (код_операц INNER JOIN ((Paprkind INNER JOIN (CLCOUN INNER JOIN ФИО ON CLCOUN.Код_страны = ФИО.код_стран) ON Paprkind.код_докум = ФИО.документ) INNER JOIN (системы_переводов INNER JOIN ((nopT INNER JOIN (пункты INNER JOIN номер_реестра ON пункты.код_пункта = номер_реестра.пункт) ON nopT.nop = номер_реестра.операционист) INNER JOIN (классиф INNER JOIN (класс_вал INNER JOIN (карты INNER JOIN (BNKSEEK INNER JOIN операции ON BNKSEEK.NEWNUM = операции.БИК) ON карты.код_карта = операции.код_карта) ON класс_вал.код_вал = операции.код_вал_операции) ON классиф.Код = операции.код) ON номер_реестра.счетчик_реестров = операции.реестр) ON системы_переводов.код_системы = операции.система_перевод) ON ФИО.счетчик = операции.[н-физ]) ON код_операц.код_операции = классиф.код_выд_получ) ON код_курс.код_курс = код_операц.код_курс) INNER JOIN курсы ON (курсы.код_вал = класс_вал.код_вал) AND (курсы.код_курс_реестр = номер_реестра.счетчик_реестров) AND (код_курс.код_курс = курсы.код_курс);
___________________________
причём оба запроса отрабатывают нормально, выходные данные совпадают. Если во второй select добавить поле "СУММА" из таблицы "КУРС", то в зависимости от отобранных записей по таблице "ОПЕРАЦИИ" выдаётся абсолютно корректное значение курса для каждой записи. Всё отлично.
НО почему второй запрос не обновляемый? Вернее почему после добавления таблицы "КУРСЫ" запрос перестаёт быть обновляемым?
Алина!
так сложно сказать.
если хотите, вышлите мне копию базы, где будут только участвующие
в запросах таблицы и сами запросы.
Из таблиц можете удалить 99% данных, оставьте пару записей,
чтобы можно было посмотреть работу запросов.
мыло: sitcom@narod.ru
сожмите базу и поместите в архив.
Андрей.
так сложно сказать.
если хотите, вышлите мне копию базы, где будут только участвующие
в запросах таблицы и сами запросы.
Из таблиц можете удалить 99% данных, оставьте пару записей,
чтобы можно было посмотреть работу запросов.
мыло: sitcom@narod.ru
сожмите базу и поместите в архив.
Андрей.
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
У меня так и не духу разложить ВСЕ предложения Join в дерево объединений...НО почему второй запрос не обновляемый? Вернее почему после добавления таблицы "КУРСЫ" запрос перестаёт быть обновляемым?

Попробую объяснить на более простом примере. Допустим мы объединяем две таблицы Т1 и Т2 имеющие соответственно отношение 1-ко-многим (т.е. "много" на стороне талицы Т2). После объединения данных первичный ключ таблицы будет оставаться уникальным, а ключ таблицы Т2 будет повторяться.
В данном случае таблицу Т2 называют ТАБЛИЦЕЙ, СОХРАНЯЮЩЕЙ КЛЮЧИ (есть такое понятие). Разумеется если в начале запроса будет написано "select t2.* from ..." то запрос будет обновляемым, так как добавление будет производиться в таблицу t2. А если "select t1.* from ...", то разумеется добавление/изменение невозможно, так как ключи повторяются и неизвестно, что редактировать.
Т.е. через запрос "select * from t1 inner join t2 on (...)" в описанных условиях можно редактировать только таблицу T2!
После добавления таблицы КУРСЫ таблица ОПЕРАЦИИ перестает быть таблицей сохраняющей ключи (т.е. не факт, что первичный ключ таблицы ОПЕРАЦИИ действительно повторяется, а просто между ними могло возникнуть отношение много-ко-многим, например).
Как быть?
Попробуйте преобразовать условия из предложения JOIN ON в условия предложения where это должно помочь.
Например JOIN можно заменить на EXISTS
в первый запрос добавьте where со связанным подзапросом
where exists(
select * from КУРРСЫ
where код_вал = класс_вал.код_вал and
код_курс_реестр = номер_реестра.счетчик_реестров and
код_курс = курсы.код_курс
)
Только боже упаси тащить потом это в "Конструктор запросов". Эта зараза
Exists (...) преобразовывает в (Exists (...)<>false) и еще скобок наставит...
Итак в результате у Вас останется просто отфильтрованный первый запрос, который редактируется.
Но опять-таки нет гарантии, что все получится.... Пишите, попробуем еще что-нибудь придумать.
Уважаемый Андрей И Наиль Адилевич!
Большое спасибо за участие.
В связи с необходимостью решать вопросы бысто, пришлось найти альтернативный подход. Выполняется запрос на добавление шаблонной записи, а далее идет работа в форме по редактированию уже существующей записи. Т.е. надобность в создании обновляемого запрса отпала.
Ещё раз спасибо.
У меня очередная загвоздка. (с вашего позволения)
На кнопку навешивается обработка события:
Private Sub Option3_Click()
On Error GoTo Err_Option3_Click
Dim stDocName As String
Dim stLinkCriteria As String
Dim pass As String
pass = InputBox("Введите пароль!!! ")
If pass = "пожалуйста" Then
MsgBox "Пароль верен!!!"
Else
MsgBox "Пароль не верен! Вам отказано в доступе к этой форме"
Exit Sub
Cancel = 1
End If
stDocName = ChrW(1085) & ChrW(1086) & ChrW(1084) & ChrW(1077) & ChrW(1088) & ChrW(95) & ChrW(1088) & ChrW(1077) & ChrW(1077) & ChrW(1089) & ChrW(1090) & ChrW(1088) & ChrW(1072) & ChrW(95) & ChrW(1082) & ChrW(1086) & ChrW(1088) & ChrW(1088) & ChrW(1077) & ChrW(1082) & ChrW(1090) & ChrW(1080) & ChrW(1088) & ChrW(1086) & ChrW(1074) & ChrW(1082) & ChrW(1072)
DoCmd.OpenForm stDocName, , , stLinkCriteria
Exit_Option3_Click:
Exit Sub
Err_Option3_Click:
MsgBox Err.Description
Resume Exit_Option3_Click
End Sub
Т.е. вход в форму осуществляется при введении пароля.
Но он (пароль), самым наглым образом, при вводе отображается на экране. Как бы вместо вводимых с клавиатуры символов, выводить "звёздочки" или какой-то другой символ?!
Спасибо!
Большое спасибо за участие.
В связи с необходимостью решать вопросы бысто, пришлось найти альтернативный подход. Выполняется запрос на добавление шаблонной записи, а далее идет работа в форме по редактированию уже существующей записи. Т.е. надобность в создании обновляемого запрса отпала.
Ещё раз спасибо.
У меня очередная загвоздка. (с вашего позволения)
На кнопку навешивается обработка события:
Private Sub Option3_Click()
On Error GoTo Err_Option3_Click
Dim stDocName As String
Dim stLinkCriteria As String
Dim pass As String
pass = InputBox("Введите пароль!!! ")
If pass = "пожалуйста" Then
MsgBox "Пароль верен!!!"
Else
MsgBox "Пароль не верен! Вам отказано в доступе к этой форме"
Exit Sub
Cancel = 1
End If
stDocName = ChrW(1085) & ChrW(1086) & ChrW(1084) & ChrW(1077) & ChrW(1088) & ChrW(95) & ChrW(1088) & ChrW(1077) & ChrW(1077) & ChrW(1089) & ChrW(1090) & ChrW(1088) & ChrW(1072) & ChrW(95) & ChrW(1082) & ChrW(1086) & ChrW(1088) & ChrW(1088) & ChrW(1077) & ChrW(1082) & ChrW(1090) & ChrW(1080) & ChrW(1088) & ChrW(1086) & ChrW(1074) & ChrW(1082) & ChrW(1072)
DoCmd.OpenForm stDocName, , , stLinkCriteria
Exit_Option3_Click:
Exit Sub
Err_Option3_Click:
MsgBox Err.Description
Resume Exit_Option3_Click
End Sub
Т.е. вход в форму осуществляется при введении пароля.
Но он (пароль), самым наглым образом, при вводе отображается на экране. Как бы вместо вводимых с клавиатуры символов, выводить "звёздочки" или какой-то другой символ?!
Спасибо!
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
Во-первых access имеет средства для разграничения доступа к любым объектам на уровне прав пользователей и групп пользователей. Т.е. кому-то можно разрешить открытие некой формы только на просмотр, кому-то с полным доступом к данным, а кому-то даже в конструктор этой формы. И т.д.
Для этого нужно файл рабочей группы создать ДО создания базы и далее работать в рамках имено этой рабочей группы.
Ну а во-вторых можно оргшанизовать защиту и Вашим способом, но для ее обхода надо нажать alt-F11, а тогда возникает вопрос: зачем она такая нужна?
Ну да ладно.
Итак InputBox не может решить эту задачу, следовательно прийдется наприсовать свою форму Форма1, используемую вместо InputBox. Т.е. вместо "pass = InputBox("Введите пароль!!! ") " мы напишем
Passw - это глобальная переменная уровня проекта (К сожалению, это оптимальный способ извлечения данных из формы В ДАННОМ СЛУЧАЕ). Т.е. добавим в проект модуль в котором единственная строчка:
Форма же Форма1 содержит поле Поле0 и две кнопки, а в модуле формы имеются следующие обработчики:
Ну и наконец последний штрих - настройка элементов на форме Форма1.
1) У поля Поле0 свойство МаскаВвода установим в значение "Пароль" (см. справку по свойству)
2) сделаем форму похожей на модальное диалоговое окно (см свойства формы):
- Разделительные линии = Нет
- Кнопки перехода (Поле номера (в access95)) = Нет
- Модальное окно = Да (это очень важно!)
- Область выделения = Нет
- Тип границы = Окна диалога
- Выравнивание по центру = Да
Для этого нужно файл рабочей группы создать ДО создания базы и далее работать в рамках имено этой рабочей группы.
Ну а во-вторых можно оргшанизовать защиту и Вашим способом, но для ее обхода надо нажать alt-F11, а тогда возникает вопрос: зачем она такая нужна?
Ну да ладно.
Итак InputBox не может решить эту задачу, следовательно прийдется наприсовать свою форму Форма1, используемую вместо InputBox. Т.е. вместо "pass = InputBox("Введите пароль!!! ") " мы напишем
Код: Выделить всё
DoCmd.OpenForm "Форма1", , , , , acDialog
pass = Passw
Код: Выделить всё
Public Passw As String
Код: Выделить всё
Private Sub Form_Open(Cancel As Integer)
Passw = ""
End Sub
Private Sub Кнопка6_Click()
On Error Resume Next
Me.Поле0.SetFocus
Passw = ""
Passw = CStr(Me.Поле0.Value)
DoCmd.Close
End Sub
Private Sub Кнопка7_Click()
Passw = ""
DoCmd.Close
End Sub
1) У поля Поле0 свойство МаскаВвода установим в значение "Пароль" (см. справку по свойству)
2) сделаем форму похожей на модальное диалоговое окно (см свойства формы):
- Разделительные линии = Нет
- Кнопки перехода (Поле номера (в access95)) = Нет
- Модальное окно = Да (это очень важно!)
- Область выделения = Нет
- Тип границы = Окна диалога
- Выравнивание по центру = Да
Спасибо, всё чудесно работает!