|
v7: Проверка уникальности номера и серии документа при записи в 1С 7.7 SQL. | ☑ | ||
---|---|---|---|---|
0
Walter69y
31.08.12
✎
11:36
|
Суть проблемы такова.
Есть документ в 1С, квитанция. В модуле прописана проверка на уникальность номера и серии документа, вот так. дд = СоздатьОбъект("Документ.Квитанция"); дд.ОбратныйПорядок(1); дд.ВыбратьДокументы(); Пока дд.ПолучитьДокумент()=1 Цикл Если дд.ПометкаУдаления()=1 Тогда Продолжить КонецЕсли; Если дд.Серия=Серия Тогда Если (дд.Номер=Номер) и (дд.НомерДок<>НомерДок) и (дд.ТекущийДокумент()<>ТекущийДокумент()) Тогда Предупреждение("Квитанция с таким номером и серией существует !"); СтатусВозврата(0); Возврат; КонецЕсли; КонецЕсли; КонецЦикла; Я с 1С работаю не давно, после объединения двух баз в одну, ее пришлось перевести на SQL, который работает медленнее. Ранее выполнение этой проверки на DBF базе не вызывало затруднений и проходило за 1-2 секунды, теперь же операторам приходится ждать около минуты. При оформлении порядка 70 документов в день, потеря времени выходит больше часа. Насколько я понимаю, если переписать эту проверку используя механизм запросов, то это может снизить время записи документа. Собственно вот, почитал про запросы, понял как они работают, но хожу как кот вокруг сметаны и не знаю с какой стороны. Можете предложить скелет подобной проверки используя запрос? |
|||
1
Ork
31.08.12
✎
11:39
|
(0) В семерке запросы ничуть не быстрее выборок. Посему - не взлетит.
Должно помочь НайтиПоНомеру + последующая проверка не серию. |
|||
2
Ёпрст
31.08.12
✎
11:41
|
только не найти по номеру, а ВыбратьПоНомеру - это самое быстрое штатное средство
|
|||
3
Ёпрст
31.08.12
✎
11:41
|
Хотя, достаточно уникальность нумера выставить и не страдать х..ней
|
|||
4
Ёпрст
31.08.12
✎
11:42
|
а ёпт.. не увидел серию еще.
|
|||
5
Азат
31.08.12
✎
11:42
|
ЗагрузитьВнешнююКомпоненту("1cpp.dll");
Запрос = СОздатьОбъект("ODBCRecordSet"); Текст = "select top 1 * from $Документ.Квитанция as d1 (nolock) |inner join _1sjourn as jj (nolock) on jj.iddoc = d1.iddoc where $d1.Номер = :Номер and jj.docno <> :НомерДок and d1.iddoc <> :iddoc |" ну и что-то такое |
|||
6
Азат
31.08.12
✎
11:42
|
+ (5) серию тож забыл
|
|||
7
Walter69y
31.08.12
✎
11:50
|
Если я правильно понял, Вы (Азат) используете некий компонент, который не входит в стандартную поставку 1С, есть ли какие-либо опасности при его использовании?
|
|||
8
Азат
31.08.12
✎
11:51
|
(7) www.1cpp.ru опасность одна - юзерам понравятся быстрые отчеты, они сядут тебе на шею и свесят ножки
|
|||
9
Walter69y
31.08.12
✎
11:54
|
Какая версия нужна мне с раздельной загрузкой FormEX или включенным?
|
|||
10
Азат
31.08.12
✎
11:57
|
(9) с раздельной возьми
|
|||
11
Ёпрст
31.08.12
✎
11:57
|
||||
12
Walter69y
31.08.12
✎
12:01
|
в общем я так понимаю, не обязательно загружать эту компоненту глобально для всей 1С, можно использовать ее только в данном случае, так?
|
|||
13
Азат
31.08.12
✎
12:08
|
(12) да воткни в глобальнике в ПриНачалеРаботыСистемы и все
|
|||
14
Walter69y
31.08.12
✎
12:16
|
Хорошо, тогда
ЗагрузитьВнешнююКомпоненту("1cpp.dll"); из запроса можно убрать? Еще вопрос. Понятно, что запрос позволяет не шарится по всей базе, а частично ограничивает область поиска и затем можно работать с результатом запроса, собственно как мне реализовать механизм проверки. Если я правильно прочитал Ваш код, то результатом данного запроса будет квитанция с аналогичным номером, если она есть. Что мне делать дальше? Нужно как-то сверить результат запроса с данными внесенными в квитанцию на сохранение и либо отказать в записи, либо пропустить этот документ. |
|||
15
Азат
31.08.12
✎
12:38
|
(14) ты на выходе получишь таблицу значений. если в ней есть хоть одна строка, то значит,
Предупреждение("Квитанция с таким номером и серией существует !"); СтатусВозврата(0); Возврат; |
|||
16
Walter69y
31.08.12
✎
12:49
|
то есть вся моя проверка будет выглядеть, вот таким образом:
Запрос = СОздатьОбъект("ODBCRecordSet"); Текст = "select top 1 * from $Документ.Квитанция as d1 (nolock) |inner join _1sjourn as jj (nolock) on jj.iddoc = d1.iddoc where $d1.Номер = :Номер and jj.docno <> :НомерДок and d1.iddoc <> :iddoc |" Предупреждение("Квитанция с таким номером и серией существует !"); СтатусВозврата(0); Возврат; ? |
|||
17
Азат
31.08.12
✎
14:20
|
нет
|
|||
18
Walter69y
31.08.12
✎
14:23
|
Да, затупил.
Вроде вот так правильно. Запрос = СОздатьОбъект("ODBCRecordSet"); Текст = "select top 1 * from $Документ.Квитанция as d1 (nolock) |inner join _1sjourn as jj (nolock) on jj.iddoc = d1.iddoc where $d1.Номер = :Номер and jj.docno <> :НомерДок and d1.iddoc <> :iddoc |" ; Если Запрос.Выполнить (Текст)=1 Тогда Предупреждение("Квитанция с таким номером и серией существует !"); СтатусВозврата(0); Возврат; КонецЕсли; |
|||
19
Светлый Гений
31.08.12
✎
14:25
|
(18)ага, только туда еще серию добавить надо
|
|||
20
Ёпрст
31.08.12
✎
14:31
|
(18) параметры не установлены в текст запроса, да и синтаксис выполнения другой.
|
|||
21
Walter69y
31.08.12
✎
14:53
|
Хм, что-то не так. Получается следующее.
При данной формулоровке, полис с серией и номером который уже есть в базу без проблем дублируется и записывается еще раз. Если же Если Запрос.Выполнить (Текст)=0 Тогда то любой полис выдает сообщение об ошибке |
|||
22
varelchik
31.08.12
✎
16:27
|
Народ.
Вы с Методами ничего не напутали? Выполнить() возвращает 1 или 0 если запрос отработал или нет. Используй ВыполнитьИНструкцию() или ВыполнитьСкалярный() |
|||
23
varelchik
31.08.12
✎
16:28
|
Внимательно курим описание данного объекта.
|
|||
24
varelchik
31.08.12
✎
16:51
|
Синтаксис: Выполнить(ТекстSQL)
Параметры: ТекстSQL - тип: Строка. SQL запрос не возвращающий результат набор данных. Возвращает: тип: Число. 1 - запрос выполнился успешно, 0 - безуспешно, описание ошибки можно получить, вызвав метод ПолучитьОписаниеОшибки. Описание: позволяет выполнить SQL запрос, без возврата результата выборки. Метод в основном предназначен для выполнения запросов вставки, обновления, вызова процедур. |
|||
25
varelchik
31.08.12
✎
16:52
|
а вам надо это:
1C++ :: Прямой доступ через ODBC | Ранее: ОбратныйРасчетОтТА / BackFromTAEnabled | Далее: ВыполнитьСкалярный / ExecuteScalar ODBCRecordSet :: ВыполнитьИнструкцию / ExecuteStatement Синтаксис: ВыполнитьИнструкцию([ТекстЗапроса], [ОбъектРезультатов], [Очищать]) Параметры: ТекстЗапроса - тип: Строка. Текст запроса, если пустая строка - запрос считается параметризированным. Необязателен, по умолчанию - пустая строка. ОбъектРезультатов - тип: любой из ТаблицаЗначений, СписокЗначений, ИндексированнаяТаблица или наследник от любого из них. (Это должен быть объект какого-либо из перечисленных типов, а не объект, реализующий их интерфейс.) Если параметр передан, то он и будет возвращаемым значением. Необязателен, по умолчанию пустое значение, в этом случае будет возвращен объект типа ТаблицаЗначений. Очищать - тип: Число. 1 - очистить переданный ОбъектРезультатов и создать колонки если его тип ТаблицаЗначений или ИндексированнаяТаблица. 0 - не очищать. Необязателен, по умолчанию - 1. Возвращает: тип: ТаблицаЗначений, СписокЗначений, ИндексированнаяТаблица или наследник от любого из них, Число. Объект с результатом запроса, или число - количество обработанных строк. Описание: Выполняет SQL запрос, при ошибке парсинга или при ошибке на ODBC драйвере формируется исключение. Если запрос возвращает набор строк, метод возвращает объект с результатом запроса, если запрос не возвращает набор строк (не select, а DML или прочий) - возвращается количество обработанных строк. Если запрос содержит несколько SQL инструкций (multistatement batch), результаты возвращаются только от первой инструкции. Однако, на драйвер уходит весь текст запроса (По спецификации ODBC, будут ли выполнены остальные инструкции в пакете - зависит от драйвера. Для драйвера SQL Server они выполняются), остальные результаты игнорируются. Если запрос возвращает набор данных, и в наборе данных нет ни одной строки - это не является ошибкой. Если запрос не параметризированный - метод гарантированно закрывает курсор. Если передан ОбъектРезультатов типа ТаблицаЗначений или ИндексированнаяТаблица или наследник и параметр Очишать = 0, то колонки объекта и поля результата совмещаются по порядку. Если передан ОбъектРезультатов типа СписокЗначений, то значения из первого поля результата помещаются в значения списка. Если существует второе поле результата и оно типа Строка, то значения этого поля помещается в представление списка. Если существует третье поле результата и оно типа Число, то значения этого поля помещается в признак пометки значений. или это: 1C++ :: Прямой доступ через ODBC | Ранее: ВыполнитьИнструкцию / ExecuteStatement | Далее: ВыполнитьXML / ExecuteXML ODBCRecordSet :: ВыполнитьСкалярный / ExecuteScalar Синтаксис: ВыполнитьСкалярный([ТекстЗапроса]) Параметры: ТекстЗапроса - тип: Строка. Текст запроса, если пустая строка-запрос считается параметризированным. Необязателен, по умолчанию - пустая строка. Возвращает: тип: Любой, Структура. Если значение поля результата запроса, или зачения полей результата запроса. Описание: Выполняет SQL запрос, при ошибке парсинга или при ошибке на ODBC драйвере формируется исключение. Запрос может возвращать количество обработанных строк: в этом случае возвращается это значение. Запрос может возвращать набор данных, состоящий из одной строки, при этом если в наборе данных одна колонка - возвращается значение из нее, если запрос возвращает несколько колонок - возвращается объект Структура, заполненный полями и именами ключей, соответствующими именам колонок и значениями из этих колонок. Если запрос возвращает набор данных, и в наборе данных нет ни одной строки - это не является ошибкой, в этом случае возвращается пустое значение типа, определенного в первой колонке, или объект Структура, заполненный соответствующим образом. Если запрос не параметризированный - метод гарантированно закрывает курсор. |
|||
26
Walter69y
02.09.12
✎
20:00
|
Спасибо за наводку про ВыполнитьИнструкцию.
Где-то тут есть ошибка при выполнении запроса через ВыполнитьИнструкцию получаю ошибку. Meta name parseer error: Не указан параметр ":Номер", в чем проблема, где можно найти решение? Проблема с корректным обращением к значению в базе SQL? Где взять верное обращение к записи? Текст = "select top 1 * from $Документ.Квитанция as d1 (nolock) |inner join _1sjourn as jj (nolock) on jj.iddoc = d1.iddoc where $d1.Номер = :Номер and jj.docno <> :НомерДок and d1.iddoc <> :iddoc |" ; |
|||
27
Злопчинский
02.09.12
✎
21:37
|
если отстуствует создание документов программным образом, т.е. только интерактивным пользователями. я бы проуерку перенес в ПриЗаписи, нахрен она в модуле првоедения? тем более нахрен такую проверку делать при перепроведении групповом..
|
|||
28
Cthulhu
02.09.12
✎
22:03
|
тю. в графу отбора и выбратьпозначению.
|
|||
29
Злопчинский
02.09.12
✎
22:09
|
(28) тссс. не шурши! весь дом с ритма сбиваешь!
|
|||
30
Злопчинский
02.09.12
✎
22:10
|
||||
31
Cthulhu
02.09.12
✎
22:11
|
(29): да, точно, нуивонаф штатные методы.
|
|||
32
Walter69y
02.09.12
✎
23:19
|
Я еще больше путаюсь. У меня совсем туго с написанием кода. Пусть эта проверка пока работает при проведении. Только пусть заработает. Может кто-то показать пальцем, где конкретно не так и как сделать правильно?
Необходимо принять экстренные меры, а затем уже можно это сколько угодно доводить до совершенства. |
|||
33
КонецЦикла
02.09.12
✎
23:26
|
Предусмотрена ситуация, когда пометку удаления снимут? :)
|
|||
34
Cthulhu
02.09.12
✎
23:30
|
(32): может. незабесплатно.
|
|||
35
Ёпрст
03.09.12
✎
09:21
|
(26) кури УстановитьТекстовыйПараметр
http://www.1cpp.ru/docum/icpp/html/ODBC.html#settextparam |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |