Procedura i zmienna liczba zmiennych

0

Witam,
mam problem i boje się, że może być coś "grubszego"..
Mianowicie dotychczas robiłem (i testowałem) procedurę jedynie dla "stałych" danych.., jednakże docelowo procedura ma być uniwersalna i tutaj pojawił się problem ze zmiennymi...

Aktualnie procedura wygląda tak : (fragment)

DELIMITER $$
 CREATE PROCEDURE proc()
 BEGIN
     DECLARE value1 INT;
     DECLARE value2 INT;
     DECLARE value3 INT;
     DECLARE value4 INT;
     DECLARE value5 INT;

     DECLARE cur1 CURSOR FOR SELECT val1, val2, val3, val4, val5 FROM tab AS t1

     DROP TABLE IF EXISTS temp_table;
     CREATE TEMPORARY TABLE IF NOT EXISTS temp_table (val1 INT, val2 INT, val3 INT, val4 INT, val5);

     OPEN cur1;

       FETCH cur1 INTO value1, value2, value3, value4, value5;

        SELECT count(1) INTO var FROM tab WHERE val1= value1;

      ...

     CLOSE cur1;
 DELIMITER ;

O co chodzi?

Procedura ma przetwarzać dane tabel, które posiadają różną liczę kolumn 'value'..
W powyższym przypadku jest ich 5 i jak widać zastosowane jest 5 zmiennych, które następnie są wykorzystywane do działania na kursorze (i jeszcze w kilku miejscach..).

I teraz pytanie / problem - czy jest możliwość "dynamicznego" deklarowania różnej ilości zmiennych ?

     DECLARE value1 INT;
     DECLARE value2 INT;
     DECLARE value3 INT;
     DECLARE value4 INT;
     DECLARE value5 INT;

Teoretycznie mógłbym jeszcze przekazywać te wartości bezpośrednio do procedury (IN), ale wtedy musiałbym utworzyć (chyba) wiele procedur dopasowanych do liczby danych wejściowych..

A może jest jakieś inne rozwiązanie tego problemu, które nie znam/ nie widzę ? (oby..)

0

możesz użyć temporary table jak tablicę intów

0

@abrakadaber - hm.. nie za bardzo widzę jak można tutaj wykorzystać tabele tymczasowe, bo żeby tworzyć tabele o różnej długości muszę podać różną liczbę wartości (value) do procedury które następnie tą tabele utworzą.. a jak to zrobić ? (to chyba też się wiąże z utworzeniem wielu procedur dla każdej liczby zmiennej ? )

Może mógłbyś to bardziej przybliżyć / pokazać na (pseudo) kodzie..?

ps. tabele tymczasową ja de facto tworzę w tej procedurze, ale w całkiem innym celu (tzn. aby uzyskać tabele przetworzoną, której nie da się uzyskać ze "zwyklego" zapytania.. ale to inna sprawa..)

..także bardzo proszę o dalsze wskazówki :)

0

dokładnie tak samo jak tablicę - pola id int i value w zależności od tego co chcesz w niej przechowywać i zamiast value1, value2, ... masz select value from tabela where id=1 dla value1, select value from tabela where id=2 dla value2 itd. Oczywiście możesz zrobić select bez warunku i mieć wszystkie wartości "od razu". Nie ma ograniczenia ile ich tam będziesz miał. Innej opcji nie widzę ponieważ mysql nie ma tablic, a to chyba jedyna struktura która daje możliwość "posiadania dynamicznej" ilości zmiennych w stored proc.

No i oczywiście składanie zapytania będziesz musiał zrobić trochę inaczej - wygenerować je dynamicznie do zmiennej varchar a potem dopiero uruchomić (execute). Nie jestem w stanie wymyślić takiego zapytania, które miało by operować na nieznanej z góry liczbie warunków

1

Ja mam wrażenie że problem to jest z designem tej bazy, a nie z napisaniem procedury/zapytania.
Nie dało się po prostu zrobić tabeli gdzie miałbyś dwa pola:
wartość i id?
I zamiast mieć w bazie:

v1|v2|v3|v4|v5
1 | 2 | 3 | 4 | 5
2 | 3 | 4 | 5 | 6

byłoby

v | id
1 | 1
2 | 1
3 | 1
4 | 1
5 | 1
2 | 2
3 | 2
4 | 2
5 | 2
6 | 2

Wtedy pozbyłbyś się już problemów z operowaniem na tablicy o róznej liczbie elementów. Ale nadal nie napisałeś CO właściwie chcesz potem z tymi danymi robić i jak na nich operować więc trudno powiedzieć czy takie rozwiązanie ma u ciebie sens.

0

@abrakadaber - szczerze, to tak to sobie wyobrażałem.. Pewnie nie jasno się wyraziłem także poniżej przedstawie Tobie i @Shalom jeszcze inaczej problem..

Chodzi o to, że do procedury proc() będzie podawana nazwa tabeli (defacto będzie to id, które razem będzie tworzyć nazwę tabeli).. przykład:

tab_nr_(id)
tab_nr_1
tab_nr_2
itd

gdzie każda z tych tabel ma zmienną liczbę kolumn.. Stąd potrzebne jest zadeklarowanie zmiennej liczby zmiennych w zależności od tabeli..

Rozumiem że mógłbym to zrobić tak:

1)podaje id = 2 tworzące nazwę tabeli
2)robię select typu: SELECT * FROM tab_nr_2, gdzie mogę zobaczyć jaka jest liczba kolumn i następnie na tej podstawie utworzyć tabele tymczasową z otrzymaną liczbą kolumn, które będą następnie "robić" za zmienne (jeszcze nie wiem dokładnie jakby to "od strony kodu" miało wyglądać..)
3)
cytując: "No i oczywiście składanie zapytania będziesz musiał zrobić trochę inaczej - wygenerować je dynamicznie do zmiennej varchar a potem dopiero uruchomić.." - tylko wtedy korzystamy z jednej zmiennej? Hm.. bo jeśli każda zmienna ma być osobna to znowu wracamy do problemu "dynamicznego" generowania zmiennych..

Ogólnie odpowiadając jeszcze na pytania @shalom'a to niestety bazy danych nie mogę zmienić, a CO chce przetwarzać dalej to chyba jest to mało istotne (jest tam sortowanie i usuwanie niektórych wierszy w kontekscie postawionych warunków przetwarzania), bo to co mnie interesuje to - jak utworzyć kursor, którego liczba kolumn jest zmienna w zależności od tabeli..

DECLARE cur1 CURSOR FOR SELECT val1, val2, val3, val4, val5 FROM tab AS t1
 
CREATE TEMPORARY TABLE IF NOT EXISTS temp_table (val1 INT, val2 INT, val3 INT, val4 INT, val5);
 
FETCH cur1 INTO value1, value2, value3, value4, value5;

a to wszystko de facto jest oparte o zadeklarowane zmienne na początku procedury..

Tak jak już wspomniałem, jedyne rozwiązanie jakie mi przychodzi do głowy to przygotowanie n wersji procedury z różną ilością parametrów wejściowych, np.

call proc(val1,val2,val3)
call proc(val1,val2,val3,val4,val5)
call proc(val1,val2,val3,val4,val5,val6,val7,val8,val9,val10)

-.-

ps. Czy coś takiego (zmienna liczba parametrów podawanych do procedury) jest możliwa w bardziej zaawansowanych bazach danych, czy mysql jak zwykle "ułomny" ?

0

Jeśli masz tak skonstruowaną bazę, że masz tabele:
tab_nr_1
tab_nr_2
to nie znaczy, że masz skopaną bazę...
Masz ją zje..ną. I to na maksa.

0

@Marcin.Miga - hm.. nie jest dobrze, ale teraz nie mam już ruchu.. :(

Także jakby ktoś miał jeszcze jakiś sugestie na tak postawiony przeze mnie problem to bardzo proszę o wypowiedź!

0

A po co ci w ogóle te zmienne? Zupełnie nie kumam, co chcesz zrobić - może mógłbym ci pomóc, gdybym wiedział o co chodzi... Zmienne w SQL są tylko pomocnicze - da się bez nich żyć.

0
Marcin.Miga napisał(a):

A po co ci w ogóle te zmienne? Zupełnie nie kumam, co chcesz zrobić - może mógłbym ci pomóc, gdybym wiedział o co chodzi... Zmienne w SQL są tylko pomocnicze - da się bez nich żyć.

OK, to uzupełniając poprzednie moje posty..

Mam następującą procedure:
(jest ona okrojona/przerobiona po to aby nie "zaciemniać", ale problem został tutaj ujęty)

DELIMITER $$
 CREATE PROCEDURE proc()
 BEGIN
     DECLARE tabID INT;
     DECLARE value1 INT;
     DECLARE value2 INT;
     DECLARE value3 INT;
     DECLARE value4 INT;
     DECLARE value5 INT;
 
     DECLARE cur1 CURSOR FOR SELECT tab_id, ,val1, val2, val3, val4, val5 FROM tab_nr_1
                        ORDER BY val1;
 
     DROP TABLE IF EXISTS temp_table;
     CREATE TEMPORARY TABLE IF NOT EXISTS temp_table (tab_id INT, val1 INT, val2 INT, val3 INT, val4 INT, val5 INT);
 
     OPEN cur1;
 
       FETCH cur1 INTO value1, value2, value3, value4, value5;
 
        SELECT COUNT(1) INTO var FROM tab WHERE val1= value1;
 
        INSERT INTO temp_table (tab_id, val1, val2, val3, val4, val5) VALUES (tabID, value1,value2,value3, value4, value5);

      ...
 
     CLOSE cur1;
 DELIMITER ;

Zamieszczony przeze mnie przykład za wiele nie robi, lecz jest to tylko przykład.

O co chodzi?

Powiedzmy, że jako parametr do procedury podaje id, np. 2. W samej procedurze musi być konkatenacja nazwy w stylu

SET tableName = CONCAT('table_nr_',@id);

I teraz chciałbym wyciągnąć wszystkie kolumny danej tabeli z tym, że tabele mają różną ilość kolumn 'val(x)', a z racji tego iż muszę wykorzystać kursor deklaruje sobie wcześniej zmienne aby móc do nich przypisać wartości..

Patrząc inaczej mógłbym te zmienne przekazywać jako parametry do procedury, ale wtedy procedura musi raczej posiadać stałą ilość tych parametrów..

Nie wiem jak to inaczej Wam przekazać..

Chyba, że wynik "końcowy", który uzyskuje po "przekształceniu" tabeli przy pomocy tej procedury można uzyskać "jednym, zwykłym" zapytaniem SQL.. (ja tego niestety nie potrafiłem zrobić i stwierdziłem, że należy tu posiłkować się np. procedurą.. [prywata: ale chętnym myślę, że już w ramach zlecenia mógłbym bliżej naświetlić (podesłać rzeczywisty przykład z kodem), aby sprawdzić czy da się to zrobić samym zapytaniem.. ]

1 użytkowników online, w tym zalogowanych: 0, gości: 1