PLS-00306: неверный номер или типы аргументов при вызове ADD_MONTHS - PullRequest
0 голосов
/ 23 февраля 2019

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

create or replace package TEST_TABLE AS
   PROCEDURE TEST_TABLE;
END TEST_TABLE;


create or replace PACKAGE BODY TEST_TABLE AS 
 PROCEDURE TEST_TABLE IS        
 BEGIN
  FOR cc IN
  (
  SELECT partition_name, high_value
  FROM user_tab_partitions
  WHERE table_name = 'TEST_TABLE'
  )    
  LOOP
   BEGIN               
     IF sysdate >= ADD_MONTHS(cc.high_value,2) THEN                  
      EXECUTE IMMEDIATE                     
      'ALTER TABLE TEST_TABLE DROP PARTITION ' || cc.partition_name;                   
       Dbms_Output.Put_Line('Dropping partition is completed.');        
     END IF;
   END;
  END LOOP;

  EXCEPTION WHEN Others THEN Dbms_Output.Put_Line( SQLERRM );

 END TEST_TABLE;

END TEST_TABLE; 

Я получаю ошибку:

Ошибка (12,6): PL / SQL: оператор игнорируется
Ошибка (12,20): PLS-00306: неверноколичество или типы аргументов в вызове 'ADD_MONTHS'

Ответы [ 5 ]

0 голосов
/ 04 марта 2019

Oracle не разрешает функции над длинными, такими как приведение, substr, add_months над типом long, однако ... читайте ниже.

  1. Тип long

    description user_tab_partitions;

    ... SUBPARTITION_COUNT NUMBER
    HIGH_VALUE LONG
    HIGH_VALUE_LENGTH NUMBER
    ...

  2. Функция преобразования длинных в varchar2

    FUNCTIONlong_to_varchar2 (p_table_owner IN VARCHAR2, p_table_name IN VARCHAR2, p_partition_name IN VARCHAR2) Возвращаемый VARCHAR2 имеет длину l_tmp;BEGIN

    выбрать старшее_значение в l_tmp из всех_таблиц_отделов, где table_owner = p_table_owner и table_name = p_table_name и имя_раздела = p_partition_name;

    RETURN l_tmp;END long_to_varchar2;

3.Используйте новую функцию

select tpar."OWNER",tpar."TABLE_NAME",tpar."PART_MIN",tpar."PART_MIN_HV",tpar."PART_MAX",tpar."PART_MAX_HV",tpar."NR_PART"
      ,pkey.column_name as partitioned_by
      ,ptab.partitioning_type as partition_type
      ,ptab.status  
from        
      (select p1.table_owner     as owner
             ,p1.table_name 
             ,pmin.partition_name as part_min
             ,to_date(substr(long_to_varchar2(p1.table_owner,p1.table_name,pmin.partition_name),11,10),'yyyy-mm-dd') as part_min_hv
             ,pmax.partition_name as part_max
             ,to_date(substr(long_to_varchar2(p1.table_owner,p1.table_name,pmax.partition_name),11,10),'yyyy-mm-dd') as part_max_hv
             ,p1.nr_part+1        as nr_part
       from (select min(part.partition_position) as minp
                   ,max(part.partition_position) as maxp
                   ,count(*)                     as nr_part
                   ,part.table_name
                   ,part.table_owner
             from all_tab_partitions part,
                  dba_tables tbls
             where part.table_name=tbls.table_name
             and part.table_owner=tbls.owner
             and part.PARTITION_NAME <> 'P_CURRENT'
             group by part.table_name, part.table_owner) p1
            ,all_tab_partitions pmin
            ,all_tab_partitions pmax
       where p1.table_name = pmin.table_name
       and p1.table_owner = pmin.table_owner
       and p1.minp=pmin.partition_position
       and p1.table_name = pmax.table_name
       and p1.table_owner = pmax.table_owner
       and p1.maxp = pmax.partition_position) tpar
     ,ALL_PART_KEY_COLUMNS pkey
     ,ALL_PART_TABLES      ptab
where tpar.owner=pkey.owner
and tpar.table_name=pkey.name
and tpar.owner=ptab.owner
and tpar.table_name=ptab.table_name
and pkey.object_type='TABLE';

Единственная проблема заключается в том, что вы будете выполнять неявное преобразование varchar2 в дату, и я не вижу способаделать это иначе.

0 голосов
/ 23 февраля 2019

Во-первых, безумно называть имя таблицы, имя пакета и имя процедуры TEST_TABLE, как вы делаете, как будто другого имени нет.Я назвал их соответствующим образом.

HIGH_VALUE не может напрямую использоваться в DATE связанных функциях, так как имеет LONG TYPE.Существует простой метод преобразования его в дату с использованием динамического SQL (EXECUTE IMMEDIATE)

CREATE OR replace PACKAGE BODY PKG_test_table AS
     PROCEDURE pr_test_table
          IS
          v_high_value DATE;
     BEGIN
          FOR cc IN (
               SELECT partition_name,
                      high_value
               FROM user_tab_partitions
               WHERE table_name = 'TEST_TABLE'
          ) LOOP
               BEGIN
             EXECUTE IMMEDIATE 'BEGIN :v_high_val := '|| cc.high_value || '; END;' 
                           USING OUT v_high_value;
                    IF
                         SYSDATE >= add_months(v_high_value,2)
                    THEN
                         EXECUTE IMMEDIATE 'ALTER TABLE TEST_TABLE DROP PARTITION ' 
           || cc.partition_name;
                         dbms_output.put_line('Dropping partition is completed.');
                    END IF;
               END;
          END LOOP;
     EXCEPTION
          WHEN OTHERS THEN
               dbms_output.put_line(sqlerrm);
     END pr_TEST_TABLE;
END PKG_test_table;
/

Вызов процедуры

BEGIN 
 PKG_test_table.pr_test_table; 
END;
/
0 голосов
/ 23 февраля 2019

Столбец HIGH_VALUE из USER_TAB_PARTITIONS является длинным типом данных, я не собираюсь копировать код с другого веб-сайта, но если вы включите Google "oracle convert high value to date", вы должны получить некоторые идеи о том, как создать функцию, котораяВы можете использовать, чтобы конвертировать 'long' в дату.

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

0 голосов
/ 23 февраля 2019

Поскольку ошибка говорит о том, что все ADD_MONTHS принимает DATE, и вы передаете как LONG.

Попробуйте что-то подобное, и все должно быть в порядке.

Пример:

DECLARE
DT LONG(1000) := 'TO_DATE('||''''||'2018-08-01 00:00:00'||''''||',' ||''''|| 'SYYYY-MM-DD HH24:MI:SS'||''''||','||''''||'NLS_CALENDAR=GREGORIAN'||''''||')';
BEGIN
DBMS_OUTPUT.PUT_LINE(DT);
EXECUTE IMMEDIATE
             'BEGIN
                 DBMS_OUTPUT.PUT_LINE(TO_CHAR(ADD_MONTHS('||DT||',2),'||''''||'YYYY-MM-DD HH24:MI:SS'||''''||
              ')); END;';

END;

Вывод:

TO_DATE('2018-08-01 00:00:00','SYYYY-MM-DD HH24:MI:SS','NLS_CALENDAR=GREGORIAN')
2018-10-01 00:00:00     
0 голосов
/ 23 февраля 2019

Ваша процедура не принимает никаких параметров.Вы не можете передать ему никаких аргументов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...