Форум Кладовочки АЛьФ`а

Общие вопросы => 7.7 => Тема начата: АЛьФ от 09 октября 2024, 12:32

Название: Выполнения пакета запросов в 1С++
Отправлено: АЛьФ от 09 октября 2024, 12:32
Решил опять попробовать разобраться почему не удаляются временные таблицы. Набросал такой вот запросик:
ТекстЗапроса = "
|IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID(N'[tempdb].[dbo].[#Временная]')) DROP TABLE #Временная
|
|SELECT ID
|INTO #Временная
|FROM Справочник_РегионыПрайса
|
|IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID(N'[tempdb].[dbo].[#Временная]')) DROP TABLE #Временная
|
|SELECT DESCR
|INTO #Временная
|FROM Справочник_РегионыПрайса
|
|SELECT *
|FROM #Временная
|";

тзВыборка = глПрямойЗапрос.ВыполнитьИнструкцию(ТекстЗапроса);

При попытке выполнить получаю ошибку:
There is already an object named '#Временная' in the database.
Отсюда сделал вывод, что SQL сначала создает временные таблицы, а потом их заполняет. И дроп посреди запроса похоже игнорируется, если таблица ранее уже встретилась.

В Menagement Studio проблема решается разбитием запроса с помощью "GO".
Как-то в 1С++ можно запрос разбить аналогичным образом? Или только вручную резать текст запроса на части?
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: trad от 10 октября 2024, 12:07
резать на части
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: vladmenleo от 10 октября 2024, 12:51
Первой строкой в запросе поставить SET NOCOUNT ON не пробовали?
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: АЛьФ от 10 октября 2024, 15:59
Цитата: vladmenleo от 10 октября 2024, 12:51Первой строкой в запросе поставить SET NOCOUNT ON не пробовали?

Пробовали. Все та же ошибка "There is already..." еще на этапе до начала выполнения запроса.
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: vladmenleo от 10 октября 2024, 16:27
Есть еще нюанс. Если первое обращение вылетело с ошибкой, то временная таблица там останется, до какого времени не знаю, возможно до перезапуска сервера. Т.е. нужно сделать так: первая строка SET NOCOUNT ON, и заменить имя временной таблицы например на #ВременнаяНовая. Должно взлететь
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: АЛьФ от 11 октября 2024, 11:19
Цитата: vladmenleo от 10 октября 2024, 16:27Есть еще нюанс. Если первое обращение вылетело с ошибкой, то временная таблица там останется, до какого времени не знаю, возможно до перезапуска сервера. Т.е. нужно сделать так: первая строка SET NOCOUNT ON, и заменить имя временной таблицы например на #ВременнаяНовая. Должно взлететь
Именно на случай, если осталась временная таблица, в начале и стоит DROP. Но получается, что он не выполняется нормально. И NOCOUNT проблему не решает.
Мы вообще с этим начали разбираться из-за того, что иногда временная таблица создается в одном запросе (отчете), а потом в другом используется таблица с таким же именем, но другой структурой и получаем ошибку типа "нет такой колонки". Лечится перезаходом пользователя, но хотелось бы как-то проблему все же решить.
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: Arbuz от 11 октября 2024, 17:51
Как прямой вариант, добавить соль к имени таблицы.
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: trdm от 13 октября 2024, 23:20
Цитата: АЛьФ от 09 октября 2024, 12:32В Menagement Studio проблема решается разбитием запроса с помощью "GO".

в odbcrecordset (на скуле) разделитель запросов ";"
ТекстЗапроса = "
    |IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID(N'[tempdb].[dbo].[#Временная]')) DROP TABLE #Временная
    |;
    |SELECT ID
    |INTO #Временная
    |FROM Справочник_РегионыПрайса
    |;
    |IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID(N'[tempdb].[dbo].[#Временная]')) DROP TABLE #Временная
    |;
    |SELECT DESCR
    |INTO #Временная
    |FROM Справочник_РегионыПрайса
    |;
    |SELECT *
    |FROM #Временная
    |";
   
    тзВыборка = глПрямойЗапрос.ВыполнитьИнструкцию(ТекстЗапроса);

вот только запрос вернет последний результат.
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: АЛьФ от 14 октября 2024, 14:28
Цитата: trdm от 13 октября 2024, 23:20
Цитата: АЛьФ от 09 октября 2024, 12:32В Menagement Studio проблема решается разбитием запроса с помощью "GO".

в odbcrecordset (на скуле) разделитель запросов ";"
ТекстЗапроса = "
    |IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID(N'[tempdb].[dbo].[#Временная]')) DROP TABLE #Временная
    |;
    |SELECT ID
    |INTO #Временная
    |FROM Справочник_РегионыПрайса
    |;
    |IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID(N'[tempdb].[dbo].[#Временная]')) DROP TABLE #Временная
    |;
    |SELECT DESCR
    |INTO #Временная
    |FROM Справочник_РегионыПрайса
    |;
    |SELECT *
    |FROM #Временная
    |";
   
    тзВыборка = глПрямойЗапрос.ВыполнитьИнструкцию(ТекстЗапроса);

вот только запрос вернет последний результат.


Нет, все та же ошибка "There is already an object".
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: trdm от 14 октября 2024, 19:35
латиницу попробуй.
+ там имя не "#Временная" получается, а что-то вроде "#Временная        12121".
так что на равенство не особо надейся.
короче там все непросто. но победимо..
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: АЛьФ от 15 октября 2024, 09:12
Не понял по поводу латиницы. Ошибка "There is already an object" вываливается еще до начала выполнения собственно запроса. Я так понимаю, на этапе парсинга.

Вот для чистоты эксперимента код, который должен отработать на любой скульной базе:
ТекстЗапроса = "
|SET NOCOUNT ON
|
|IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID(N'[tempdb].[dbo].[#TMP]')) DROP TABLE #TMP
|;
|SELECT ID
|INTO #TMP
|FROM _1SCONST
|;
|IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID(N'[tempdb].[dbo].[#TMP]')) DROP TABLE #TMP
|;
|SELECT DESCR, ID
|INTO #TMP
|FROM _1SCONST
|;
|SELECT *
|FROM #TMP
|";

Запрос = СоздатьОбъект("ODBCRecordSet");
тзВыборка = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);

Получаем ошибку:
тзВыборка = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
{...\TEST.ERT(22)}: State 42S01, native 2714, message [Microsoft][ODBC SQL Server Driver][SQL Server]There is already an object named '#TMP' in the database.
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: trad от 15 октября 2024, 09:25
Цитата: trdm от 13 октября 2024, 23:20в odbcrecordset (на скуле) разделитель запросов ";"
Нету там такого разделителя

Тут одно решение - резать выполнение на части
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: Djelf от 15 октября 2024, 15:22
Пожалуй соглашусь с #11, про mssql не уверен, но sqlite (а это я точно знаю) не умеет отслеживать предпологаемое изменение состава таблиц, т.е. каждый отдельный запрос в блоке запросов видит только первоначальное состояние таблиц, и не пытается понять динамику изменений внутри блока запросов.
Т.е. drop table и create table надо выносить за блоки запросов.
Название: Re: Выполнения пакета запросов в 1С++
Отправлено: trdm от 15 октября 2024, 18:31
Цитата: trad от 15 октября 2024, 09:25Нету там такого разделителя
Верно, это в T-SQL он такой есть.

Название: Re: Выполнения пакета запросов в 1С++
Отправлено: trdm от 15 октября 2024, 18:56
Цитата: АЛьФ от 14 октября 2024, 14:28Нет, все та же ошибка "There is already an object".

Верно, сори.
Дело в том, что я использовал консоль QA.ert, а там у меня есть обработка ";" и "GO", запросы делаются раздельно.
А если выполнять текст запроса так:
    Запрос = СоздатьОбъект("ODBCRecordSet");
    тзВыборка = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
то ошибка та-же.