MySQL 5 – czego nie było wcześniej cd

Kolejna rzecz, której nie było wcześniej to kursory. Świetnie nadają się one do pobierania danych z bazy i przemieszczanie się po nich.

Aby zacząć używać kursora trzeba go najpierw zadeklarować:

DECLARE nazwa_kursora CURSOR FOR SELECT pole FROM tabela;

Następnie należy go otworzyć:

OPEN nazwa_kursora

Aby pobrać kolejne wiersze uzyskane przez zapytanie zdefiniowane w kursorze używamy:

FETCH nazwa_kursora INTO a;

W tym przypadku a jest wcześniej zadeklarowaną zmienną. Powyższe polecenie zwykle występuje wewnątrz instrukcji REPEAT która umożliwia przejście po wszystkich wierszach pobranych przez kursor.

Gdy kursor przestanie być potrzebny zamykamy go:

CLOSE nazwa_kursora

Przykład użycia w procedurze:

CREATE PROCEDURE proccur()
 
BEGIN
    DECLARE done INT DEFAULT 0;
    DECLARE a INT;
    DECLARE kursor CURSOR FOR SELECT id FROM dane;
    DECLARE CONTINUE HANDLER FOR SQLSTATE ‘02000SET done = 1;
 
    OPEN kursor;
    REPEAT FETCH kursor INTO a;
        IF a > 2 THEN
            UPDATE dane SET nazwa=”a” WHERE id=a;
        END IF;
    UNTIL done END REPEAT;
    CLOSE kursor;
END;

Zmienna done potrzebna jest aby wiedzieć kiedy kursor zakończy pobieranie danych z bazy. Instrukcja REPEAT przechodzi przez wszystkie wiersze tablicy dane i jeśli id danego rekordu jest większe od 2 zmienia wartość pola nazwa na „a”. Kiedy wszystkie wiersze zostaną przeglądnięte REPEAT zostaje zakończone, zamykamy kursor.

MySQL 5 – czego nie było wcześniej

Utrwalam sobie różnice między wersjami;)

Procedury składowane:

W wersji bez parametrów przekazywanych do procedury:

CREATE procedure select_all()
SELECT * FROM tabela;

Wywołanie procedury select_all:

CALL select_all()

W wersji z parametrami:

CREATE procedure select_one(IN szukane_id INT(11))
    SELECT * FROM tabela WHERE id=szukane_id;

Wywołanie procedury:

CALL select_one(3)

Usunięcie procedury:

DROP procedure select_one

W procedurach można korzystać z instrukcji warunkowej IF:

CREATE procedure ifik(IN zmienna INT)
 
BEGIN
    IF zmienna > 5
        SELECT * FROM tabela LIMIT zmienna;
    ELSE
        SELECT * FROM tabela LIMIT 5;
    END IF;
END;

Można zrobić coś w rodzaju instrukcji switch, tutaj nazywanej instrukcją CASE:

CREATE procedure casik(IN zmienna INT)
 
CASE zmienna
    WHEN 0 THEN SELECT * FROM tabela
    WHEN 1 THEN SELECT COUNT(*) FROM tabela
    ELSE SELECT FROM tabela LIMIT 5
END CASE;

Jak widać odpowiednikiem case’ów są konstrukcje WHEN, a zamiast default mamy ELSE.

Jest również pętla WHILE:

CREATE procedure whilik()
 
BEGIN
    DECLARE indeks INT;
    SET indeks = 1;
    WHILE indeks < 10 DO
        SELECT * FROM tabela WHERE id = indeks;
        SET indeks = indeks + 1;
    END WHILE;
END;

Niejako odwrotnością WHILE jest REPEAT:

CREATE procedure repeacik()
 
BEGIN
    DECLARE indeks INT DEFAULT 1;
    REPEAT
        SET indeks = indeks + 2;
        UNTIL j > 10
    END REPEAT
END;

Coś jak continue:

CREATE procedure iteracik()
 
BEGIN
    DECLARE indeks INT DEFAULT 1;
    etykieta: REPEAT
        SET indeks = indeks + 5;
        IF indeks = 20 THEN ITERATE etykieta; END IF;
        UNTIL indeks = 100
    END REPEAT etykieta;
END;

Procedury mogą prawie wszystko – jednak nie mogą zmieniać innych procedur, funkcji czy triggerów.

30 dni do sukcesu

Ostatnio szukając materiałów na temat Ruby on Rails, znalazłam bloga z tłumaczeniem tekstu: http://www.stevepavlina.com/blog/2005/04/30-days-to-success/. W sumie dość sprytny to pomysł, by spróbować z czymś wytrzymać 30 dni, a później będzie się już tak przyzwyczajonym, że nie straszne będą kolejne dni, miesiące, tygodnie. Póki co zamierzam to wcielić w życie na blogu, którego ostatnio nie udawało mi się urozmaicać wyrywkami z życia programisty po godzinach;) Co oczywiście nie znaczy, że nic się nie działo – zainteresowałam się dość przelotnie frameworkiem Symfony, który jednak szybko doprowadził mnie do pasji, jeśli chodzi o jego konfigurację (stos błędów jakie pojawiają się mimo iż stosuję się do tutoriala na stronie frameworka), ale ja go jeszcze dopadnę;) Z przyjemniejszych rzeczy – zainstalowałam sobie Beryla na mojej Fedorze i bawię się płynnymi okienkami oraz masą innych rzeczy:) Znalazłam też fajną stronę dla społeczności związanej z językiem Ruby: http://rubyquiz.com/. Umieszczane są na niej różne programistyczne zadanka, a później ludzie wymieniają się rozwiązaniami na liście mailingowej.

Perl vs PHP – 1

Fajna rzecz, która działa w Perlu, a nie działa w PHP:

print "Maga ", "uczy ", "się ", "Perla.\n";

Efekt w Perlu – wypisanie tekstu: Maga uczy się Perla.

Podobnie jak:

print ("Maga ", "uczy ", "się ", "Perla.\n");

Drugi skrypt zadziała również w PHP. Z kolei jedyne co z pierwszym skryptem zrobi PHP, to wyświetli parse error, ponieważ nie jest on przystosowany do wyświetlania rzeczy po przecinku bez nawiasów. Wynika to z tego, że w Perlu print jest operatorem i jego argumentem jest lista. Natomiast w PHP print jest funkcją i potrzebuje argumentów podanych w nawiasach i oddzielonych przecinkami

PHP – sztuczki

Natknęłam się ostatnio na ciekawą rzecz.
Prawie każdy zna wywodzący się z C operator warunkowy (?:). Dla przypomnienia – jedyny trójargumentowy operator – świetnie zastępuje if…else… – przynajmniej w prostych przypadkach.

Przykład zastosowania:

$a = 10;
$b = ($a > 4) ? 100 : 200;

Wówczas zmienna $b zależnie od wartości zmiennej $a przyjmie:
wartość 100 – jeśli zmienna $a będzie większa niż 4
wartość 200 – jeśli zmienna $a będzie mniejsza lub równa 4.
W powyższym przykładzie $a jest większe niż 4 więc zmienna $b przyjmie wartość 100.
Myślałam, że to wszystko jeśli chodzi o operator ?: – do wczoraj.
Kiedy to okazało się, że argumentami tego operatora mogą być funkcje i to w całkiem inny sposób niż robiłam to do tej pory.

Kolejny przykład:

function inkrementacja($i)
{
    return ++$i;
}
function dekrementacja($i)
{
    return$i;
}
$a = 10;
$b = ($a > 4) ? 'inkrementacja' : 'dekrementacja';
$b = $b($a);

Co się stanie?
Jeśli zmienna $a będzie większa od 4, zmiennej $b zostanie przypisany wynik wyrażenia: inkrementacja($a).
Jeśli zmienna $a będzie mniejsza lub równa 4, zmiennej $b zostanie przypisany wynik wyrażenia: dekrementacja($a).
I tak w tym przypadku wartość zmiennej $b wyniesie 11.

Dlaczego nie zrobić tego tradycyjnie?
Tradycyjnie wyglądałoby to tak:

function inkrementacja($i)
{
    return ++$i;
}
function dekrementacja($i)
{
    return$i;
}
$a = 10;
$b = ($a > 4) ? inkrementacja($a) : dekrementacja($b);

Zmienna $b przyjmuje teraz wartość 11.

Jaka jest wyższość wcześniejszego rozwiązania nad tradycyjnym? Moim zdaniem – spora, choć jeszcze nie znalazłam na to konkretnego zastosowania, ale jestem pewna, że się przyda. Nie-tradycyjne tworzy minifunkcję – można wielokrotnie sprawdzać warunek ($a > 4) i przypisywać zmiennej $b – bądź jakieś innej zmiennej wartości zwracane przez funkcje inkrementacja i dekrementacja. Jak to?
Można wielokrotnie później wywoływać $b($a) podstawiając za $a coraz to nowe wartości.
Natomiast tradycyjne rozwiązanie pozwala tylko raz sprawdzić warunek i raz dokonać podstawienia.
Wszystko więc zależy od potrzeb.
Nawiasem – nie znalazłam żadnych udokumentowanych źródeł pozwalających dokonać czegoś takiego w C – choć w końcu PHP napisano w C. Co prawda próbowałam eksperymentować i z moich doświadczeń wynika, że zastosowanie tej „innej” składni w C nie jest możliwe;)
To tylko pogłębia moją sympatię do PHP.