PL SQL отсутствует запятая - PullRequest
0 голосов
/ 01 мая 2020

Я пытаюсь проанализировать этот оператор вставки с помощью DBMS_ SQL .PARSE, но получаю ошибку «пропущена запятая». Пожалуйста, помогите :(

     'insert into ' || '"' || v_materie || '"' || ' ( 
      nume,prenume,nr_matricol,valoare,data_notare) values(' ||
      v_nume || ','||
      v_prenume || ','||
      v_nr_matricol || ','||
      v_nota || ','||
      v_dataNotare || ')'

Ответы [ 2 ]

1 голос
/ 01 мая 2020

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

'insert into ' || '"' || v_materie || '"' || ' ( 
nume,prenume,nr_matricol,valoare,data_notare) values(''' ||
v_nume || ''','''||
v_prenume || ''','''||
v_nr_matricol || ''','''||
v_nota || ''','''||
v_dataNotare || ''')'

Вы должны поместить значения в 'символ, но поскольку вы генерируете строку, вам нужно экранировать символ', так что вы получите '' '

0 голосов
/ 04 мая 2020

Как @Giga указал, что построение оператора sql в виде конкатенации строк является очень плохой идеей . Не только опасно подвергаться инъекции sql, но и безобразно и совершенно не нужно. Вы уже используете dbms_ sql для проверки запроса - кстати, хорошая идея - так почему бы не построить запрос с учетом этого. Так что с вашим запросом, используя dbms_ sql до конца:

-- Setup 
create table "Mat Val" 
     ( nume        integer
     , prenume     integer
     , nr_matricol integer
     , valoare     integer
     , data_notare integer
     );


declare
   k_materie_name varchar2(8) := 'Mat Val';
   k_sql_base varchar2(1000) :=  
     'insert into "v_materie" (nume,prenume,nr_matricol,valoare,data_notare) values(:1,:2,:3,:4,:5)';

   l_sql_stmt varchar2(1000);
   l_dbms_cursor_ref integer; 

   l_rows_processed integer;

   v_nume        integer := 1;
   v_prenume     integer := 2;
   v_nr_matricol integer := 3;
   v_valoare     integer := 4;
   v_data_notare integer := 5;

begin 
  l_sql_stmt := replace(k_sql_base,'v_materie',k_materie_name);
  dbms_output.put_line('Setting up dbms_sql processing for statement:' || chr(10) || l_sql_stmt);  

  l_dbms_cursor_ref:= dbms_sql.open_cursor;
  dbms_sql.parse(l_dbms_cursor_ref,l_sql_stmt,DBMS_SQL.native);

  -- set up bind variables with local variables
  dbms_sql.bind_variable(l_dbms_cursor_ref, ':1', v_nume);
  dbms_sql.bind_variable(l_dbms_cursor_ref, ':2', v_prenume);
  dbms_sql.bind_variable(l_dbms_cursor_ref, ':3', v_nr_matricol);
  dbms_sql.bind_variable(l_dbms_cursor_ref, ':4', v_valoare);
  dbms_sql.bind_variable(l_dbms_cursor_ref, ':5', v_data_notare);

  -- execute dynamic sql
  l_rows_processed := dbms_sql.execute(l_dbms_cursor_ref);

  dbms_output.put_line('Rows inserted  to "' || k_materie_name || '" ==> ' || to_char(l_rows_processed)); 
  dbms_sql.close_cursor(l_dbms_cursor_ref);
end ;

Или просто dbms_ sql, чтобы подтвердить запрос, а затем вернуться к немедленному выполнению:

declare
   k_materie_name varchar2(8) := 'Mat Val';
   k_sql_base varchar2(1000) :=  
     'insert into "v_materie" (nume,prenume,nr_matricol,valoare,data_notare) values(:1,:2,:3,:4,:5)';

   l_sql_stmt varchar2(1000);
   l_dbms_cursor_ref integer; 

   l_rows_processed integer;

   v_nume        integer := 21;
   v_prenume     integer := 32;
   v_nr_matricol integer := 43;
   v_valoare     integer := 54;
   v_data_notare integer := 65;

begin 
  l_sql_stmt := replace(k_sql_base,'v_materie',k_materie_name);
  dbms_output.put_line('Setting up executee immediate for statement:' || chr(10) || l_sql_stmt);  

  l_dbms_cursor_ref:= dbms_sql.open_cursor;
  dbms_sql.parse(l_dbms_cursor_ref,l_sql_stmt,DBMS_SQL.native);
  dbms_sql.close_cursor(l_dbms_cursor_ref);

  execute immediate l_sql_stmt 
              using v_nume      
                  , v_prenume     
                  , v_nr_matricol 
                  , v_valoare     
                  , v_data_notare;

  dbms_output.put_line('Rows inserted  to "' || k_materie_name || '" ==> ' || to_char(sql%rowcount)); 

end ;

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

...