Имя: Пароль:
1C
1C 7.7
v7: Примитивный запрос UPDATE :-)
,
0 MWWRuza
 
гуру
09.10.20
22:04
Добрый вечер!
В продолжение(точнее, "по мотивам") темы: Замена ссылок в движениях регистров(в таблицах DBF)
Там я реальную проблему решил, конвертнул базу в SQL, воспользовался обработкой, поменял что нужно, и сконвертил в DBF обратно. Все получилось, нет проблем.
Но, захотелось все-таки что-то такое под DBF сделать, что-бы при необходимости обходиться без этих "плясок с бубном" с конвертацией туда-обратно.

В посте (7) Ёпрст писал: "Написать примитивный запрос на update нужных табличек проще всего на vfpoledb, синтаксис не особо и отличаться будет от запроса для mssql"...
Пошел по этому пути. Но опыта в прямых запросах - явно не хватает :-(
Первая часть, по поиску ссылок, заработала без особых проблем.
А вот вторая, по замене - ну никак не хочет работать...
Вот так это выглядит в отладчике: https://content.foto.my.mail.ru/mail/m_w_w/_mypagephoto/h-351.jpg
На следующем шаге падает с ошибкой, вот так: https://content.foto.my.mail.ru/mail/m_w_w/_mypagephoto/h-352.jpg
Текст ошибки:
рс.ВыполнитьИнструкцию(ТекстЗапроса);
{D:\BASA_1C\ВЕГА\ЗАМЕНАЭЛЕМЕНТАДБФ.ERT(689)}: FAILED! ICommandText::Execute(): Record is not locked.

Вот текст самого запроса:
                База = СоздатьОбъект("OLEDBData");
                Соединение = "Provider=VFPOLEDB.1;Data Source=" + КаталогИБ()+ ";Mode=ReadWrite;Collating Sequence=MACHINE";
                Если База.Соединение(Соединение) = 0 Тогда
                    Сообщить("Не соеденились");
                    Возврат;
                КонецЕсли;
                рс = База.СоздатьКоманду();                
                
                ТекстЗапроса = "
                |UPDATE  
                |    $"+тзПотомки.Метаданные+"
                | SET $"+тзПотомки.Метаданные+"."+тзПотомки.Реквизит +" = :Объект
                |FROM $"+тзПотомки.Метаданные+" AS Tab
                |where (Tab.IDDOC = :Док)
                | AND  ($Tab."+тзПотомки.Реквизит+" = :Источник)
                |";
                рс.УстановитьТекстовыйПараметр("Объект", Приемник);
                рс.УстановитьТекстовыйПараметр("Источник", Источник);
                рс.УстановитьТекстовыйПараметр("Док", Док.ТекущийДокумент());
        //        рс.Выполнить("EXECSCRIPT('SET ANSI OFF')");
                рс.ВыполнитьИнструкцию(ТекстЗапроса);

Все-таки, видимо синтаксис не особо, но отличается... Такое ощущение, что он не может получить доступ к таблице на запись...
Подскажите пожалуйста, что я не правильно делаю?
1 МихаилМ
 
09.10.20
22:56
2 Ёпрст
 
09.10.20
23:35
(0)


    ОлеДБ = СоздатьОбъект("OLEDBData");
    Соединение = "Provider=VFPOLEDB.1;Data Source=" + КаталогИБ() + ";Mode=ReadWrite;Collating Sequence=MACHINE";
    Рез = ОлеДБ.Соединение(Соединение);
    Запрос = ОлеДБ.СоздатьКоманду();
    Запрос.Выполнить("EXECSCRIPT('SET ANSI OFF')");  
    Запрос.Выполнить("EXECSCRIPT('SET REPROCESS TO 60 SECONDS')");
    Запрос.Выполнить("EXECSCRIPT('SET REFRESH TO 0,-1')");    
    Запрос.Выполнить("Exec('SET TABLEVALIDATE TO 0')");
    Запрос = ОлеДБ.СоздатьКоманду();
    ТекстЗапроса = "
    |Update
    |   Вася
    |Set
    |   $Вася.Реквизит=:Параметр
    |
    |from $Справочник.Вася as Вася
    |
    |";
    Запрос.УстановитьТекстовыйПараметр("Параметр", "Лошпед");
    Запрос.ВыполнитьИнструкцию(ТекстЗапроса);


ЗЫ: пихать метаданные...да уж.
Если че, есть Идентификатор у метаданных.
3 Ёпрст
 
09.10.20
23:36
и.. Запрос.Отладка(1) надо показывать на форуме, если че..
4 МихаилМ
 
09.10.20
23:41
(3) а как быть с длинными строками и не ограниченной длинны. рни вроде хранятся отдельно по 500 байт
5 Ёпрст
 
09.10.20
23:44
(4) да, в блобе хранятся блоками, там тупо искать все блоки и апдейтить ..кусками
6 Ёпрст
 
09.10.20
23:48
вот так выглядит:
https://i.postimg.cc/Hs9sdR3k/blob.png
7 Ёпрст
 
09.10.20
23:49
имея id объекта и id реквизита ..и по всем blockno
8 Ёпрст
 
09.10.20
23:49
можно заместо update пользовать delete + insert
9 Ёпрст
 
09.10.20
23:50
в этом случае.

Да..автора еще ждёт Периодика :)) и знакомство с 1sconst
10 Ёпрст
 
09.10.20
23:50
если уж всё заменять
11 Ёпрст
 
09.10.20
23:52
и...в документах, в графах отбора, если есть, познакомится с 1crdoc
12 MWWRuza
 
гуру
10.10.20
09:08
Спасибо. Сегодня буду пробовать.
А длинных строк и периодики - нет. Задача несколько уже, чем у исходной обработки. Мне по большому счету, достаточно "освободить" лишний элемент номенклатуры, перенеся все его движения на "правильный", и потом удалить. Единицы, подчинённые ему - тоже. Регистр остатки, потом пересчитается. Все длинные строки удалятся вместе с ненужным элементом. Единицы, уже на новом владельце, тоже удалить лишние, которые без Шк. А периодика? Ну, только в ценах... Мне проще удалить цены ненужного элемента, вместе с ним, и оставить цены от правильного, свежего элемента... Цены годовалой давности... Ну, моим точно не нужны, ни какой аналитикой мои "лавочники' не занимаются, от слова совсем.
13 MWWRuza
 
гуру
11.10.20
01:02
(2),(3)
Включил отладку:

UPDATE  
    ra405
SET sp408 = '   3TB   '
FROM ra405 AS Tab
where (Tab.IDDOC = '    2T   ')
AND  (Tab.sp408 = '    IG   ')
рс.ВыполнитьИнструкцию(ТекстЗапроса);
{D:\BASA_1C\ВЕГА\ЗАМЕНАНОМЕНКЛАТУРЫ.ERT(562)}: FAILED! ICommandText::Execute(): Record is not locked.

Вот... Все равно не меняет. Имя таблицы и идентификаторы, вроде все правильные.
14 MWWRuza
 
гуру
11.10.20
01:04
Инициализирую запрос так:

                ОлеДБ = СоздатьОбъект("OLEDBData");
                Соединение = "Provider=vfpoledb.1;Mode=ReadWrite;Data Source="+КаталогИБ()+";Collating Sequence=machine;";
                Если ОлеДБ.Соединение(Соединение)=0 Тогда
                    Сообщить("Не соеденились");
                    Возврат;
                КонецЕсли;
                рс = ОлеДБ.СоздатьКоманду();
                
                рс = ОлеДБ.СоздатьКоманду();
                рс.Выполнить("EXECSCRIPT('SET ANSI OFF')");  
                рс.Выполнить("EXECSCRIPT('SET REPROCESS TO 60 SECONDS')");
                рс.Выполнить("EXECSCRIPT('SET REFRESH TO 0,-1')");    
                рс.Выполнить("Exec('SET TABLEVALIDATE TO 0')");
                рс = ОлеДБ.СоздатьКоманду();
15 Злопчинский
 
11.10.20
01:36
галактеко волнуецо
16 AAA
 
11.10.20
05:37
(14)Сделай сначала не UPDATE, а SELECT, может выборка пустая. Поле SP408 случайно не справочник неопределенного вида ?
17 MWWRuza
 
гуру
11.10.20
07:32
(16) Нет. Справочник "Номенклатура".
А вот что выборка пустая... Возможно.
Что эта ошибка вообще означает, то, что не может получить доступ на запись, или не спозиционировался на записи?
18 MWWRuza
 
гуру
11.10.20
07:43
+(17) А не может быть причиной, что я сначала аналогичным запросом таблицу ссылок формирую, а потом, менять пытаюсь? Может после первого запроса, таблица "занята" остаётся?
Попробовать изменить первый запрос, открывать таблицу только на чтение? Или как то принудительно "освобождать" ее?
19 Ёпрст
 
11.10.20
09:03
(18) покажи весь код
20 Ёпрст
 
11.10.20
09:14
Хотя, не нужен код. Просто открой 1сину НЕ монопольно. Для монопольного режима нужно ставить заплаткутот hogik
21 MWWRuza
 
гуру
11.10.20
10:31
(20) Не...
Прежде, чем задавать вопросы здесь, я естественно изучил все, что удалось найти поиском по этой проблеме... И про монопольный режим - первое, что выскочило.
Пробовал и в разделенном, и в монопольном - все одинаково. И заплатку от hogik поставил, тоже эффекта нет.
Сейчас проверил свое предположение - в первом запросе, вместо "Mode=ReadWrite;" написал "Mode=Read;", тоже ничего не дало, во всех случаях ошибка та-же.
(19) Показать весь код? Там почти 600 строк, на форум такое выкладывать... Как-то не корректно... Вот ссылка на мою поделку: https://cloud.mail.ru/public/5yzg/4isPPPU9t Там большая часть кода не моя, заимствована отсюда:  http://catalog.mista.ru/public/77355/, с минимальной адаптацией под мои "хотелки"...
22 MWWRuza
 
гуру
11.10.20
11:56
Тут нечто подобное описано: https://www.1cpp.ru/forum/YaBB.pl?num=1259656140
Попробовал без FROM -
|UPDATE                   
|    $"+тзПотомки.Метаданные+"                 
| SET $"+тзПотомки.Метаданные+"."+тзПотомки.Реквизит +" = :Объект              
//|FROM $"+тзПотомки.Метаданные+" AS Tab                 
|where (Tab.IDDOC = :Док)             
//| AND  ($Tab."+тзПотомки.Реквизит+" = :Источник)                 
| AND  ($"+тзПотомки.Метаданные+"."+тзПотомки.Реквизит+" = :Источник)                 
|";

Получаю:
UPDATE  
    ra405
SET sp408 = '   3TB   '
where (Tab.IDDOC = '    2T   ')
AND  (sp408 = '    IG   ')
рс.ВыполнитьИнструкцию(ТекстЗапроса);
{D:\BASA_1C\ВЕГА\ЗАМЕНАНОМЕНКЛАТУРЫ.ERT(562)}: FAILED! ICommandText::Execute(): SQL: Column '     ' is not found.

Какую-то колонку не находит почему-то...
Не пойму, таблица - правильная, заменить в ней поле в колонке "sp408" когда идентификатор документа "2T" и значение этого поля "IG"... Какая ему еще колонка нужна?
Может не "sp408" должно быть, а "Tab.sp408" - ?
23 MWWRuza
 
гуру
11.10.20
12:14
Вот так заработало:
                ТекстЗапроса = "
                |UPDATE
                |    $"+тзПотомки.Метаданные+"
                | SET $"+тзПотомки.Метаданные+"."+тзПотомки.Реквизит +" = :Объект
            //    |FROM $"+тзПотомки.Метаданные+" AS Tab
            //    |where (Tab.IDDOC = :Док)
                |where ("+тзПотомки.Метаданные+".IDDOC = :Док)
            //    | AND  ($Tab."+тзПотомки.Реквизит+" = :Источник)
                | AND  ($"+тзПотомки.Метаданные+"."+тзПотомки.Реквизит+" = :Источник)
                |";

В отладке пишет:
UPDATE
    ra405
SET sp408 = '   3TB   '
where (Регистр.ОстаткиТМЦ.IDDOC = '    2T   ')
AND  (sp408 = '    IG   ')
- Изменены движения по регистру ОстаткиТМЦ
UPDATE
    ra328
SET sp331 = '   3TB   '
where (Регистр.ПартииНаличие.IDDOC = '    2T   ')
AND  (sp331 = '    IG   ')
- Изменены движения по регистру ПартииНаличие

Но, реально ничего не меняет... Повторный поиск ссылок опять их находит.
24 MWWRuza
 
гуру
11.10.20
12:32
+(23) Ну, да... Проверил файлы, время изменения в 0:15(это я через XBase менял, как внешние, и потом копировал в базу, ради пробы, в выложенной обработке этот кусок закомментирован), а последний раз запускал в 12:25 - файлы не меняются... Хотя пишет, что все изменено и ошибок нет. Может как-то записывать изменения надо?
25 MWWRuza
 
гуру
11.10.20
13:52
+(23) Я уже и имя параметра "Объект" заменил на "ОбПрием", ничего не меняется.
26 Ёпрст
 
11.10.20
21:37
Ё...чего, (2) не осилил ?

На вот, занимайся


            ТекстЗапроса = "
                |UPDATE  
                |    Tab
                | SET $Tab."+тзПотомки.Реквизит +" = :Объект
                |FROM $"+тзПотомки.Метаданные+" AS Tab
                |where (Tab.IDDOC = :Док)
                | AND  ($Tab."+тзПотомки.Реквизит+" = :Источник)
                |";
27 MWWRuza
 
гуру
11.10.20
22:53
(26) Да, так работает! Спасибо огромное!
28 Злопчинский
 
11.10.20
23:08
(27) галактеко вздохнуло с облегчением. темный император повержен
29 MWWRuza
 
гуру
25.10.20
17:32
Та-же обработка, на другой базе:
Ошибка обработки запроса:

SELECT DISTINCT
    :Объект As [Объект $Справочник.Номенклатура]
    ,Tab.IDDOC As [Ссылка $Документ.Приходная]
    ,'Товар' As Реквизит
    ,'ДокументСтроки.Приходная' As Метаданные
    
FROM
    $ДокументСтроки.Приходная As Tab
    
where  $Tab.Товар = :Объект

База данных не установлена

Что значит "База данных не установлена", как это понимать?
30 ДенисЧ
 
25.10.20
17:51
31 MWWRuza
 
гуру
25.10.20
18:15
Ну... А почему, в другой аналогичной базе работает?
Вот полный текст:
        ДопКолонка = тзРеквизитов.ДопКолонка;
        ДопТаблица = тзРеквизитов.ДопТаблица;
        
        Если тзРеквизитов.ОбъектМетаданных = "Константа" Тогда
            ОбъектМетаданных = "_1SCONST";
        Иначе
            ОбъектМетаданных = "$"+тзРеквизитов.ОбъектМетаданных;
        КонецЕсли;
        
        ТекстЗапроса = "
        |SELECT DISTINCT
        |    :Объект As [Объект $"+ПредТип_Вид+"]
        |    ,"  + тзРеквизитов.Идентификатор+" As " + Типизатор +"
        |    ,'"+ тзРеквизитов.Реквизит+"' As Реквизит
        |    ,'"+ тзРеквизитов.ОбъектМетаданных+"' As Метаданные
        |    "  + ДопКолонка+"
        |FROM
        |    "+ ОбъектМетаданных+" As Tab
        |    "+ ДопТаблица + "
        |where "+тзРеквизитов.Условие +"
        |";
        рс.УстановитьТекстовыйПараметр("Объект",ВыбОбъект);
        Попытка
            тзЗапроса = рс.ВыполнитьИнструкцию(ТекстЗапроса);
        Исключение
            Сообщить("Ошибка обработки запроса: ");
            Сообщить(ТекстЗапроса);
            Сообщить(ОписаниеОшибки());
            Сообщить("--------------------------");
        КонецПопытки;
        Если тзЗапроса.КоличествоСтрок() <> 0 Тогда
            тзСсылок.Объединить(тзЗапроса);
        Иначе
            //Сообщить("В "+СтрЗаменить(тзРеквизитов.ОбъектМетаданных,"Строки","")+ " ссылки не найдены");
        КонецЕсли;
32 MWWRuza
 
гуру
25.10.20
18:18
Я там ничего специально не устанавливаю... Может это где-то не явно происходит?
33 Ёпрст
 
25.10.20
21:01
(29) формат базы то какой хоть? Дбф/скуль
34 trdm
 
25.10.20
23:01
(32) РС на скуле автоконектится.
35 MWWRuza
 
гуру
25.10.20
23:50
(33) Да ничего не поменялось... Обработка та-же, база как и изначально - dbf, компьютер тот-же, соответственно драйвер db установлен.
36 Ёпрст
 
25.10.20
23:55
(35) формат базы какой ? dbf/sql ?
37 Ёпрст
 
25.10.20
23:56
строка соединения с базой какая ?
38 Ёпрст
 
25.10.20
23:57
и.. версия 1cpp какая светится в меню "О программе "?
39 MWWRuza
 
гуру
26.10.20
00:14
(37) А ни какая... Спасибо, извиняюсь, просто перепутал обработку... Это исходная была, под скуль...
Проверил - а нет строки подключения... И сразу все понятно стало, использовал ту, которую дорабатывал под дбф - и все заработало.
Требовать и эффективности, и гибкости от одной и той же программы — все равно, что искать очаровательную и скромную жену... по-видимому, нам следует остановиться на чем-то одном из двух. Фредерик Брукс-младший