Разработчик Sybase спрашивает: как создать временную таблицу в Oracle?

Я знаком с сервером Sybase/SQL, где могу создать временный файл. такая таблица:

SELECT * 
INTO   #temp
FROM   tab1 , 
       tab2 
WHERE  tab1.key = tab2.fkey

SELECT * 
FROM   #temp 
WHERE  field1 = 'value' 

#temp существует только в течение этого сеанса и может быть виден только мне.

Я хотел бы сделать то же самое в Oracle, но я читаю о «глобальных временных таблицах», которые звучат не так, как одно и то же.

Как я могу сделать в Oracle то же самое, что и в Sybase?

Спасибо :)


person AJ.    schedule 21.10.2008    source источник


Ответы (6)


Ваш первый подход должен заключаться в том, чтобы сделать это как один запрос:

SELECT * 
FROM   
(
SELECT * 
FROM   tab1 , 
       tab2 
WHERE  tab1.key = tab2.fkey
)
WHERE  field1 = 'value';

В очень сложных ситуациях или когда temp# очень велик, попробуйте предложение факторинга подзапроса, необязательно с подсказкой материализации:

with #temp as
(
SELECT /*+ materialize */ 
       * 
FROM   tab1 , 
       tab2 
WHERE  tab1.key = tab2.fkey
)
SELECT * 
FROM   temp#
WHERE  field1 = 'value';

Если это не помогает, перейдите к методу Global Temporary Table.

person David Aldridge    schedule 22.10.2008

Глобальная временная таблица уже не та, определение остается после окончания сеанса, также таблица (но не данные) видна всем сеансам.

Если вы пишете хранимые процедуры, изучали ли вы курсоры? Это немного сложнее, но очень эффективный и понятный способ работы с временным набором данных.

person Colin Pickard    schedule 21.10.2008
comment
Пользователи Sybase часто избегают использования курсоров из соображений производительности. Я не уверен, было ли это исторически верным, но сейчас это не так, или это оправдано, но это, конечно, не проблема с использованием Oracle. - person Stephen Darlington; 21.10.2008
comment
Топ ответ. Спасибо за предложение курсоров. Я думаю, мне придется найти способ жить с глобальной временной таблицей. Наверное, в этом есть свои преимущества. Мне просто нужно выяснить, что они из себя представляют! ;) - person AJ.; 21.10.2008
comment
Ну, вы можете получить небольшое преимущество в производительности, если не будете создавать таблицу каждый раз :) Еще одна вещь, которая пришла мне в голову, для вашего первого примера, если вам просто нужен один столбец для каждой из двух таблиц, вы можете вместо этого рассмотреть представление. - person Colin Pickard; 21.10.2008

Oracle не предоставляет прямого аналога этой возможности. Глобальная временная таблица аналогична, но она должна быть создана заранее, и ее может быть трудно изменить в дальнейшем из-за проблем с блокировкой.

Большинство потребностей такого рода можно удовлетворить с помощью курсоров или одного из различных типов коллекций pl/sql (вложенные таблицы, varrays, ассоциативные массивы), но ни один из них нельзя использовать так, как если бы они были таблицей. То есть вы не можете выбрать из них.

person Noah Yetter    schedule 21.10.2008

Я считаю, что глобальные временные таблицы одинаковы. Они дадут вам частный доступ к временной таблице, которая умирает, когда сеанс заканчивается:

Данные в глобальной временной таблице являются частными, поэтому данные, вставленные сеансом, могут быть доступны только этому сеансу. Специфичные для сеанса строки в глобальной временной таблице могут быть сохранены для всего сеанса или только для текущей транзакции. Предложение ON COMMIT DELETE ROWS указывает, что данные должны быть удалены в конце транзакции.

Прочитав вопрос еще несколько раз, я считаю, что это главное отличие, и, возможно, ваша проблема в том, что временные таблицы сохраняются между сеансами. Таким образом, точный эквивалент невозможен, как вы можете себе представить в Oracle, это будет что-то вроде:

CREATE GLOBAL TEMPORARY TABLE my_temp_table ON COMMIT DELETE ROWS select * from other table;

Эта таблица будет жить до тех пор, пока она не будет удалена даже через сеансы, хотя данные в ней не удаляются. Вместо этого вам нужно будет создать временную таблицу заранее.

person carson    schedule 21.10.2008
comment
Я бы не сказал, что они одинаковы, так как вы должны явно создавать и удалять глобальную временную таблицу, но они являются лучшей функцией Oracle для этой цели, насколько мне известно. - person Dave Costa; 21.10.2008
comment
на самом деле ON COMMIT PRESERVE ROWS было бы ближе к тому, что он хочет, так как его таблица sybase существует для остальной части сеанса. ON COMMIT DELETE ROWS усекается в конце транзакции (аналогично выполнению отката) - person Colin Pickard; 21.10.2008

Модель временной таблицы в Oracle несколько отличается и сосредоточена на операторе «CREATE GLOBAL TEMPORARY TABLE..». Определения временных таблиц всегда являются глобальными, но данные всегда являются частными для сеанса, и то, сохраняются ли данные во время фиксации, зависит от того, указана ли квалификация «при фиксации сохранить строки» или «при фиксации удалить строки».

У меня есть несколько сценариев Perl и сообщение в блоге, в котором исследуется конкретное поведение или временные таблицы Oracle на мой блог.

person tardate    schedule 22.10.2008

Да, Карсон прав. Глобальные временные таблицы видны только создавшему их сеансу и исчезают либо при первой фиксации или откате, либо в конце сеанса. Вы можете установить это при создании файла gtt.

person Jim Hudson    schedule 21.10.2008
comment
Строго говоря: данные, вставленные в таблицу, видны только в сеансе и исчезают в конце транзакции или сеанса. Таблица видна любому сеансу в схеме. Вот почему он глобальный. - person Dave Costa; 21.10.2008