Выберите таблицу в курсоре после создания таблицы - PullRequest
1 голос
/ 28 сентября 2019

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

Проблема в том, что когда я пытаюсь выполнить свой скрипт, он показывает, что «таблица или представление не существует», кажется, что курсор пытается проверить его уже, когдая запускаю свой сценарийЕсть ли способ решить эту проблему?

DECLARE 
tbl_exist_s1 PLS_INTEGER;
tbl_exist_s2 PLS_INTEGER;
total_were_updated_sc2 NUMBER(10,0);
total_need_to_update_sc2 NUMBER(10,0);
total_were_updated_sc1 NUMBER(10,0);
total_need_to_update_sc1 NUMBER(10,0);
run_date Date := SYSDATE;


BEGIN

  DBMS_OUTPUT.ENABLE(NULL);
  --Checking if the table is already existing, create table if not existing.
  select count(*) into tbl_exist_s2
  from all_tables
  where owner = 'cent' AND table_name = 'serv_req';

  DBMS_OUTPUT.PUT_LINE('Cleanup run: ' || SYSDATE);

  if (tbl_exist_s2 = 0) THEN
     DBMS_OUTPUT.PUT_LINE('Start Creating table cent.serv_req');

    EXECUTE IMMEDIATE 'CREATE TABLE cent.serv_req (      
    association_type NUMBER(10,0), 
    association_id NUMBER(10,0), 
    association_id_serv NUMBER(10,0),
    request_id NUMBER(10, 0)
    record_audit_datet DATE,

    CONSTRAINT pk_sc1 PRIMARY KEY(association_type, association_id, association_id_serv))';
END IF;

-- this is to insert the new data to the table.
EXECUTE IMMEDIATE 'INSERT INTO cent.serv_req
      VALUES(12, 13, 14, 1172, SYSDATE)';
commit;

 DECLARE
 v_err_comp CHAR(2000);
 c SYS_REFCURSOR;

 CURSOR sample_cursor IS
 select *
 from cent.serv_req
 where record_audit_date = run_date;

 sample_cursor_rec sample_cursor%ROWTYPE;
 BEGIN
   -- This will count the no of the records that are getting updated
   total_need_to_update_sc2 := 0;
   total_were_updated_sc2 := 0;

   DBMS_OUTPUT.PUT_LINE('===Starting process to activate the component element record associated to the active member instance record===');

-- this loop is to update the component element
OPEN sample_cursor ;
  LOOP
    FETCH sample_cursor INTO sample_cursor_rec;
      EXIT WHEN sample_cursor % NOTFOUND;

       DBMS_OUTPUT.PUT_LINE('===sample===');
        --Logic should be here
    END;

  END LOOP;
CLOSE sample_cursor;
END;

END;

Ответы [ 2 ]

1 голос
/ 28 сентября 2019

Проверьте, поможет ли следующее.Это отрывок из вашего кода:

select count(*) into tbl_exist_s2
from all_tables
where owner = 'cent' AND table_name = 'serv_req';     --> this

<snip>

EXECUTE IMMEDIATE 'CREATE TABLE cent.serv_req (       --> this

<snip>

EXECUTE IMMEDIATE 'INSERT INTO cent.serv_req          --> this

По умолчанию Oracle хранит имена объектов (включая имена владельцев, имена таблиц, имена столбцов, ...) в UPPERCASE .

Следовательно, SELECT, который вы запустили, вернул 0, потому что он действительно не нашел таблицу с именем serv_req (в нижнем регистре), принадлежащую пользователю cent (снова в нижнем регистре).

Тогдаиспользуя динамический SQL, вы пытаетесь создать таблицу и вставить в нее, но на этот раз ссылаетесь на нее «обычно» (т.е. cent.serv_req), что правильно интерпретируется Oracle;если имя таблицы не заключено в двойные кавычки (так что MiXEd CAsE имеет значение), Oracle знает , что делать.

Коротко: попробуйте переключиться на UPPERCASE при первом выборе, т.е.

select count(*) into tbl_exist_s2
from all_tables
where owner = 'CENT' AND table_name = 'SERV_REQ';     --> this; use UPPERCASE

Более того, вы не можете ссылаться на таблицу, которая еще не существует - это то, что пытается сделать ваш КУРСОР.Если вы хотите сделать это, вам придется снова переключиться на динамический SQL, который постепенно превращается в кошмар.

Вот ваш модифицированный код, который фактически компилируется и что-то делает :

Первая часть:

SQL> declare
  2    tbl_exist_s1             pls_integer;
  3    tbl_exist_s2             pls_integer;
  4    --total_were_updated_sc2   NUMBER(10,0);     --> moved to ...
  5    --total_need_to_update_sc2 NUMBER(10,0);     --> ... another PL/SQL ...
  6    total_were_updated_sc1   number(10,0);
  7    total_need_to_update_sc1 number(10,0);
  8    --run_date                 Date := SYSDATE;  --> ... block
  9  begin
 10    dbms_output.enable(null);
 11    --Checking if the table is already existing, create table if not existing.
 12    select count(*) into tbl_exist_s2
 13      from all_tables
 14      where owner = 'SCOTT' and table_name = 'SERV_REQ';
 15
 16      dbms_output.put_line('Cleanup run: ' || sysdate);
 17
 18    if (tbl_exist_s2 = 0) then
 19       dbms_output.put_line('Start Creating table cent.serv_req');
 20
 21       execute immediate 'CREATE TABLE scott.serv_req (
 22         association_type    NUMBER(10,0),
 23         association_id      NUMBER(10,0),
 24         association_id_serv NUMBER(10,0),
 25         request_id          NUMBER(10,0),          --> missing comma here
 26         record_audit_date   DATE,
 27         CONSTRAINT pk_sc1 PRIMARY KEY(association_type,
 28                                       association_id,
 29                                       association_id_serv))';
 30    end if;
 31
 32    -- this is to insert the new data to the table.
 33    execute immediate 'INSERT INTO scott.serv_req
 34        VALUES(12, 13, 14, 1172, SYSDATE)';
 35    commit;
 36  end;
 37  /
Cleanup run: 09/28/2019
Start Creating table cent.serv_req

PL/SQL procedure successfully completed.

SQL>

Вторая часть:

SQL> -- This should be a new PL/SQL procedure as you can't reference table that
SQL> -- doesn't exist (yet)
SQL> declare
  2    total_were_updated_sc2   number(10,0);
  3    total_need_to_update_sc2 number(10,0);
  4    run_date                 date := sysdate;
  5
  6    v_err_comp               char(2000);
  7    c                        sys_refcursor;
  8
  9    cursor sample_cursor is
 10      select *
 11      from scott.serv_req
 12      where record_audit_date = run_date;
 13
 14    sample_cursor_rec sample_cursor%rowtype;
 15  begin
 16    -- This will count the no of the records that are getting updated
 17    total_need_to_update_sc2 := 0;
 18    total_were_updated_sc2 := 0;
 19
 20    dbms_output.put_line('===Starting process to activate the component element record associated to the active member instance record===');
 21
 22    -- this loop is to update the component element
 23    open sample_cursor ;
 24    loop
 25      fetch sample_cursor into sample_cursor_rec;
 26      exit when sample_cursor % notfound;
 27
 28      dbms_output.put_line('===sample===');
 29      --Logic should be here
 30      --END;  --> this doesn't have its BEGIN; remove it
 31    end loop;
 32    close sample_cursor;
 33  end;
 34  /
===Starting process to activate the component element record associated to the active member instance record===

PL/SQL procedure successfully completed.

SQL>

На мой взгляд, вы должны обдумать это.Не создавайте таблицы динамически, это редко хорошая идея.Создайте его один раз, используя чистый SQL, и используйте его позже столько раз, сколько хотите.Динамический SQL приятно иметь , но он не масштабируется, его трудно отлаживать, он может превратиться в монстра, который сделает вашу жизнь (как разработчика) несчастной.

1 голос
/ 28 сентября 2019

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

  • Вы можете разбить ваш скрипт на два отдельных блока PL / SQL.Первый создает таблицу, если она не существует.Затем вторая реализует любую логику, которую вы хотите реализовать.
  • Если вам нужно, чтобы это был один блок PL / SQL, вам нужно будет использовать динамический SQL везде, где вы ссылаетесь на таблицу.Вы можете открыть курсор с помощью динамического оператора SQL и / или использовать пакет dbms_sql для выполнения последующих запросов.Однако это добавляет значительную сложность вашему коду, поэтому, как правило, он не идеален.
...