Решил опять попробовать разобраться почему не удаляются временные таблицы. Набросал такой вот запросик:
ТекстЗапроса = "
|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С++ можно запрос разбить аналогичным образом? Или только вручную резать текст запроса на части?
резать на части
Первой строкой в запросе поставить SET NOCOUNT ON не пробовали?
Цитата: vladmenleo от 10 октября 2024, 12:51Первой строкой в запросе поставить SET NOCOUNT ON не пробовали?
Пробовали. Все та же ошибка "There is already..." еще на этапе до начала выполнения запроса.
Есть еще нюанс. Если первое обращение вылетело с ошибкой, то временная таблица там останется, до какого времени не знаю, возможно до перезапуска сервера. Т.е. нужно сделать так: первая строка SET NOCOUNT ON, и заменить имя временной таблицы например на #ВременнаяНовая. Должно взлететь
Цитата: vladmenleo от 10 октября 2024, 16:27Есть еще нюанс. Если первое обращение вылетело с ошибкой, то временная таблица там останется, до какого времени не знаю, возможно до перезапуска сервера. Т.е. нужно сделать так: первая строка SET NOCOUNT ON, и заменить имя временной таблицы например на #ВременнаяНовая. Должно взлететь
Именно на случай, если осталась временная таблица, в начале и стоит DROP. Но получается, что он не выполняется нормально. И NOCOUNT проблему не решает.
Мы вообще с этим начали разбираться из-за того, что иногда временная таблица создается в одном запросе (отчете), а потом в другом используется таблица с таким же именем, но другой структурой и получаем ошибку типа "нет такой колонки". Лечится перезаходом пользователя, но хотелось бы как-то проблему все же решить.
Как прямой вариант, добавить соль к имени таблицы.
Цитата: АЛьФ от 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 #Временная
|";
тзВыборка = глПрямойЗапрос.ВыполнитьИнструкцию(ТекстЗапроса);
вот только запрос вернет последний результат.
Цитата: 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".
латиницу попробуй.
+ там имя не "#Временная" получается, а что-то вроде "#Временная 12121".
так что на равенство не особо надейся.
короче там все непросто. но победимо..
Не понял по поводу латиницы. Ошибка "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.
Цитата: trdm от 13 октября 2024, 23:20в odbcrecordset (на скуле) разделитель запросов ";"
Нету там такого разделителя
Тут одно решение - резать выполнение на части
Пожалуй соглашусь с #11, про mssql не уверен, но sqlite (а это я точно знаю) не умеет отслеживать предпологаемое изменение состава таблиц, т.е. каждый отдельный запрос в блоке запросов видит только первоначальное состояние таблиц, и не пытается понять динамику изменений внутри блока запросов.
Т.е. drop table и create table надо выносить за блоки запросов.
Цитата: trad от 15 октября 2024, 09:25Нету там такого разделителя
Верно, это в T-SQL он такой есть.
Цитата: АЛьФ от 14 октября 2024, 14:28Нет, все та же ошибка "There is already an object".
Верно, сори.
Дело в том, что я использовал консоль QA.ert, а там у меня есть обработка ";" и "GO", запросы делаются раздельно.
А если выполнять текст запроса так:
Запрос = СоздатьОбъект("ODBCRecordSet");
тзВыборка = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
то ошибка та-же.