Табличное поле в 1С++

Автор АЛьФ, 11 марта 2024, 09:07

« назад - далее »

АЛьФ

На работе активно использую ТабличноПоле из 1С++. Всегда вызывает заморочки, когда в основе поля лежит сложный запрос со множеством условий. В основном приходилось делать в качестве поставщика таблицу значений. Нигде не встречал подталкивания к простейшей мысли - использовать временную таблицу. Как-то у меня в голове сидело, что временная таблица работает в рамках одного запроса. Инерция мышления.
И вот когда в очередной раз возникла задача со сложным запросом, вдруг решил проверить - а как поведет себя временная таблица? А она хорошо себя повела. Выбрал предварительно данные во временную таблицу, а потом в табличном поле можно уже вертеть, как угодно и накладывать дополнительные фильтры. Все просто летает. И не нужны лишние заморочки с таблицей значений.
Это я просто делюсь опытом.

trad

Табличные переменные (declare @tab table(...)) живут в рамках запроса.
Временные таблицы #tab живут до конца создавшего сеанса или до явного удаления.
Временные таблицы ##tab живут до конца всех сеансов или до явного удаления.
Временные таблицы, ставшие ненужными, особенно если они большие, желательно удалять. И тут главное уловить момент когда это сделать.
Просто делюсь

АЛьФ

Цитата: trad от 11 марта 2024, 09:30Табличные переменные (declare @tab table(...)) живут в рамках запроса.
Временные таблицы #tab живут до конца создавшего сеанса или до явного удаления.
Временные таблицы ##tab живут до конца всех сеансов или до явного удаления.
Временные таблицы, ставшие ненужными, особенно если они большие, желательно удалять. И тут главное уловить момент когда это сделать.
Просто делюсь

Может подскажешь один момент.
У нас перед всеми запросами со временными таблицами добавляется такой код:
IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID(N'[tempdb].[dbo].[#<ИмяВременнойТаблицы>]')) DROP TABLE #<ИмяВременнойТаблицы>
Код этот был еще со времен Rainbow. Но он как-то странно работает. Вроде таблица очищается, но вот если меняется структура временной таблицы (добавляем колонку), то стабильно получаем "invalid column name". Приходится перезапускать 1C.
В чем дело?

Злоп

Цитата: trad от 11 марта 2024, 09:30до конца создавшего сеанса
а что такое "сеанс" и когда он "кончается"..?

trad

В случае семерки, один клиентский процесс 1cv7s.exe - это одно подключение/сеанс
(ну если конечно других подключений из этого процесса не сделано через ADO/1c++)
Ну, вот когда клиентский процесс кончается тогда и подключение/сеанс тоже.

зы
Прямые запросы 1c++ по умолчанию используют нативное подключение клиентского процесса 1cv7s.exe

trad

Цитата: АЛьФ от 11 марта 2024, 09:52Вроде таблица очищается, но вот
этим кодом таблица должна удаляться, а не очищаться

А по существу, проверь чему равно ИмяВременнойТаблицы. Возможно там уже есть #
В итоге получается ##

Хотя нет, не похоже на это, таблица же вроде удаляется. Тогда у меня нет ответа

trad

Я создаю временные таблицы так:
   |set nocount on
   |if exists (select * from tempdb..sysobjects where id = object_id('tempdb..%Имя%') and sysstat & 0xf = 3)
   |  drop table %Имя%;
   |create table %Имя% ...

, где %Имя% это #имяВТ или ##имяВТ

АЛьФ

Какие-то значит наши внутренние заморочки в настройках.

trdm

Сегодня 8-ку вспомнил, решил попробовать:
ТекстЗапроса = "
	|-- рабочие запросы
	|SELECT TOP 4
	|	спрФирмы.ID, спрФирмы.DESCR
	|INTO #ТаблицаФирм3	
	|FROM $Справочник.Фирмы as спрФирмы (NOLOCK)
	|WHERE спрФирмы.ISMARK = 0
	|
	|; -- можно и GO использовать, результат будет тем же..
	|
	|-- Drop table #ТаблицаФирм3
	|SELECT top 50
	|	*
	|FROM $Регистр.ПартииТоваров as спрПартии(NOLOCK)
	|WHERE $спрПартии.Фирма IN (SELECT ID FROM #ТаблицаФирм3)
	|";
запрос рабочий, только надо после его отработки уничтожать таблицу.

пикча https://disk.yandex.ru/i/3-EmXEfapU-UMA

Злоп

Вообще ничего не понял.
При чем здесь 8?
.
В чем суть? Чем я, неискушенный в прямых запросах, должен проникнуться?

trdm

Цитата: Злоп от 19 марта 2024, 23:31В чем суть?
Просто я открыл для себя связку Select ... Into в прямых запросах и пакетные запросы в 1С++ :) спустя 10 лет :)

ну бывает, чё... :)

trad

используя пакетные запросы нужно не забывать про set nocount on

trad

Цитата: trdm от 19 марта 2024, 20:34запрос рабочий, только надо после его отработки уничтожать таблицу.
конкретно в этом случае можно использовать табличную переменную. Тогда и дропать не нужно

|set nocount on
|declare @ТаблицаФирм3 table(ID char(9), DESCR varchar(100), primary key(id))
|
|insert into @ТаблицаФирм3
|SELECT TOP 4
|   спрФирмы.ID, спрФирмы.DESCR
|FROM $Справочник.Фирмы as спрФирмы (NOLOCK)
|WHERE спрФирмы.ISMARK = 0
|
|SELECT top 50
|   *
|FROM $Регистр.ПартииТоваров as спрПартии(NOLOCK)
|WHERE $спрПартии.Фирма IN (SELECT ID FROM @ТаблицаФирм3)

АЛьФ

Цитата: trad от 20 марта 2024, 11:21
Цитата: trdm от 19 марта 2024, 20:34запрос рабочий, только надо после его отработки уничтожать таблицу.
конкретно в этом случае можно использовать табличную переменную. Тогда и дропать не нужно

Тогда возникает другая проблема - полное описание таблицы. Зачастую временные таблицы используются с разным набором колонок. И прописывать их каждый раз явно - мрак.

trdm

Цитата: АЛьФ от 20 марта 2024, 11:24Тогда возникает другая проблема - полное описание таблицы. Зачастую временные таблицы используются с разным набором колонок. И прописывать их каждый раз явно - мрак.
Вот именно. Так что SELECT ... INTO #ИмяТаблицы гораздо изящнее.
Только добавить вверху запроса конструкции IF EXIST .. Drop TABLE
А еще лучше модернизировать ODBCRecordset для уничтожения таблиц после запроса.
В принципе можно и унаследоваться и обабатывать "После"ВыполнитьИнструкцию() и т.п.