Wpis z mikrobloga

#oracle #dba #sql #it
Mirki,

w ramach procedury odświeżania środowiska testowego, muszę zrobić import danych, o tyle, o ile przez SQL Developera to nie problem, o tyle chciałem zautomatyzować te czynności.

Znalazłem query, które stworzy mi insert-y, niestety NIEBANGLA ORA-00936 i ORA-06512 :( w 31 linijce podobno, tak szukałem, tak analizowałem skrypt, ale nie wiem co jest złe.:

set serveroutput on size 100000
set feedback off

declare
v_table_name varchar2(30) := 'EMP'; -- Your Tablename
v_column_list varchar2(2000);
v_insert_list varchar2(2000);
v_ref_cur_columns varchar2(4000);
v_ref_cur_query varchar2(2000);
v_ref_cur_output varchar2(2000);
v_column_name varchar2(2000);
cursor c1 is select column_name, data_type from user_tab_columns where table_name = v_table_name order by column_id;
refcur sys_refcursor;
begin
for i in c1 loop
v_column_list := v_column_list||','||i.column_name;
if i.data_type = 'NUMBER' then
v_column_name := i.column_name;
elsif i.data_type = 'DATE' then
v_column_name := chr(39)||'to_date('||chr(39)||'||chr(39)'||'||to_char('||i.column_name||','||chr(39)||'dd/mm/yyyy hh:mi:ss'||chr(39)||')||chr(39)||'||chr(39)||', '||chr(39)||'||chr(39)||'||chr(39)||'dd/mm/rrrr hh:mi:ss'||chr(39)||'||chr(39)||'||chr(39)||')'||chr(39);
elsif i.data_type = 'VARCHAR2' then
v_column_name := 'chr(39)||'||i.column_name||'||chr(39)';
end if;
v_ref_cur_columns := v_ref_cur_columns||'||'||chr(39)||','||chr(39)||'||'||v_column_name;
end loop;
v_column_list := ltrim(v_column_list,',');
v_ref_cur_columns := substr(v_ref_cur_columns,8);

v_insert_list := 'INSERT INTO '||v_table_name||' ('||v_column_list||') VALUES ';
v_ref_cur_query := 'SELECT '||v_ref_cur_columns||' FROM '||v_table_name;

open refcur for v_ref_cur_query;
loop
fetch refcur into v_ref_cur_output;
exit when refcur%notfound;
v_ref_cur_output := '('||v_ref_cur_output||');';
v_ref_cur_output := replace(v_ref_cur_output,',,',',null,');
v_ref_cur_output := replace(v_ref_cur_output,'(,','(null,');
v_ref_cur_output := replace(v_ref_cur_output,',,)',',null)');
v_ref_cur_output := replace(v_ref_cur_output,'null,)','null,null)');
v_ref_cur_output := v_insert_list||v_ref_cur_output;
dbms_output.put_line (v_ref_cur_output);
end loop;
end;
/

  • 13
@rotero: Na testy dostałem maszynę z polskimi komunikatami.
ORA-00936: Błąd wyrażenia
ORA-00936: Błąd w linii 29

To w której linii pokaże błąd się zmienia, czasem pokazuje 31
@pokukma: nie jestem pewien czy to to, ale składnia INSERT INTO to

INSERT INTO tablename (column1, column2, column3, ...) VALUES (value1, value2, value3, ...);


Ty masz

INSERT INTO tablename (column1, column2, column3, ...) VALUES
@rotero: chyba jednak values są doklejone:

vrefcuroutput := vinsertlist||vrefcuroutput;
dbmsoutput.putline (vrefcuroutput);

zauważ, że to co opisujesz jest stringiem, który pójdzie na dbms_output
więc, to nei to, te inserty nie są egzekwowane. Mają zostać wyprintowane, do użycia po odświeżeniu bazy.
@pokukma: #!$%@?ąc od tego, że wybrałeś złą metodę, to jak się przy niej upierasz to wklej na pastebin wersję oryginalną, a nie tą która już została zepsuta przez wypok.

PS: W mojej ocenie dobra metoda na odświeżenie testinga danymi z produkcji to:
1. Pełen sync pryz użyci DUPLICATE DATABASE
2. Sync tabel i/lub danych przy użyciu Data Pump (expdp/impdp)
3. Sync tabel i/lub danych przy użyciu imp/exp

Kolejność taka jak ja
@pokukma: zgadzam sie z @maniac777 lepiej uzyc expdp/impdp lub starego dobrego exp/imp;

a co do tego kodu powyzej to blad obstawiam jest tutaj:

vrefcurcolumns := substr(vrefcur_columns,8);

vinsertlist := 'INSERT INTO '||vtablename||' ('||vcolumnlist||') VALUES ';
vrefcurquery := 'SELECT '||vrefcurcolumns||' FROM '||vtablename;

wycinasz substringiem ze zmiennej ktora nie istnieje ?? czy mnie sie wydaje i pozniej do query trafia pusty string(brak kolumn) ??
@maniac777: @cih:

restore jest robiony za pomocą DUPLICATE DATABASE

Natomiast pewne dane muszę zrzucać przed restorem, dodatkowi userzy aplikacji, ustawienia specyficzne dla środowiska etc. i po restorze je ponownie zaaplikować.

najprościej mógłbym zrobić

select "insert into table_name (nazwa_kolumny1, nazwa_kolumny2, nazwa_kolumny3) VALUES '"||nazwa_kolumny1||"', '"||nazwa_kolumny2||"', '"||nazwa_kolumny3||"';" from table_name;
i miałbym zrzucone dane z ustawieniami na których mi zależy. Natomiast nadal byłbym zależny od architektury zrzucanych tabel, czego zdecydowanie nie chcę.

Natomiast, nie