Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Как создается временная таблица?  [new]
LionHeart
Member

Откуда: Киев
Сообщений: 19
Такая проблема:

из программы вызываю 2 запроса (все это в одной транзакции):
1. CREATE TABLE #tmp (...); INSERT INTO #tmp VALUES(...)
2. EXEC MyStoredProc

внутри MyStoredProc есть обращения к #tmp.

ИНОГДА (достаточно часто) хранимая процедура вылетает по ошибке "Не существует таблицы #tmp".
/*Такое впечатление, что временные таблицы создаются не сразу, с некоторым интервалом, в 2й запрос выполняется через другой поток, и добирается до обращения к #tmp раньше процесса, который завершит ее создание.*/

Как с этим бороться?
Спасибо
11 июн 03, 14:53    [228354]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
GreenSunrise
Member

Откуда:
Сообщений: 12310
Создание таблицы и обращение к ней должны быть в разных batch'ах.
11 июн 03, 14:54    [228359]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
jimmers
Member

Откуда: Санкт-Петербург - New York City
Сообщений: 5069
Создание таблицы и обращение к ней должны быть в разных batch'ах.

Откуда такая информация?
11 июн 03, 14:59    [228366]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
tpg
Member

Откуда: Novosibirsk
Сообщений: 23902
А внутри MyStoredProc проверка на существование временной таблицы есть?
11 июн 03, 15:06    [228375]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
LionHeart
Member

Откуда: Киев
Сообщений: 19
если запустить одной строкой:
CREATE TABLE #tmp (...);
INSERT INTO #tmp (...);
EXEC MyProc
DROP TABLE #tmp

то все нормально
проблема когда я запускаю разными запросами (просто последовательные вызовы через ADO под MTS)

2 jimmers:
информация из практики (пробую прямо сейчас)
11 июн 03, 15:08    [228379]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
tpg
Member

Откуда: Novosibirsk
Сообщений: 23902
Вот и создай хранимую процедуру с текстом
CREATE PROCEDURE dbo.RunMyProc

CREATE TABLE #tmp (...)
INSERT INTO #tmp (...)
EXEC MyProc

и пинай её через ADO
11 июн 03, 15:13    [228383]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
LionHeart
Member

Откуда: Киев
Сообщений: 19
2 tgp:
Нет. По логике работы процедуры такая таблица ОБЯЗАТЕЛЬНО должна быть.
11 июн 03, 15:15    [228385]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
LionHeart
Member

Откуда: Киев
Сообщений: 19
вариант в рамке - подходит так и придется сделать
спа
11 июн 03, 15:23    [228397]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74925
2 LionHeart

просто последовательные вызовы через ADO

Вот в этом и проблема, IMHO Каждый твой из последовательных вызовов (CREATE TABLE #... в том числе) заварачивается в sp_executesql, что является отдельным бачем. Можешь посмотреть профайлером. Ты ведь, наверно, инструкцию на создание временной таблицы выполняешь через Command. Попробуй выполнить ее через Connection.Execute. Тогда она не завернеться в sp_executesql. Во всяком случаи в Delphi так работает.
11 июн 03, 15:26    [228400]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
GreenSunrise
Member

Откуда:
Сообщений: 12310
2jimmers: сорри, гоню однозначно. беру свои слова назад.
11 июн 03, 16:05    [228495]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
ziktuw
Member

Откуда:
Сообщений: 3552
Я думаю, причина в том, что приложение шлет перед вызовом процедуры следующий код:
SET FMTONLY ON exec MyStoredProc SET FMTONLY OFF,
в чем можно легко убедиться, заглянув профайлер.
Такая конструкция действительно может давать вышеуказанную ошибку.

Чтобы избежать ошибки, можно сделать так:
вместо "EXEC MyStoredProc" выполнять из приложения
"SET FMTONLY OFF EXEC MyStoredProc"
11 июн 03, 16:18    [228520]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
ziktuw
Member

Откуда:
Сообщений: 3552
А еще такую ошибку может давать то обстоятельство, что ADO часто создает доп. коннект для выполнения запроса, если основной коннект занят чем-нибудь другим. Естественно, второй временный коннект не имеет понятия о временной таблице, созданной в первом коннекте.

Чтобы свести к минимуму такую ошибку в данном случае, надо придерживаться следующего правила: открывать курсор только клиентский. (чтобы основной коннект не был занят недофетченной выборкой)
11 июн 03, 16:23    [228526]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
GreenSunrise
Member

Откуда:
Сообщений: 12310
2Dankov: это точно???? Проверенная информация? Честно говоря, верится с трудом, иначе как писать приложения в условиях, когда ты не знаешь, внутри одного и того же коннекта выполняются несколько последовательных операций? Сомнительно...
Может быть, вы имеете в виду, что если создавать объект Command, то он будет неявно порождать Connection, если ему в конструкторе не указан существующий?
11 июн 03, 16:35    [228551]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
LionHeart
Member

Откуда: Киев
Сообщений: 19
Всем спасибо!
Я всегда создавал новый коннекшн при обращении к базе (в том же MTS-объекте с Requires Transaction) и вызывал через Command с этим коннекшином. Если запросы выполнять последовательно с малым интервалом времени, то второй коннекшн еще не видит таблицы, созданной в первом (запуск через ADOCommand). Если же один запрос выполнять через несколько секунд после другого (например, подержать BreakPoint), то все нормально, так что разные коннекшины в одной транз. все видят.
Решил просто через единый коннекшн.
11 июн 03, 17:01    [228608]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
MiCe
Member

Откуда: RUSSIA STAVROPOL Pyatigorsk
Сообщений: 1996
2GreenSunrise
дорогая... как это ни прискорбно, но Dankov прав...
11 июн 03, 17:36    [228662]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
GreenSunrise
Member

Откуда:
Сообщений: 12310
2MiCe: милый, милый... как теперь жить, во что верить? никакого постоянства в этом мире ;-) коннекты и те изменяют............

А если серьезно - дайте ссылочку в хелпе почитать, если есть. Уж больно инфа неожиданная, хочу своими глазами увидеть.
11 июн 03, 17:43    [228668]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
ziktuw
Member

Откуда:
Сообщений: 3552
>GreenSunrise

Это точно. В этом ты можешь сама легко убедиться. Делай так: открывай динамический серверный курсор с большой ожидаемой выборкой, но не фетчи его до конца естественно. И через тот AdoConnection пусти запрос любой. В профайлере или чтением sysprocesses лови. Увидишь вторую сессию. Таким образом ADO обходит ограничение протокола TDS - невозможность делать одновременно параллельные операции.
11 июн 03, 17:47    [228678]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
GreenSunrise
Member

Откуда:
Сообщений: 12310
Почти уговорили, позже посмотрю. Скажите, а по какому принципу будет открыт или нет новый коннект? Наличие недофетченного рекордсета? Долгое выполнение запроса? (абсурд. что считается долгим? в чем измеряется).

Иными словами, если я пишу приложение, где у меня стоит создание временной таблицы и заполнение ее чем-либо, потом выборка из базы (не обязательно в эту временную таблицу), а потом какие-то еще действия с этой временной таблицей, мне нужно заранее знать, удовлетворяет ли моя выборка каким-то критериям, по которым для следующих действий будет открыт или нет новый коннект? Что-то уж очень сложно выходит...
11 июн 03, 18:00    [228690]     Ответить | Цитировать Сообщить модератору
 Re: Как создается временная таблица?  [new]
ziktuw
Member

Откуда:
Сообщений: 3552
Собственно, потому и не стоит делать временные таблицы уровня сессии, а стоит ими пользоваться только внутри процедур (вместе с созданием).

Еще интересней случается, если так красочно описанную мною ситацию немного усложнить - завернуть те вызовы в явную транзакцию. ADO при этом генерит совершенно замечательную ошибку - что-то типа "не могу начать новую сессию по причине явной транзакции".

Избежать, кстати, такой ситуации легко. Всего 2 правила:
1. фетчить все до конца сразу же
2. не обращаться к одному объекту Connection из разных потоков или, по крайней мере, эти действия синхронизировать и упорядочивать.
11 июн 03, 19:35    [228801]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить