CodeGym /Kurslar /SQL SELF /Sifarişlərin işlənməsi üçün kompleks prosedur nümunəsi: m...

Sifarişlərin işlənməsi üçün kompleks prosedur nümunəsi: məlumatların yoxlanması, statusun yenilənməsi, loglama

SQL SELF
Səviyyə , Dərs
Mövcuddur

Bu gün biz real sifariş işləmə prosedurunun qurulmasını müzakirə edəcəyik. Burada bir neçə mərhələ var: məlumatların yoxlanması, sifariş statusunun yenilənməsi və loglama. Təsəvvür elə ki, restorandasın, burada şef, ofisiant və kassir bir-biri ilə razılaşdırılmış şəkildə işləməlidir. Bizim prosedurumuzda mərhələlər arasında oxşar məntiqi tətbiq edəcəyik.

Prosedurun tapşırığının təsviri

Sifariş işləmə proseduru aşağıdakı mərhələləri yerinə yetirməlidir:

  1. Lazım olan məhsulun anbarda olub-olmadığını yoxla.
  2. Əgər məhsul kifayət qədərdirsə, onun sayını anbar siyahısından çıx.
  3. Sifarişin statusunu "İşləndi" olaraq yenilə.
  4. Uğurlu əməliyyat barədə məlumatı loga yaz.
  5. Hər hansı bir səhv baş verərsə, bütün dəyişiklikləri əvvələ qaytar.

Prosedurun reallaşdırılması

Addım 1. İş üçün sxem və cədvəllər yaradırıq

Proseduru yazmazdan əvvəl, onun işləyəcəyi cədvəlləri yaradaq.

orders cədvəli — sifarişlər

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_name TEXT NOT NULL,
    product_id INT NOT NULL,
    quantity INT NOT NULL CHECK (quantity > 0),
    status TEXT DEFAULT 'Pending'
);

Bu cədvəl sifarişləri saxlayır. Hər sifarişin müştərisi, məhsul id-si, miqdarı və statusu var (default olaraq "İşlənməni gözləyir").

inventory cədvəli — anbar

CREATE TABLE inventory (
    product_id SERIAL PRIMARY KEY,
    product_name TEXT NOT NULL UNIQUE,
    stock INT NOT NULL CHECK (stock >= 0)
);

Anbarda olan məhsulların siyahısı üçün cədvəl. Hər məhsulun cari ehtiyatı (stock) var.

order_logs cədvəli — əməliyyat jurnalı

CREATE TABLE order_logs (
    log_id SERIAL PRIMARY KEY,
    order_id INT NOT NULL REFERENCES orders(order_id) ON DELETE CASCADE,
    log_message TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Jurnal sifarişlərin icra statusu barədə məlumat yazmaq üçün istifadə olunacaq.

Addım 2. Prosedurun strukturu

Çoxmərhələli prosedurun strukturu belədir:

  1. Soruşulan məhsulun anbarda olub-olmadığını və kifayət qədər olub-olmadığını yoxla.
  2. Əgər məhsul kifayət qədərdirsə, inventory cədvəlində onun miqdarını azaldırıq.
  3. Sifarişin statusunu "İşləndi" olaraq dəyiş.
  4. Uğurlu nəticəni order_logs cədvəlinə yaz.
  5. Mümkün səhvləri geri qaytarmaqla işlət.

Addım 3. Prosedurun yazılması

Gəlin yuxarıda təsvir olunan addımlar üçün process_order prosedurunu yazaq.

CREATE OR REPLACE FUNCTION process_order(order_id INT)
RETURNS VOID AS $$
DECLARE
    v_product_id INT;
    v_quantity INT;
    v_stock INT;
BEGIN
    -- Addım 1: Sifariş haqqında məlumat alırıq
    SELECT product_id, quantity
    INTO v_product_id, v_quantity
    FROM orders
    WHERE order_id = $1;

    -- Sifarişin olub-olmadığını yoxlayırıq
    IF NOT FOUND THEN
        RAISE EXCEPTION 'Sifariş ID % ilə mövcud deyil.', $1;
    END IF;

    -- Addım 2: Məhsulun anbarda olub-olmadığını yoxlayırıq
    SELECT stock INTO v_stock
    FROM inventory
    WHERE product_id = v_product_id;

    IF NOT FOUND THEN
        RAISE EXCEPTION 'Məhsul ID % ilə anbarda yoxdur.', v_product_id;
    END IF;

    IF v_stock < v_quantity THEN
        RAISE EXCEPTION 'Məhsul ID % üçün kifayət qədər ehtiyat yoxdur. Soruşulan: %, Mövcud: %.',
            v_product_id, v_quantity, v_stock;
    END IF;

    -- Addım 3: Anbarda məhsulun miqdarını azaldırıq
    UPDATE inventory
    SET stock = stock - v_quantity
    WHERE product_id = v_product_id;

    -- Addım 4: Sifarişin statusunu 'Processed' olaraq yeniləyirik
    UPDATE orders
    SET status = 'Processed'
    WHERE order_id = $1;

    -- Addım 5: Uğurlu icranı jurnala yazırıq
    INSERT INTO order_logs (order_id, log_message)
    VALUES ($1, 'Sifariş uğurla işlənib.');

EXCEPTION
    WHEN OTHERS THEN
        -- Hər hansı uğursuzluqda səhvi loga yazırıq
        INSERT INTO order_logs (order_id, log_message)
        VALUES ($1, 'Sifariş işlənərkən səhv: ' || SQLERRM);

        -- Bütün dəyişiklikləri geri qaytarırıq
        RAISE;
END;
$$ LANGUAGE plpgsql;

Gəlin bu proseduru izah edək.

  1. Yoxlama mərhələsi:

    biz orders cədvəlində göstərilən sifarişin olub-olmadığını yoxlayırıq. Əgər sifariş tapılmasa, detallı mesajla exception atılır. Eyni qayda ilə, anbarda məhsulun olub-olmadığını və miqdarını yoxlayırıq.

  2. Anbarla iş mərhələsi:

    əgər məhsul kifayət qədərdirsə, onun miqdarını anbarda azaldırıq. Bu əməliyyat UPDATE ilə edilir.

  3. Sifariş statusunun dəyişməsi mərhələsi:

    statusu "Processed" (İşləndi) olaraq dəyişirik ki, sifarişin uğurla başa çatdığını göstərək.

  4. Loglama mərhələsi:

    sifariş uğurla işlənəndən sonra əməliyyat barədə mesajı order_logs cədvəlinə əlavə edirik.

  5. Exception işlənməsi:

    əgər nəsə düz getməsə, EXCEPTION blokunda səhvi tuturuq, loga detallı mesaj yazırıq və bütün dəyişiklikləri geri qaytarırıq.

İstifadə nümunələri

Prosedurun işləməsini yoxlamaq üçün test dataları əlavə edək.

-- Məhsulu anbarda əlavə edirik
INSERT INTO inventory (product_name, stock)
VALUES ('Laptop', 10), ('Monitor', 5);

-- Sifarişləri əlavə edirik
INSERT INTO orders (customer_name, product_id, quantity)
VALUES
    ('Alice', 1, 2),
    ('Bob', 2, 1),
    ('Charlie', 1, 20); -- Bu sifariş səhv verməlidir

İndi proseduru test edirik:

-- Alice-in sifarişini işləyirik
SELECT process_order(1);

-- Bob-un sifarişini işləyirik
SELECT process_order(2);

-- Charlie-nin sifarişini işləməyə çalışırıq (səhv)
SELECT process_order(3);

Nəticələr:

  • Alice və Bob-un sifarişləri uğurla işlənəcək, loga yazılacaq və anbardakı ehtiyatlar azalacaq.
  • Charlie-nin sifarişi anbarda kifayət qədər məhsul olmadığı üçün səhv verəcək və logda səhv barədə qeyd olacaq.

Sorğulardan sonra cədvəlləri yoxlayaq:

SELECT * FROM inventory; -- Ehtiyatlarda dəyişikliklər
SELECT * FROM orders; -- Sifariş statuslarında dəyişikliklər
SELECT * FROM order_logs; -- Jurnalda qeydlər

Tipik səhvlər və məsləhətlər

  1. Səhv: SELECT INTO-dan sonra NOT FOUND yoxlanılmayıb.

    Həmişə sorğunun boş nəticə qaytardığı halları yoxlayın, yoxsa gözlənilməz exception-lar ala bilərsiniz.

  2. Səhv: EXCEPTION bloku əlavə olunmayıb.

    Əgər prosedurda error handler yoxdursa, exception zamanı transaction ilişib qala və ya icra məntiqini poza bilər.

  3. Məsləhət: SQL injection-dan qorunun.

    Yalnız tipli parametrlərdən istifadə edin və dinamik SQL-dən yalnız zəruri hallarda istifadə edin.

Prosedurun genişləndirilməsi

Real həyatda daha çox yoxlama əlavə etmək olar, məsələn:

  • Müştərilər üçün endirim və ya aksiyaları nəzərə almaq.
  • Sifarişi işləməzdən əvvəl müştərinin kredit limitini yoxlamaq.
  • Yalnız uğurlu əməliyyatları deyil, rollback-ləri də loglamaq.
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION