Wojciech Antoniak

Wojciech Antoniak Doktorant/Aktuariusz

Temat: Execute immediate z bulk collect

Cześć,
chcę wykorzystać dynamiczne zapytanie execute immediate z wykorzystaniem bulk collect into. Ogólnie schemat jest prosty
EXECUTE IMMEDIATE
'SELECT kolumny FROM tabela' BULK COLLECT INTO zmienne_po_przecinku;

Problem pojawia się w tym, że kolumny w zapytaniu SELECT i zmiene_po_przeciunku tworzę dynamicznie. Czyli całość wygląda mniej więcej tak:

DECLARE
kolumny varchar2(255),
zmienne_po_przecinku varchar2(255)
BEGIN
-----
Tworzenie zmiennej kolumny i zmienne_po_przecinku
-----
EXECUTE IMMEDIATE
'SELECT ||kolumny||' FROM tabela' BULK COLLECT INTO zmienne_po_przecinku;

END;

Oczywiście powyższy kod jest błędny. Problem pojawia się w dołączeniu zmienne_po_przecinku. Ktoś wie jak to połączyć?

konto usunięte

Temat: Execute immediate z bulk collect

Wojciech Antoniak:
EXECUTE IMMEDIATE
'SELECT ||kolumny||' FROM tabela' BULK COLLECT INTO zmienne_po_przecinku;
END;
Oczywiście powyższy kod jest błędny. Problem pojawia się w dołączeniu zmienne_po_przecinku. Ktoś wie jak to połączyć?

Tak prosto to se ne da se :) Ale można zastosować kilka w sumie dość prostych wytrychów ... zależnie od okoliczności.

Np.

zmienne_po_przecinku mogą być stałą listą, ale kolumny starać się dopasować tak, żeby pasowały do zmiennych typem. Jednak jeśli jakaś kolumna ma nie wystąpić to zastępujesz ją w select'cie wartością NULL. I to wszystko.
Wojciech Antoniak

Wojciech Antoniak Doktorant/Aktuariusz

Temat: Execute immediate z bulk collect

Dzięki za odpowiedź. Trochę przerobię procedurę i będzie hulać ;) Właśnie podstawowym problemem był dla mnie typ danych.

Podrążę dalej. Zaciągnąłem dane i chce je wrzucić do pewnej tabeli .Tutaj także ilość kolumn jest dynamiczna - jest taka sama jak ilość zmiennych.

FOR M IN 1..ILOSC_WIERSZY LOOP

KOMENDA:='INSERT INTO '||NAZWA_TABELI||' VALUES('||REPLACE(ZMIENNE,'*XXX*',TO_CHAR(M))||')';

EXECUTE IMMEDIATE KOMENDA;
END LOOP;

Wyskakuje mi błąd, że zmienne są niezadeklarowne
ORA-00904: "T_NUMBER_2": niepoprawny identyfikator

Ten zabieg z funkcją REPLACE() ma za zadanie wprowadzić licznik z pętli do zapytania.Wojciech Antoniak edytował(a) ten post dnia 22.09.11 o godzinie 14:37
Kamil Stawiarski

Kamil Stawiarski Oracle Certified
Master | Oracle ACE

Temat: Execute immediate z bulk collect

Wojciech Antoniak:
Podrążę dalej. Zaciągnąłem dane i chce je wrzucić do pewnej tabeli .Tutaj także ilość kolumn jest dynamiczna - jest taka sama jak ilość zmiennych.

FOR M IN 1..ILOSC_WIERSZY LOOP

KOMENDA:='INSERT INTO '||NAZWA_TABELI||' VALUES('||REPLACE(ZMIENNE,'*XXX*',TO_CHAR(M))||')';

EXECUTE IMMEDIATE KOMENDA;
END LOOP;

Wyskakuje mi błąd, że zmienne są niezadeklarowne
ORA-00904: "T_NUMBER_2": niepoprawny identyfikator

Ten zabieg z funkcją REPLACE() ma za zadanie wprowadzić licznik z pętli do zapytania.


Jeśli ZMIENNE='T_NUMBER_*XXX*' to po replace masz np. inserta:


insert into tabela
values (T_NUMBER_2);


Co samo w sobie wrzucone do wykonania nie ma prawa się udać, bo faktycznie identyfikator T_NUMBER_2 nie istnieje.

A tak wógóle to nie prościej byłoby Ci zbudować kolekcję rekordów?

Pozdrawiam,
Kamil.
Wojciech Antoniak

Wojciech Antoniak Doktorant/Aktuariusz

Temat: Execute immediate z bulk collect

Cześć, po zrobieniu DBMS_OUTPUT.PUT_LINE z tego co jest w EXECUTE IMMEDIATE dostaję:
INSERT INTO ID_WYPLATY VALUES( T_NUMBER_1(1), T_NUMBER_2(1))
czyli poprawnie.
Kamil Stawiarski:
A tak wógóle to nie prościej byłoby Ci zbudować kolekcję rekordów?
Mógłbyś podrzucić link do literatury.
To jest moja pierwsza procedura z wrzucaniem danych do "wektorów". Ogólnie chciałem wrzucić całą tabelę do zmiennych. Jedyny sposób jaki mi wpadł do głowy to zdefiniowanie na stałe wektorów dat, liczbowych, numerycznych. Potem utworzenie dynamicznego zaciągnięcia danych do tych wektorów za pomocą execute immediate. Następnie dynamiczne zainsertowanie do nowej tabeli. I utknąłem na insertowaniu, a już było tak blisko.
Sebastian Kolski

Sebastian Kolski programista/DBA

Temat: Execute immediate z bulk collect

Wojciech Antoniak:
Cześć, po zrobieniu DBMS_OUTPUT.PUT_LINE z tego co jest w EXECUTE IMMEDIATE dostaję:
INSERT INTO ID_WYPLATY VALUES( T_NUMBER_1(1), T_NUMBER_2(1))
czyli poprawnie.

Nie jest to poprawne bo wykonujesz przez EXECUTE IMMEDIATE sql'a, który nie ma pojęcia o T_NUMBER_1(1) etc.
Aby to zadziałało musiał byś tworzyć dynamicznego PL/SQL'a, czyli w EXECUTE IMMEDIATE 'BEGIN INSERT ....; END;';
W dodatku zmienne T_NUMBER_1 etc musiały by być zadeklarowane jako publiczne globalne na poziomie jakiegoś pakietu. I dostęp do nich trzeba by było robić przez pakiet.

Wydaje mi się, że za bardzo kombinujesz. Łatwiej było by coś poradzić gdyby było wiadomo co chcesz uzyskać (nie w konkretnej funkcji/procedurze, ale ogólnie).
Jeśli tworzysz jakiegoś bardzo ogólnego framework'a, który naprawdę potrzebuje składać takie sql'e dynamicznie, to wydaje mi się, że do tego służy DBMS_SQL

Pozdrawiam
Sebastian
Wojciech Antoniak

Wojciech Antoniak Doktorant/Aktuariusz

Temat: Execute immediate z bulk collect

Na razie wykorzystałem przed EXECUTE IMMEDIATE funkcję REPLACE i podmieniłem nazwy zmiennych ich wartościami i działa teraz elegancko.
Domyślam się, że to co napisałem jest bardzo toporne ale potrzebuję szybko rozwiązania. Doczytam o tym DBMS_SQL jak będę miał czas.
Dzięki wszystkim za wypowiedzi w tym wątku.

Następna dyskusja:

Oracle Financials Techno Fu...




Wyślij zaproszenie do