2016-02-01 2 views
0

Мой запрос прост, но PL/SQL блок кода ожидает 'INTO'.Создать 'TABLE AS' в PL/SQL-блоке

Вот мой запрос:

DECLARE 

yesterdays_date DATE := SYSDATE-1; 
start_date DATE :='01/JAN/2013'; 

BEGIN  
    EXECUTE IMMEDIATE 'DROP TABLE P2P_DATA'; 
    EXCEPTION  
    WHEN OTHERS THEN   
    IF SQLCODE != -942 THEN  
--if table not found DO NOTHING AND MOVE ON 
--dbms_output.put_line('HELLO'); 
      NULL; 
    END IF; 

---------------------------create new table here------------------- 
CREATE TABLE P2P_DATA AS 
SELECT 
    GM_NAME, 
    NEW_SKILL,  
    WEEK_DATE, 
    TOR_MWF 
FROM TEST_TABLE 
WHERE WEEK_DATE BETWEEN start_date AND yesterdays_date; 

END; 

это дает ошибку во время компиляции:

FOUND CREATE: EXPECTING END SELECT or (BEGIN CASE CLOSE CONTINUE DECLARE ... ETC) 

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

+4

вам нужно будет немедленно выполнить выполнение, чтобы создать таблицу, а также удалить ее. Почему бы просто не усечь стол, а затем вставить в него? Это не SQL-сервер, а при отбрасывании и создании таблиц есть накладные расходы – kevinsky

+0

@kevinsky любой блок кода кода будет оценен – Shery

+2

Я бы просто хотел добавить, я даже не рассматривал бы блок PL/SQL для того, что вы там делаете, вы можете выпустить 'WHENEVER SQLERROR CONTINUE' .. сделайте' DROP', затем выполните 'WHENEVER SQLERROR EXIT sqlcode' ... и выпустите' CREATE' .. с вашими диапазонами дат (переменные здесь действительно не помогают вы много, если не будет намного больше, чем вы показываете?) – Ditto

ответ

3

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

DECLARE 

yesterdays_date DATE := SYSDATE-1; 
start_date DATE :='01/JAN/2013'; 

BEGIN  
--clear out old data------ 
DELETE from P2P_DATA; 

---------------------------insert new data here----------------- 
INSERT INTO P2P_DATA 
SELECT 
GM_NAME, 
CASE WHEN SUBSTR(CST_NAME,0,5) = 'A' 
    THEN 'BVG1' ELSE SUBSTR(CST_NAME,0,5) END AS CST_NAME, 
NEW_SKILL,  
WEEK_DATE, 
TOR_MWF, 
TOR_MA,  
TOR_DL 
FROM TEST_TABLE 
WHERE WEEK_DATE BETWEEN start_date AND yesterdays_date; 

END; 

--do ваша фиксация вне сделки только в случае

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

CREATE VIEW VW_P2P_DATA 
AS 
SELECT 
GM_NAME, 
CASE WHEN SUBSTR(CST_NAME,0,5) = 'A' 
    THEN 'BVG1' ELSE SUBSTR(CST_NAME,0,5) END AS CST_NAME, 
NEW_SKILL,  
WEEK_DATE, 
TOR_MWF, 
TOR_MA,  
TOR_DL 
FROM TEST_TABLE 
WHERE WEEK_DATE BETWEEN TO_DATE('01/JAN/2013','DD/MON/YYYY') AND SYSDATE-1; 
+1

без предложения WHERE', рассмотрите 'TRUNCATE' над' DELETE';) (подсказка: выпустите его непосредственно перед 'DECLARE' за пределами pl/sql block;)), если эта таблица большая, что 'DELETE' может длиться долгое время – Ditto

+0

@Ditto Sure DROP и TRUNCATE являются DDL и не могут быть выполнены внутри блока без немедленного выполнения, которого я пытался избежать. Согласился, что Truncate более чист и не генерирует журналы повтора. – kevinsky

1

Вы не можете выполнять DDL-запросы в блоке PL/SQL; если вам нужно это сделать, вам нужно использовать динамический SQL; Например, вы могли бы использовать:

execute immediate ' 
        CREATE TABLE P2P_DATA AS 
        SELECT 
         GM_NAME, 
         NEW_SKILL,  
         WEEK_DATE, 
         TOR_MWF 
        FROM TEST_TABLE 
        WHERE WEEK_DATE BETWEEN start_date AND yesterdays_date; 
        '; 

Однако, пожалуйста, рассмотреть решения, отличные от создания таблиц/вывода на лету, если вы можете

1

На самом деле, я помещу это как ответ вместо комментария. ..

я бы рекомендовал избегать PL/SQL целиком ... просто сделайте следующее:

truncate table P2P_DATA; 

    insert into P2P_DATA 
    SELECT 
     GM_NAME, 
     NEW_SKILL,  
     WEEK_DATE, 
     TOR_MWF 
    FROM TEST_TABLE 
    WHERE WEEK_DATE BETWEEN to_date('01/JAN/2013','dd/MON/yyyy') AND SYSDATE-1; 

Simpler, чище и быстрее. ;)

+0

, но это может быть запущено только как SQL-скрипт. Я предполагал, но похоже, что это что-то сделано не один раз, возможно даже каждый день, так что бы процедура, которую можно было бы назвать работой, была бы лучше? – kevinsky

+0

@kevinsky: ОП не упоминал ничего о необходимости его в процедуре или такой. И даже это в стороне, это может быть запланировано вне процедуры, как простой sql довольно легко. (если ОП разъясняет необходимость изменения этих входных значений - то есть параметров - тогда да, у нас совершенно другой вопрос);) lol – Ditto

Смежные вопросы