Ewa P.

Ewa P. programinsta SQL i
Delphi w Gliwicach

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Proszę o pomoc.
Potrzebuję napisać w jednym skrypcie
zamianę typu kolumny z LONG na VATCHAR2(4000) bez utraty danych.
Mam takie 4 kawałki, które działają jako osobne skrypty uruchamiane po kolei
(w SQL DEVELOPER) ale nie umiem ich złożyć w jeden działający skrypt:

DWARUNEK jest typu LONG,
SID jest typu INTEGER i jest kluczem głównym

1.
alter table nazwa_tab add dwarunek3 varchar2(4000)

2.
begin
for a in (select * from nazwa_tab) loop
update nazwa_tab set DWARUNEK3= substr(a.DWARUNEK,1,4000)
where sid=a.sid;
end loop;
commit;
end;

3.
alter table nazwa_tab drop column DWARUNEK

4.
ALTER TABLE nazwa_tab RENAME COLUMN dwarunek3 to DWARUNEK
Grzegorz D.

Grzegorz D. PL/SQL Developer

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Jeżeli te 4 kawałki działają, to nie można tak?


begin
execute immediate 'alter table nazwa_tab add dwarunek3 varchar2(4000)';
begin
for a in (select * from nazwa_tab) loop
update nazwa_tab set DWARUNEK3= substr(a.DWARUNEK,1,4000)
where sid=a.sid;
end loop;
commit;
end;
execute immediate 'alter table nazwa_tab drop column DWARUNEK';
execute immediate 'ALTER TABLE nazwa_tab RENAME COLUMN dwarunek3 to DWARUNEK';
end;
Grzegorz Drzymała edytował(a) ten post dnia 10.05.11 o godzinie 10:47
Ewa P.

Ewa P. programinsta SQL i
Delphi w Gliwicach

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Niestety, tak już próbowałam i nie działa :(
Ewa P.

Ewa P. programinsta SQL i
Delphi w Gliwicach

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Taki błąd się pojawia:

Error report:
ORA-06550: linia 9, kolumna 30:
PL/SQL: ORA-00904: "DWARUNEK3": niepoprawny identyfikator
ORA-06550: linia 9, kolumna 1:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

konto usunięte

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Cofam, nie doczytalem skryptu :)Ireneusz Ptak edytował(a) ten post dnia 10.05.11 o godzinie 11:28
Łukasz Kurowski

Łukasz Kurowski Usque Ad Finem

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Ewa P.:
Proszę o pomoc.
Potrzebuję napisać w jednym skrypcie
zamianę typu kolumny z LONG na VATCHAR2(4000) bez utraty danych.
Mam takie 4 kawałki, które działają jako osobne skrypty uruchamiane po kolei
(w SQL DEVELOPER) ale nie umiem ich złożyć w jeden działający skrypt:


Zdaje mi się, że tak to powinno wyglądać:

alter table nazwa_tab add dwarunek3 varchar2(4000);

declare
begin
for a in (select * from nazwa_tab) loop
update nazwa_tab set DWARUNEK3= substr(a.DWARUNEK,1,4000)
where sid=a.sid;
end loop;
commit;
end;

alter table nazwa_tab drop column DWARUNEK;

ALTER TABLE nazwa_tab RENAME COLUMN dwarunek3 to DWARUNEK;
Łukasz Kurowski edytował(a) ten post dnia 10.05.11 o godzinie 11:30

konto usunięte

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Ewa P.:
Taki błąd się pojawia:

Error report:
ORA-06550: linia 9, kolumna 30:
PL/SQL: ORA-00904: "DWARUNEK3": niepoprawny identyfikator
ORA-06550: linia 9, kolumna 1:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

Wywala sie przy parsowaniu anonimowego bloku (jeszcze przed wywolaniem) - po prostu kolumny, ktora chcesz zmieniac, jeszcze nie ma w tabeli :)

Trzeba zrobic tak jak Lukasz proponuje (w SQL+) albo update tez musisz umiescic w execute immediate.
Ewa P.

Ewa P. programinsta SQL i
Delphi w Gliwicach

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Nadal ten sam błąd.
Ewa P.

Ewa P. programinsta SQL i
Delphi w Gliwicach

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

już sprawdzam
Ewa P.

Ewa P. programinsta SQL i
Delphi w Gliwicach

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Problem polega na tym, że wykonanie poniższego polecenia:

execute immediate
'update nazwa_tab set DWARUNEK3= substr(a.DWARUNEK,1,4000)
where sid=a.sid';

- powoduje błąd spójności typów LONG i VARCHAR2.

Wykonanie samego:
update nazwa_tab set DWARUNEK3= substr(a.DWARUNEK,1,4000)
- też generuje taki błąd.
Stąd pojawiła się konieczność wykonania poniższego bloku:

begin
for a in (select * from nazwa_tab) loop
update nazwa_tab set DWARUNEK3= substr(a.DWARUNEK,1,4000)
where sid=a.sid';
end loop;
commit;
end;Ewa P. edytował(a) ten post dnia 10.05.11 o godzinie 11:58

konto usunięte

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Wyciagnij substr(a.DWARUNEK,1,4000) poza execute immediate - wtedy zadziala.

EXECUTE IMMEDIATE 'update nazwa_tab set DWARUNEK3 = :a
where sid = :b' USING substr(a.DWARUNEK,1,4000), a.sid;Ireneusz Ptak edytował(a) ten post dnia 10.05.11 o godzinie 12:02
Ewa P.

Ewa P. programinsta SQL i
Delphi w Gliwicach

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

begin
execute immediate 'alter table nazwa_tab add dwarunek3 varchar2(4000)';
begin
for a in (select * from nazwa_tab) loop
EXECUTE IMMEDIATE 'update nazwa_tab set DWARUNEK3 = :a
where sid = :b' USING substr(a.DWARUNEK,1,4000), a.sid;
end loop;
commit;
end;
execute immediate 'alter table nazwa_tab drop column DWARUNEK';
execute immediate 'ALTER TABLE nazwa_tab RENAME COLUMN dwarunek3 to DWARUNEK';
end;

generuje błąd:

Error report:
ORA-00932: niespójne typy danych: oczekiwano -, uzyskano -
ORA-06512: przy linia 5
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*Cause:
*Action:

konto usunięte

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

To moze warto jeszcze cos takiego zrobic:

for a in (select sid, dwarunek from nazwa_tab) loop

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

declare
lv_col varchar2(4000);
begin
execute immediate 'alter table nazwa_tab add(DWARUNEK3
varchar2(4000))';
for rec in (select * from nazwa_tab) loop
lv_col := substr(rec.DWARUNEK, 1, 4000);
execute immediate 'update nazwa_tab set DWARUNEK3 = :1 where sid = :2' using lv_col, rec.sid;
commit;
end loop;
execute immediate 'alter table nazwa_tab drop column DWARUNEK';
execute immediate 'ALTER TABLE nazwa_tab RENAME COLUMN DWARUNEK3 to DWARUNEK';
end;

sprawdzałem, puszczałem - działa. Do poprawy:
1) Wydajność
2) ogólna konstrukcja tego szkicu (żeby wyglądał ;] )Wojciech T. edytował(a) ten post dnia 10.05.11 o godzinie 13:33
Krzysztof Bokiej

Krzysztof Bokiej Software Engineer

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Czy DWARUNEK jako long zawiera jakieś polskie znaki?

Jeżeli tak, to być może to jest problem. Bo jak zrobisz substr na longu do 4000 to i tak ciąg może mieć więcej niż 4000 BYTE i nie zostanie wpuszczony przez DBMS do kolumny typu varchar (on może mieć max 4000 BYTE). Ja bym na próbę puścił procedurę z substr do 3000. Jeżeli przejdzie, to procedurę będzie trzeba zmodyfikować, aby obcinała long do 4000 BYTE a nie 4000 CHAR.

Pozdrawiam

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Fragment:
execute immediate
'update nazwa_tab set DWARUNEK3= substr(a.DWARUNEK,1,4000)
where sid=a.sid';

generuje błąd. Należy wcześniej przypisać tego substring'a do zmiennej, a potem tą zmienną robić update i po błędzie :)

konto usunięte

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Krzysztof Bokiej:
Bo jak zrobisz substr na longu do 4000 to i tak ciąg może mieć więcej niż 4000 BYTE

Nie wydaje mi sie :]

EDIT: A rzeczywiscie, wydawalo mi sie, ze widzialem gdzies problemy wlasnie z dzieleniem znakow w UTFie...Ireneusz Ptak edytował(a) ten post dnia 10.05.11 o godzinie 13:38
Ewa P.

Ewa P. programinsta SQL i
Delphi w Gliwicach

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Dzięki bardzo!

Wyrzucenie substr(a.DWARUNEK, 1, 3000) do zmiennej i na wszelki wypadek dałam 3000 zamiast 4000 i od razu zadziałało

:)

konto usunięte

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Wojciech T.:
sprawdzałem, puszczałem - działa.

Ciekawe - jaka wersja Oracle?
U mnie ten skrypt sie wywala - dziala dopiero po zmianie tego kursora w petli.
Marek Łukianowski

Marek Łukianowski Menadżer ds. Rozwoju
Narzędzi IT CABP
S.A.

Temat: ORACLE: LONG na VARCHAR2 bez utraty danych

Ewa P.:
Dzięki bardzo!

Wyrzucenie substr(a.DWARUNEK, 1, 3000) do zmiennej i na wszelki wypadek dałam 3000 zamiast 4000 i od razu zadziałało

:)

1) To może zamiast

alter table nazwa_tab add dwarunek3 varchar2(4000);

Zrób

alter table nazwa_tab add dwarunek3 varchar2(4000 CHAR)

kodowanie nie będzie miało wtedy znaczenia.

Przy deklaracji VARCHAR2(4000) baza oracle'a domyślnie podstawia wartość BYTE.

2) Proponowałbym skorzystać z funkcji substrc zamiast substrMarek Łukianowski edytował(a) ten post dnia 10.05.11 o godzinie 16:47



Wyślij zaproszenie do