Создать временную таблицу в PL / SQL - PullRequest
6 голосов
/ 11 августа 2010

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

Если бы это был T-SQL, я бы сделал это примерно так:

CREATE TABLE #PatientIDs (
  pId int
)

INSERT INTO #PatientIDs
  select distinct pId from appointments

SELECT * from Person WHERE Person.pId IN (select pId from #PatientIDs)

SELECT * from Allergies WHERE Allergies.pId IN (select pId from #PatientIDs)

DROP TABLE #PatientIDs

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

(Кстати, вместо того, чтобы запускать это как один сценарий, я, вероятно, открою сеанс в Oracle SQL Developer, создаю временную таблицу, а затем запускаю каждый запрос из нее, экспортируя их в CSV по мере продвижения. работать?)

Ответы [ 3 ]

12 голосов
/ 11 августа 2010

Oracle имеет временные таблицы, но они требуют явного создания:

create global temporary table...

Данные во временной таблице являются частными для сеанса, который ее создал, и могут быть специфичными для сеанса или для конкретной транзакции.Если данные не должны быть удалены до завершения сеанса, вам необходимо использовать ON COMMIT PRESERVE ROWS в конце оператора create.Для них также нет отката или поддержки коммита ...

Я не вижу необходимости в временных таблицах в приведенном вами примере - есть риск, что обновления, внесенные в таблицу APPOINTMENTS, так как временная таблица заполнялась, выигралине должно быть отражено.Используйте IN / EXISTS / JOIN:

SELECT p.* 
  FROM PERSON p
 WHERE EXISTS (SELECT NULL
                 FROM APPOINTMENTS a
                WHERE a.personid = a.id)

SELECT p.* 
  FROM PERSON p
 WHERE p.personid IN (SELECT a.id
                        FROM APPOINTMENTS a)

SELECT DISTINCT p.* 
  FROM PERSON p
  JOIN APPOINTMENTS a ON a.id = p.personid

Объединение рисков дубликатов, если с одной записью PERSON связано несколько записей APPOINTMENT, поэтому я добавил DISTINCT.

6 голосов
/ 12 августа 2010

Oracle не имеет возможности случайно создавать временные таблицы так же, как SQL Server.Вы должны явно создать таблицу в схеме базы данных (create global tempory table).Это также означает, что вам необходимы разрешения, позволяющие создавать таблицы, и сценарий должен быть явно развернут как изменение базы данных.Таблица также видна в глобальном пространстве имен.

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

Идиоматический PL / SQL гораздо быстрее выпадает на процедурный код, и вам, вероятно, будет лучше сделать это, чем пытаться подделывать временные таблицы.Обратите внимание, что PL / SQL имеет ориентированные на производительность конструкции, такие как управление потоком для явной параллельной обработки курсоров и вложенных наборов результатов (выражений курсора);последние версии имеют JIT-компилятор.

У вас есть доступ к ряду инструментов для быстрого выполнения процедурного кода PL / SQL, и это, возможно, идиоматическое программирование на PL / SQL.Базовая парадигма несколько отличается от T-SQL, и подход к временным таблицам является одним из основных моментов, когда архитектура системы и идиомы программирования отличаются.

5 голосов
/ 12 августа 2010

Хотя точная проблема была решена, если вы хотите приобрести некоторые полезные навыки в этой области, я бы взглянул на коллекции PL / SQL, и особенно на массовые операции SQL с использованием коллекций pl / sql (BULK COLLECT / BulkСвязывает), предложение RETURNING и определение коллекций с использованием% ROWTYPE.

Вы можете значительно сократить объем кода pl / sql, который вы пишете, понимая все вышеизложенное, хотя всегда помните, что решение полностью на SQL практическивсегда бить PL / SQL один.

...