{"id":31250,"date":"2025-10-07T20:32:11","date_gmt":"2025-10-07T17:32:11","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/"},"modified":"2025-10-07T20:32:11","modified_gmt":"2025-10-07T17:32:11","slug":"mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/","title":{"rendered":"Mastering SQL: Oracle&#8217;da Cursor ve Trigger&#8217;lar ile Pratik Veritaban\u0131 Y\u00f6netimi"},"content":{"rendered":"<p><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><\/p>\n<style>\n    body {\n        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n        line-height: 1.6;\n        color: #333;\n        max-width: 900px;\n        margin: 20px auto;\n        padding: 0 15px;\n        background-color: #f9f9f9;\n    }\n    h2, h3 {\n        color: #2c3e50;\n        margin-top: 30px;\n        margin-bottom: 15px;\n    }\n    h2 {\n        border-bottom: 2px solid #3498db;\n        padding-bottom: 10px;\n    }\n    h3 {\n        color: #34495e;\n        border-bottom: 1px dashed #ccc;\n        padding-bottom: 5px;\n    }\n    p {\n        margin-bottom: 1em;\n    }\n    ul, ol {\n        margin-bottom: 1em;\n        padding-left: 20px;\n    }\n    li {\n        margin-bottom: 0.5em;\n    }\n    pre {\n        background-color: #ecf0f1;\n        border: 1px solid #ddd;\n        padding: 15px;\n        border-radius: 5px;\n        overflow-x: auto;\n        font-family: 'Consolas', 'Monaco', monospace;\n        font-size: 0.9em;\n        line-height: 1.4;\n    }\n    code {\n        font-family: 'Consolas', 'Monaco', monospace;\n        background-color: #e0e0e0;\n        padding: 2px 4px;\n        border-radius: 3px;\n    }\n    table {\n        width: 100%;\n        border-collapse: collapse;\n        margin-bottom: 1em;\n    }\n    th, td {\n        border: 1px solid #ccc;\n        padding: 8px;\n        text-align: left;\n    }\n    th {\n        background-color: #3498db;\n        color: white;\n    }\n    .expert-tip {\n        background-color: #d9edf7;\n        border-left: 5px solid #3498db;\n        padding: 15px;\n        margin: 20px 0;\n        font-style: italic;\n        color: #31708f;\n        border-radius: 4px;\n    }\n    .faq-item {\n        margin-bottom: 15px;\n    }\n    .faq-question {\n        font-weight: bold;\n        color: #2c3e50;\n    }\n    .faq-answer {\n        margin-left: 20px;\n        padding-left: 10px;\n        border-left: 3px solid #eee;\n    }<\/p>\n<p>    \/* Mobil uyumluluk i\u00e7in medya sorgular\u0131 *\/\n    @media (max-width: 768px) {\n        body {\n            margin: 10px auto;\n            padding: 0 10px;\n        }\n        h2 {\n            font-size: 1.5em;\n        }\n        h3 {\n            font-size: 1.2em;\n        }\n        pre {\n            font-size: 0.85em;\n            padding: 10px;\n        }\n        table, thead, tbody, th, td, tr {\n            display: block;\n        }\n        th {\n            display: none; \/* Hide table headers (but not important for screen readers) *\/\n        }\n        td {\n            border: none;\n            border-bottom: 1px solid #eee;\n            position: relative;\n            padding-left: 50%;\n            text-align: right;\n        }\n        td::before {\n            content: attr(data-label);\n            position: absolute;\n            left: 6px;\n            width: 45%;\n            padding-right: 10px;\n            white-space: nowrap;\n            text-align: left;\n            font-weight: bold;\n        }\n    }\n<\/style>\n<p>Oracle veritabanlar\u0131nda veri manip\u00fclasyonu ve otomasyon s\u00fcre\u00e7lerini bir \u00fcst seviyeye ta\u015f\u0131mak m\u0131 istiyorsunuz? Bu makale, Cursor ve Trigger gibi g\u00fc\u00e7l\u00fc PL\/SQL ara\u00e7lar\u0131n\u0131 kullanarak veritaban\u0131 y\u00f6netimini nas\u0131l daha etkin hale getirece\u011finizi ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.<\/p>\n<p>Veritabanlar\u0131, modern uygulamalar\u0131n bel kemi\u011fidir ve bu veritabanlar\u0131n\u0131 etkin bir \u015fekilde y\u00f6netmek, performans\u0131 optimize etmek ve veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc sa\u011flamak kritik \u00f6neme sahiptir. SQL, verilerle etkile\u015fim kurmak i\u00e7in harika bir ara\u00e7 olsa da, bazen daha karma\u015f\u0131k i\u015flemleri ger\u00e7ekle\u015ftirmek veya belirli olaylara otomatik olarak yan\u0131t vermek i\u00e7in ek yeteneklere ihtiya\u00e7 duyar\u0131z. \u0130\u015fte tam da bu noktada Oracle PL\/SQL&#8217;in sundu\u011fu Cursor ve Trigger mekanizmalar\u0131 devreye girer. Bu ara\u00e7lar, veritaban\u0131 i\u015flemlerini programatik olarak kontrol etme, sat\u0131r baz\u0131nda i\u015flem yapma, veri de\u011fi\u015fikliklerini otomatikle\u015ftirme ve denetim kay\u0131tlar\u0131 tutma gibi bir\u00e7ok alanda bize esneklik ve g\u00fc\u00e7 sa\u011flar.<\/p>\n<p>\u00d6zellikle b\u00fcy\u00fck veri k\u00fcmeleriyle \u00e7al\u0131\u015f\u0131rken veya belirli i\u015f kurallar\u0131n\u0131n s\u0131k\u0131 bir \u015fekilde uygulanmas\u0131 gerekti\u011finde, standart SQL sorgular\u0131 yetersiz kalabilir. \u00d6rne\u011fin, bir sat\u0131\u015f i\u015flemi ger\u00e7ekle\u015fti\u011finde otomatik olarak stok miktar\u0131n\u0131 g\u00fcncellemek veya hassas bir tabloya her veri giri\u015fi yap\u0131ld\u0131\u011f\u0131nda bunu bir denetim tablosuna kaydetmek isteyebilirsiniz. Bu t\u00fcr senaryolar, ya programatik bir yakla\u015f\u0131m ya da olaya dayal\u0131 otomatik yan\u0131tlar gerektirir. Cursor&#8217;lar, sorgu sonu\u00e7 k\u00fcmeleri \u00fczerinde ad\u0131m ad\u0131m gezinerek her bir sat\u0131r\u0131 ayr\u0131 ayr\u0131 i\u015fleme yetene\u011fi sunar. Bu, karma\u015f\u0131k hesaplamalar yapmak, belirli ko\u015fullara g\u00f6re verileri g\u00fcncellemek veya d\u0131\u015f sistemlere veri g\u00f6ndermek gibi i\u015flemler i\u00e7in vazge\u00e7ilmezdir. Trigger&#8217;lar ise, belirli bir veritaban\u0131 olay\u0131 (\u00f6rne\u011fin, bir INSERT, UPDATE veya DELETE i\u015flemi) meydana geldi\u011finde otomatik olarak tetiklenen PL\/SQL bloklar\u0131d\u0131r. B\u00f6ylece, veritaban\u0131 seviyesinde i\u015f kurallar\u0131n\u0131 zorlayabilir, veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc koruyabilir ve denetim izleri olu\u015fturabiliriz. Her iki mekanizma da Oracle veritaban\u0131 y\u00f6neticileri ve geli\u015ftiricileri i\u00e7in g\u00fcnl\u00fck operasyonlarda \u00f6nemli kolayl\u0131klar ve kontrol sa\u011flar. Bu y\u00fczden, bu ara\u00e7lar\u0131n nas\u0131l \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 ve en iyi \u015fekilde nas\u0131l kullan\u0131laca\u011f\u0131n\u0131 anlamak, Oracle uzmanl\u0131\u011f\u0131n\u0131z\u0131 derinle\u015ftirmek ad\u0131na hayati bir ad\u0131md\u0131r.<\/p>\n<h2>Cursor Nedir ve SQL Verilerini Nas\u0131l Ad\u0131m Ad\u0131m \u0130\u015fleriz?<\/h2>\n<p>Veritaban\u0131 i\u015flemleri s\u0131ras\u0131nda bir SQL sorgusu \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131n\u0131zda, sonu\u00e7 olarak s\u0131f\u0131r, bir veya birden fazla sat\u0131r i\u00e7eren bir k\u00fcme elde edersiniz. Bu sonu\u00e7 k\u00fcmesini sat\u0131r sat\u0131r i\u015flemek istedi\u011finizde, yani her bir sat\u0131r \u00fczerinde belirli operasyonlar yapmak istedi\u011finizde, Cursor&#8217;lar devreye girer. Cursor, asl\u0131nda bir sorgu taraf\u0131ndan d\u00f6nd\u00fcr\u00fclen sat\u0131r k\u00fcmesi \u00fczerinde i\u015faret\u00e7i g\u00f6revi g\u00f6ren bir PL\/SQL yap\u0131s\u0131d\u0131r. Oracle, her sorguyu dahili olarak bir Cursor ile i\u015fler; bunlara &#8220;Implicit Cursor&#8221; denir. Ancak, daha karma\u015f\u0131k veya \u00f6zelle\u015ftirilmi\u015f i\u015flemler i\u00e7in kendi &#8220;Explicit Cursor&#8221;lar\u0131m\u0131z\u0131 tan\u0131mlayabiliriz. Explicit Cursor&#8217;lar, sonu\u00e7 k\u00fcmesini daha detayl\u0131 kontrol etmemizi ve \u00fczerinde programatik olarak gezinmemizi sa\u011flar. Bir Cursor&#8217;\u0131n temel ya\u015fam d\u00f6ng\u00fcs\u00fc; tan\u0131mlama (DECLARE), a\u00e7ma (OPEN), verileri getirme (FETCH) ve kapatma (CLOSE) ad\u0131mlar\u0131ndan olu\u015fur. Bu ad\u0131mlar, bize her bir sat\u0131r\u0131 ayr\u0131 ayr\u0131 ele alma esnekli\u011fi sunarak, toplu i\u015flemlerin \u00f6tesinde bir kontrol d\u00fczeyi sa\u011flar.<\/p>\n<p>Cursor&#8217;lar \u00f6zellikle raporlama, veri temizli\u011fi, karma\u015f\u0131k hesaplamalar veya bir tablodaki verileri ba\u015fka bir tabloya belirli ko\u015fullara g\u00f6re ta\u015f\u0131mak gibi senaryolarda olduk\u00e7a kullan\u0131\u015fl\u0131d\u0131r. \u00d6rne\u011fin, bir tablodaki her \u00e7al\u0131\u015fan\u0131n maa\u015f\u0131n\u0131 belirli kriterlere g\u00f6re art\u0131rman\u0131z gerekti\u011finde veya bir dizi \u00fcr\u00fcne indirim uygularken her bir \u00fcr\u00fcn\u00fcn kategorisine g\u00f6re farkl\u0131 indirim oranlar\u0131 uygulaman\u0131z gerekti\u011finde Cursor&#8217;lar size yol g\u00f6sterir. Ayr\u0131ca, Cursor&#8217;lar hata y\u00f6netimi a\u00e7\u0131s\u0131ndan da faydal\u0131d\u0131r; her bir sat\u0131r i\u015flenirken olas\u0131 hatalar\u0131 yakalay\u0131p bunlara \u00f6zel tepkiler verebilirsiniz. Ancak, Cursor kullan\u0131rken dikkatli olmak gerekir; \u00e7ok say\u0131da sat\u0131r\u0131 tek tek i\u015flemek, set tabanl\u0131 (yani tek bir SQL sorgusuyla t\u00fcm k\u00fcme \u00fczerinde i\u015flem yapmak) yakla\u015f\u0131mlara g\u00f6re performans\u0131 olumsuz etkileyebilir. Bu nedenle, Cursor&#8217;lar\u0131 yaln\u0131zca set tabanl\u0131 i\u015flemlerin m\u00fcmk\u00fcn olmad\u0131\u011f\u0131 veya \u00e7ok karma\u015f\u0131k hale geldi\u011fi durumlarda kullanmak en iyi uygulamad\u0131r. Yine de, PL\/SQL programlamas\u0131n\u0131n vazge\u00e7ilmez bir par\u00e7as\u0131d\u0131r ve do\u011fru kullan\u0131ld\u0131\u011f\u0131nda veritaban\u0131 i\u015flemlerinizde size b\u00fcy\u00fck bir esneklik sunar.<\/p>\n<h3>A\u00e7\u0131k (Explicit) Cursor Kullan\u0131m\u0131: Ad\u0131m Ad\u0131m K\u0131lavuz<\/h3>\n<p>A\u00e7\u0131k Cursor&#8217;lar, PL\/SQL kodunuzda belirli bir sorgu i\u00e7in tan\u0131mlad\u0131\u011f\u0131n\u0131z ve programatik olarak kontrol etti\u011finiz Cursor&#8217;lard\u0131r. Bu t\u00fcr Cursor&#8217;lar, bir sorgunun d\u00f6nd\u00fcrd\u00fc\u011f\u00fc sat\u0131rlar\u0131 tek tek i\u015flememiz gerekti\u011finde kullan\u0131l\u0131r. A\u015fa\u011f\u0131daki ad\u0131mlar ve \u00f6rnek, bir sat\u0131\u015f tablosundaki y\u00fcksek de\u011ferli \u00fcr\u00fcnlerin stok durumunu kontrol etme senaryosu \u00fczerinden a\u00e7\u0131k Cursor kullan\u0131m\u0131n\u0131 detayland\u0131rmaktad\u0131r.<\/p>\n<h4>Senaryo: Y\u00fcksek De\u011ferli \u00dcr\u00fcnlerin Stok Kontrol\u00fc ve Bildirimi<\/h4>\n<p>Bir e-ticaret platformunda, belirli bir e\u015fi\u011fin \u00fczerindeki (\u00f6rne\u011fin 1000 TL \u00fczeri) \u00fcr\u00fcnlerin stok miktarlar\u0131n\u0131 d\u00fczenli olarak kontrol etmemiz ve stoklar\u0131 belirli bir seviyenin (\u00f6rne\u011fin 5 adet) alt\u0131na d\u00fc\u015fen \u00fcr\u00fcnler i\u00e7in stok y\u00f6neticisine bildirim g\u00f6ndermemiz gerekiyor. Bu senaryoda, tek bir SQL sorgusu ile t\u00fcm karma\u015f\u0131k mant\u0131\u011f\u0131 uygulamak zor olabilir. Cursor, her bir \u00fcr\u00fcn\u00fc ayr\u0131 ayr\u0131 incelememize olanak tan\u0131r.<\/p>\n<p>\u0130lk olarak, \u00fcr\u00fcn bilgilerini i\u00e7eren bir <code>URUNLER<\/code> tablomuz oldu\u011funu varsayal\u0131m:<\/p>\n<pre><code>\nCREATE TABLE URUNLER (\n    urun_id NUMBER PRIMARY KEY,\n    urun_adi VARCHAR2(100),\n    fiyat NUMBER(10, 2),\n    stok_miktari NUMBER(5)\n);\n\nINSERT INTO URUNLER (urun_id, urun_adi, fiyat, stok_miktari) VALUES (1, 'Diz\u00fcst\u00fc Bilgisayar', 12000.00, 15);\nINSERT INTO URUNLER (urun_id, urun_adi, fiyat, stok_miktari) VALUES (2, 'Ak\u0131ll\u0131 Telefon', 8500.00, 25);\nINSERT INTO URUNLER (urun_id, urun_adi, fiyat, stok_miktari) VALUES (3, 'Oyun Konsolu', 7000.00, 8);\nINSERT INTO URUNLER (urun_id, urun_adi, fiyat, stok_miktari) VALUES (4, 'Kablosuz Kulakl\u0131k', 950.00, 50);\nINSERT INTO URUNLER (urun_id, urun_adi, fiyat, stok_miktari) VALUES (5, '4K Monit\u00f6r', 4500.00, 4); -- Stok d\u00fc\u015f\u00fck\nINSERT INTO URUNLER (urun_id, urun_adi, fiyat, stok_miktari) VALUES (6, 'Kamera', 15000.00, 2); -- Stok \u00e7ok d\u00fc\u015f\u00fck\nCOMMIT;\n<\/pre>\n<p><\/code><\/p>\n<p>\u015eimdi, bu tablodaki y\u00fcksek de\u011ferli (fiyat > 1000 TL) ve stok miktar\u0131 5'in alt\u0131nda olan \u00fcr\u00fcnleri bulmak i\u00e7in bir Cursor kullanal\u0131m:<\/p>\n<pre><code>\nDECLARE\n    -- 1. Cursor'\u0131 Tan\u0131mla (DECLARE)\n    CURSOR c_yuksek_degerli_urunler IS\n        SELECT urun_adi, fiyat, stok_miktari\n        FROM URUNLER\n        WHERE fiyat > 1000\n        FOR UPDATE OF stok_miktari; -- \u0130ste\u011fe ba\u011fl\u0131: Sat\u0131rlar\u0131 kilitler\n        \n    v_urun_adi      URUNLER.urun_adi%TYPE;\n    v_fiyat         URUNLER.fiyat%TYPE;\n    v_stok_miktari  URUNLER.stok_miktari%TYPE;\n    \nBEGIN\n    -- 2. Cursor'\u0131 A\u00e7 (OPEN)\n    OPEN c_yuksek_degerli_urunler;\n    \n    LOOP\n        -- 3. Verileri Getir (FETCH)\n        FETCH c_yuksek_degerli_urunler INTO v_urun_adi, v_fiyat, v_stok_miktari;\n        \n        -- E\u011fer daha fazla sat\u0131r yoksa d\u00f6ng\u00fcy\u00fc sonland\u0131r\n        EXIT WHEN c_yuksek_degerli_urunler%NOTFOUND;\n        \n        -- Her bir sat\u0131r i\u00e7in i\u015flem yap\n        DBMS_OUTPUT.PUT_LINE('\u00dcr\u00fcn Ad\u0131: ' || v_urun_adi || ', Fiyat: ' || v_fiyat || ', Stok: ' || v_stok_miktari);\n        \n        IF v_stok_miktari < 5 THEN\n            DBMS_OUTPUT.PUT_LINE('  *** D\u0130KKAT: ' || v_urun_adi || ' i\u00e7in stok miktar\u0131 KR\u0130T\u0130K SEV\u0130YEDE! Yaln\u0131zca ' || v_stok_miktari || ' adet kald\u0131.');\n            -- Burada e-posta g\u00f6nderme, ba\u015fka bir tabloya kay\u0131t atma gibi i\u015flemler yap\u0131labilir.\n            \n            -- Stok miktar\u0131n\u0131 art\u0131rmak veya not eklemek gibi bir g\u00fcncelleme yapabiliriz\n            -- UPDATE URUNLER SET stok_miktari = stok_miktari + 10 WHERE CURRENT OF c_yuksek_degerli_urunler;\n            -- DBMS_OUTPUT.PUT_LINE('  Stok miktar\u0131 10 art\u0131r\u0131ld\u0131.');\n        END IF;\n    END LOOP;\n    \n    -- 4. Cursor'\u0131 Kapat (CLOSE)\n    CLOSE c_yuksek_degerli_urunler;\n    \n    COMMIT; -- E\u011fer UPDATE i\u015flemi yap\u0131ld\u0131ysa, de\u011fi\u015fiklikleri kal\u0131c\u0131 hale getir\n    \nEXCEPTION\n    WHEN OTHERS THEN\n        DBMS_OUTPUT.PUT_LINE('Bir hata olu\u015ftu: ' || SQLERRM);\n        IF c_yuksek_degerli_urunler%ISOPEN THEN\n            CLOSE c_yuksek_degerli_urunler;\n        END IF;\n        ROLLBACK; -- Hata durumunda yap\u0131lan de\u011fi\u015fiklikleri geri al\nEND;\n\/\n<\/pre>\n<p><\/code><\/p>\n<p>Bu kod blo\u011funda, <code>FOR UPDATE OF stok_miktari<\/code> yan c\u00fcmlesi, Cursor taraf\u0131ndan se\u00e7ilen sat\u0131rlar\u0131 kilitler. Bu, siz o sat\u0131r\u0131 i\u015flerken ba\u015fka bir i\u015flemin ayn\u0131 sat\u0131r\u0131 de\u011fi\u015ftirmesini engeller ve veri tutarl\u0131l\u0131\u011f\u0131n\u0131 sa\u011flar. D\u00f6ng\u00fc i\u00e7erisinde <code>c_yuksek_degerli_urunler%NOTFOUND<\/code> \u00f6zelli\u011fini kullanarak Cursor'\u0131n t\u00fcm sat\u0131rlar\u0131 i\u015fleyip i\u015flemedi\u011fini kontrol ediyoruz. E\u011fer <code>UPDATE URUNLER SET stok_miktari = stok_miktari + 10 WHERE CURRENT OF c_yuksek_degerli_urunler;<\/code> gibi bir ifade kullan\u0131rsak, bu, o an Cursor'\u0131n \u00fczerinde durdu\u011fu sat\u0131r\u0131 g\u00fcnceller. Bu, Cursor'lar\u0131n sat\u0131r baz\u0131nda g\u00fcncelleme yapabilme yetene\u011fini g\u00f6sterir.<\/p>\n<div class=\"expert-tip\">\n  Uzman \u0130pucu: Performans hassas uygulamalarda, Cursor'lar yerine m\u00fcmk\u00fcn oldu\u011funca set tabanl\u0131 SQL i\u015flemleri (UPDATE ... WHERE, INSERT ... SELECT gibi) kullanmaya \u00f6zen g\u00f6sterin. Cursor'lar, her sat\u0131r i\u00e7in ba\u011flam de\u011fi\u015ftirme (context switching) maliyeti nedeniyle daha yava\u015f olabilir. Ancak, karma\u015f\u0131k i\u015f mant\u0131\u011f\u0131 veya harici sistemlerle entegrasyon gibi durumlarda Cursor'lar vazge\u00e7ilmezdir. \u00d6zellikle <code>FOR UPDATE<\/code> ile sat\u0131r kilitleme, e\u015fzamanl\u0131l\u0131k sorunlar\u0131n\u0131 \u00e7\u00f6zmek i\u00e7in \u00f6nemlidir.\n<\/div>\n<h2>Trigger'lar ile Veritaban\u0131 Otomasyonu Nas\u0131l Sa\u011flan\u0131r?<\/h2>\n<p>Trigger'lar, Oracle veritabanlar\u0131nda otomasyonun ve veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fcn temel ta\u015flar\u0131ndan biridir. Ad\u0131ndan da anla\u015f\u0131laca\u011f\u0131 gibi, belirli bir olay (event) meydana geldi\u011finde otomatik olarak \"tetiklenen\" PL\/SQL kod bloklar\u0131d\u0131r. Bu olaylar genellikle DML (Data Manipulation Language - INSERT, UPDATE, DELETE) i\u015flemleri, DDL (Data Definition Language - CREATE, ALTER, DROP) i\u015flemleri veya veritaban\u0131 sistem olaylar\u0131 (LOGON, LOGOFF, STARTUP, SHUTDOWN) olabilir. Trigger'lar sayesinde, uygulama katman\u0131nda veya manuel olarak yap\u0131lmas\u0131 gereken bir\u00e7ok i\u015flemi veritaban\u0131 seviyesine ta\u015f\u0131yabilir, b\u00f6ylece i\u015f kurallar\u0131n\u0131n tutarl\u0131 bir \u015fekilde uygulanmas\u0131n\u0131 sa\u011flayabiliriz. Bir Trigger'\u0131n en b\u00fcy\u00fck avantajlar\u0131ndan biri, tetiklendi\u011fi olay\u0131n bir par\u00e7as\u0131 olarak \u00e7al\u0131\u015fmas\u0131d\u0131r; bu da onun ilgili i\u015flemle ayn\u0131 transaction (i\u015flem) i\u00e7inde yer almas\u0131n\u0131 garanti eder. Bu sayede, hem olay\u0131n ger\u00e7ekle\u015fmesi hem de Trigger'\u0131n i\u015fleyi\u015fi atomik bir b\u00fct\u00fcnl\u00fck i\u00e7inde y\u00f6netilir.<\/p>\n<p>Trigger'lar, farkl\u0131 tetiklenme zamanlar\u0131na ve gran\u00fclerlik seviyelerine sahip olabilir. \u00d6rne\u011fin, bir DML i\u015flemi ger\u00e7ekle\u015fmeden \u00f6nce (BEFORE) veya sonra (AFTER) tetiklenebilirler. Ayr\u0131ca, i\u015flemden etkilenen her bir sat\u0131r i\u00e7in (FOR EACH ROW) veya t\u00fcm ifade i\u00e7in sadece bir kez (FOR EACH STATEMENT) \u00e7al\u0131\u015fabilirler. Bu \u00e7e\u015fitlilik, Trigger'lar\u0131 denetim (auditing), karma\u015f\u0131k veri do\u011frulama, otomatik varsay\u0131lan de\u011fer atama, t\u00fcretilmi\u015f verileri g\u00fcncelleme, veri kopyalama veya replikasyon gibi geni\u015f bir kullan\u0131m alan\u0131 yelpazesinde son derece g\u00fc\u00e7l\u00fc k\u0131lar. \u00d6rne\u011fin, bir kullan\u0131c\u0131n\u0131n maa\u015f\u0131n\u0131 g\u00fcncellemeden \u00f6nce eski maa\u015f\u0131n\u0131 bir kay\u0131t tablosuna kaydetmek isteyebilirsiniz (BEFORE UPDATE, FOR EACH ROW). Ya da bir tabloya yeni bir m\u00fc\u015fteri ekledi\u011finizde, bu m\u00fc\u015fteriye otomatik olarak bir ho\u015f geldin e-postas\u0131 g\u00f6nderilmesi gerekti\u011fini tetikleyici ile y\u00f6netebilirsiniz (AFTER INSERT). Bu otomasyon yetene\u011fi, geli\u015ftiricilerin uygulama kodunu daha sade tutmas\u0131na ve veritaban\u0131n\u0131n kendi i\u00e7inde g\u00fc\u00e7l\u00fc i\u015f mant\u0131\u011f\u0131 bar\u0131nd\u0131rmas\u0131na olanak tan\u0131r. Ancak, Trigger'lar\u0131 kullan\u0131rken dikkatli olmak gerekir, \u00e7\u00fcnk\u00fc a\u015f\u0131r\u0131ya ka\u00e7an veya k\u00f6t\u00fc tasarlanm\u0131\u015f Trigger'lar performans\u0131 d\u00fc\u015f\u00fcrebilir, hata ay\u0131klamay\u0131 zorla\u015ft\u0131rabilir ve beklenmeyen yan etkilere yol a\u00e7abilir. Do\u011fru kullan\u0131ld\u0131\u011f\u0131nda, Trigger'lar Oracle veritabanlar\u0131n\u0131z\u0131n omurgas\u0131n\u0131 olu\u015fturan g\u00fc\u00e7l\u00fc ve g\u00fcvenilir ara\u00e7lard\u0131r.<\/p>\n<h3>Bir Denetim (Audit) Trigger'\u0131 Nas\u0131l Olu\u015fturulur?<\/h3>\n<p>Veritabanlar\u0131nda yap\u0131lan de\u011fi\u015fiklikleri izlemek, g\u00fcvenlik, uyumluluk ve hata ay\u0131klama a\u00e7\u0131s\u0131ndan son derece \u00f6nemlidir. Hangi kullan\u0131c\u0131n\u0131n, ne zaman, hangi veriyi ne \u015fekilde de\u011fi\u015ftirdi\u011fini bilmek, denetim (auditing) kay\u0131tlar\u0131n\u0131n temelini olu\u015fturur. Trigger'lar, bu t\u00fcr denetim mekanizmalar\u0131n\u0131 otomatik ve veritaban\u0131 seviyesinde uygulamak i\u00e7in idealdir. Bir denetim Trigger'\u0131 genellikle <code>AFTER INSERT OR UPDATE OR DELETE ON TABLE_NAME FOR EACH ROW<\/code> yap\u0131s\u0131nda tan\u0131mlan\u0131r, \u00e7\u00fcnk\u00fc her bir sat\u0131r de\u011fi\u015fikli\u011finin kaydedilmesi hedeflenir.<\/p>\n<h4>Senaryo: \u00c7al\u0131\u015fan Maa\u015f De\u011fi\u015fikliklerinin Kaydedilmesi<\/h4>\n<p>Bir insan kaynaklar\u0131 sisteminde, \u00e7al\u0131\u015fanlar\u0131n maa\u015f bilgilerinin hassas olmas\u0131 nedeniyle, her maa\u015f de\u011fi\u015fikli\u011finin (ekleme, g\u00fcncelleme, silme) kim taraf\u0131ndan, ne zaman ve hangi de\u011ferlerle yap\u0131ld\u0131\u011f\u0131n\u0131n kay\u0131t alt\u0131na al\u0131nmas\u0131 gerekmektedir. Bunun i\u00e7in bir <code>CALISANLAR<\/code> tablosu ve bir <code>MAAS_DENETIM_LOG<\/code> tablosu olu\u015fturup, bu iki tablo aras\u0131nda bir Trigger ile denetim mekanizmas\u0131n\u0131 kuraca\u011f\u0131z.<\/p>\n<p>\u00d6ncelikle, tablolar\u0131m\u0131z\u0131 olu\u015ftural\u0131m:<\/p>\n<pre><code>\n-- CALISANLAR tablosu\nCREATE TABLE CALISANLAR (\n    calisan_id NUMBER PRIMARY KEY,\n    ad VARCHAR2(50),\n    soyad VARCHAR2(50),\n    maas NUMBER(10, 2)\n);\n\n-- Denetim log tablosu\nCREATE TABLE MAAS_DENETIM_LOG (\n    log_id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY,\n    calisan_id NUMBER,\n    eski_maas NUMBER(10, 2),\n    yeni_maas NUMBER(10, 2),\n    islem_turu VARCHAR2(10), -- 'INSERT', 'UPDATE', 'DELETE'\n    islem_tarihi TIMESTAMP DEFAULT SYSTIMESTAMP,\n    islem_yapan_kullanici VARCHAR2(100) DEFAULT USER\n);\n\n-- Test verisi ekleyelim\nINSERT INTO CALISANLAR (calisan_id, ad, soyad, maas) VALUES (101, 'Ay\u015fe', 'Y\u0131lmaz', 5000.00);\nINSERT INTO CALISANLAR (calisan_id, ad, soyad, maas) VALUES (102, 'Can', 'Demir', 6000.00);\nCOMMIT;\n<\/pre>\n<p><\/code><\/p>\n<p>\u015eimdi, <code>CALISANLAR<\/code> tablosundaki maa\u015f de\u011fi\u015fikliklerini <code>MAAS_DENETIM_LOG<\/code> tablosuna kaydedecek Trigger'\u0131 olu\u015ftural\u0131m:<\/p>\n<pre><code>\nCREATE OR REPLACE TRIGGER trg_maas_denetimi\nAFTER INSERT OR UPDATE OR DELETE ON CALISANLAR\nFOR EACH ROW\nDECLARE\n    v_islem_turu MAAS_DENETIM_LOG.islem_turu%TYPE;\nBEGIN\n    IF INSERTING THEN\n        v_islem_turu := 'INSERT';\n        INSERT INTO MAAS_DENETIM_LOG (calisan_id, eski_maas, yeni_maas, islem_turu)\n        VALUES (:NEW.calisan_id, NULL, :NEW.maas, v_islem_turu);\n    ELSIF UPDATING THEN\n        v_islem_turu := 'UPDATE';\n        INSERT INTO MAAS_DENETIM_LOG (calisan_id, eski_maas, yeni_maas, islem_turu)\n        VALUES (:NEW.calisan_id, :OLD.maas, :NEW.maas, v_islem_turu);\n    ELSIF DELETING THEN\n        v_islem_turu := 'DELETE';\n        INSERT INTO MAAS_DENETIM_LOG (calisan_id, eski_maas, yeni_maas, islem_turu)\n        VALUES (:OLD.calisan_id, :OLD.maas, NULL, v_islem_turu);\n    END IF;\nEND;\n\/\n<\/pre>\n<p><\/code><\/p>\n<p>Bu Trigger'\u0131 inceleyelim:<\/p>\n<ul>\n<li><code>AFTER INSERT OR UPDATE OR DELETE ON CALISANLAR<\/code>: Bu Trigger, <code>CALISANLAR<\/code> tablosunda bir ekleme, g\u00fcncelleme veya silme i\u015flemi sonras\u0131nda tetiklenecektir.<\/li>\n<li><code>FOR EACH ROW<\/code>: \u0130\u015flemden etkilenen her bir sat\u0131r i\u00e7in ayr\u0131 ayr\u0131 \u00e7al\u0131\u015f\u0131r. Bu, denetim kay\u0131tlar\u0131 i\u00e7in idealdir \u00e7\u00fcnk\u00fc her sat\u0131r\u0131n eski ve yeni de\u011ferlerini yakalamam\u0131z\u0131 sa\u011flar.<\/li>\n<li><code>:NEW<\/code> ve <code>:OLD<\/code> Pseudo-kay\u0131tlar\u0131: Bu \u00f6zel de\u011fi\u015fkenler, Trigger i\u00e7indeki sat\u0131r baz\u0131nda operasyonlarda \u00e7ok \u00f6nemlidir.\n<ul>\n<li><code>:NEW<\/code>: INSERT veya UPDATE i\u015fleminden sonraki sat\u0131r\u0131n yeni de\u011ferlerini temsil eder.<\/li>\n<li><code>:OLD<\/code>: UPDATE veya DELETE i\u015fleminden \u00f6nceki sat\u0131r\u0131n eski de\u011ferlerini temsil eder.<\/li>\n<\/ul>\n<\/li>\n<li><code>INSERTING<\/code>, <code>UPDATING<\/code>, <code>DELETING<\/code> Ko\u015fullar\u0131: Bu ko\u015fullar, Trigger'\u0131n hangi DML i\u015flemi taraf\u0131ndan tetiklendi\u011fini anlamam\u0131z\u0131 sa\u011flar ve buna g\u00f6re farkl\u0131 mant\u0131klar uygulamam\u0131za olanak tan\u0131r.<\/li>\n<\/ul>\n<p>Trigger'\u0131n \u00e7al\u0131\u015fmas\u0131n\u0131 test edelim:<\/p>\n<pre><code>\n-- Yeni \u00e7al\u0131\u015fan ekle\nINSERT INTO CALISANLAR (calisan_id, ad, soyad, maas) VALUES (103, 'Elif', 'Kara', 7500.00);\n-- Maa\u015f\u0131 g\u00fcncelle\nUPDATE CALISANLAR SET maas = 5500.00 WHERE calisan_id = 101;\n-- \u00c7al\u0131\u015fan\u0131 sil\nDELETE FROM CALISANLAR WHERE calisan_id = 102;\nCOMMIT;\n\n-- Denetim kay\u0131tlar\u0131n\u0131 kontrol et\nSELECT * FROM MAAS_DENETIM_LOG ORDER BY log_id;\n<\/pre>\n<p><\/code><\/p>\n<p>Yukar\u0131daki sorguyu \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131n\u0131zda, <code>MAAS_DENETIM_LOG<\/code> tablosunda yap\u0131lan t\u00fcm de\u011fi\u015fikliklerin eksiksiz bir \u015fekilde kaydedildi\u011fini g\u00f6receksiniz. Bu, Trigger'\u0131n denetim ihtiya\u00e7lar\u0131 i\u00e7in ne kadar g\u00fc\u00e7l\u00fc bir ara\u00e7 oldu\u011funu g\u00f6stermektedir. Bu sayede, kimin ne zaman hangi veriyi de\u011fi\u015ftirdi\u011fini kolayca takip edebilir, herhangi bir tutars\u0131zl\u0131k durumunda ge\u00e7mi\u015fe d\u00f6n\u00fck bilgilere ula\u015fabiliriz.<\/p>\n<div class=\"expert-tip\">\n  Uzman \u0130pucu: Denetim Trigger'lar\u0131 genellikle <code>AFTER<\/code> tetikleyiciler olarak olu\u015fturulur. Bunun nedeni, i\u015flemin ba\u015far\u0131l\u0131 bir \u015fekilde tamamland\u0131\u011f\u0131ndan emin olduktan sonra loglama yapmakt\u0131r. E\u011fer i\u015flem ba\u015far\u0131s\u0131z olursa, loglama yap\u0131lmas\u0131na gerek kalmaz. Ayr\u0131ca, <code>:NEW<\/code> ve <code>:OLD<\/code> de\u011ferlerini kullan\u0131rken veri tiplerinin e\u015fle\u015fti\u011finden emin olun.\n<\/div>\n<h3>Veri B\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc Sa\u011flayan Trigger \u00d6rnekleri<\/h3>\n<p>Veri b\u00fct\u00fcnl\u00fc\u011f\u00fc, bir veritaban\u0131 sisteminin g\u00fcvenilirli\u011fi ve do\u011frulu\u011fu i\u00e7in temel bir gerekliliktir. Oracle, birincil anahtarlar, yabanc\u0131 anahtarlar, benzersiz k\u0131s\u0131tlamalar ve CHECK k\u0131s\u0131tlamalar\u0131 gibi declarative (bildirimsel) b\u00fct\u00fcnl\u00fck k\u0131s\u0131tlamalar\u0131 sunsa da, bazen bu k\u0131s\u0131tlamalar\u0131n \u00f6tesine ge\u00e7en karma\u015f\u0131k i\u015f kurallar\u0131n\u0131 uygulamam\u0131z gerekebilir. \u0130\u015fte bu noktada Trigger'lar, veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc programatik olarak zorlamak i\u00e7in son derece esnek ve g\u00fc\u00e7l\u00fc bir ara\u00e7 haline gelirler. Trigger'lar sayesinde, verilerin belirli bir formatta olmas\u0131n\u0131 sa\u011flayabilir, tablolar aras\u0131 karma\u015f\u0131k ili\u015fkileri y\u00f6netebilir veya belirli ko\u015fullar alt\u0131nda veri de\u011fi\u015fikliklerini engelleyebiliriz. Bu, uygulaman\u0131n farkl\u0131 yerlerinden gelen veri giri\u015flerinin bile ayn\u0131 kurallara uymas\u0131n\u0131 garanti eder ve veri tutars\u0131zl\u0131klar\u0131n\u0131 ba\u015ftan engeller.<\/p>\n<p>\u00d6rne\u011fin, bir bankac\u0131l\u0131k uygulamas\u0131nda, bir hesab\u0131n bakiyesinin asla negatif olmamas\u0131 gerekti\u011fini garanti etmek isteyebilirsiniz. Standart bir CHECK k\u0131s\u0131tlamas\u0131 bunu yapabilir, ancak bakiye birden fazla i\u015flemle de\u011fi\u015fiyor ve her i\u015flemin bir kural seti ile do\u011frulanmas\u0131 gerekiyorsa, Trigger daha uygun bir \u00e7\u00f6z\u00fcm olabilir. Veya bir \u00e7al\u0131\u015fan\u0131n terfi etmesi durumunda, yeni pozisyonunun maa\u015f aral\u0131\u011f\u0131 ile eski maa\u015f\u0131n\u0131n uyumlu olup olmad\u0131\u011f\u0131n\u0131 kontrol etmek gibi dinamik kurallar Trigger'lar arac\u0131l\u0131\u011f\u0131yla uygulanabilir. Trigger'lar, genellikle <code>BEFORE INSERT<\/code> veya <code>BEFORE UPDATE<\/code> olaylar\u0131nda veri do\u011frulama i\u00e7in kullan\u0131l\u0131r, \u00e7\u00fcnk\u00fc bu, verinin tablolara kaydedilmeden \u00f6nce kontrol edilmesini ve potansiyel olarak hatal\u0131 i\u015flemlerin ba\u015ftan engellenmesini sa\u011flar. Bu sayede, veritaban\u0131na yanl\u0131\u015f veya tutars\u0131z veri girilmesi engellenmi\u015f olur, bu da sistemin genel g\u00fcvenilirli\u011fini art\u0131r\u0131r. Bu esnek yap\u0131, \u00f6zellikle dinamik ve karma\u015f\u0131k i\u015f kurallar\u0131na sahip uygulamalar i\u00e7in vazge\u00e7ilmez bir otomasyon katman\u0131 sunar.<\/p>\n<h4>Senaryo: Sipari\u015f Miktar\u0131n\u0131n Stoktan Fazla Olmamas\u0131n\u0131 Sa\u011flama<\/h4>\n<p>Bir sat\u0131\u015f sipari\u015fi olu\u015fturulurken, sipari\u015f edilen \u00fcr\u00fcn miktar\u0131n\u0131n mevcut stok miktar\u0131n\u0131 a\u015fmamas\u0131n\u0131 sa\u011flamak kritik bir veri b\u00fct\u00fcnl\u00fc\u011f\u00fc kural\u0131d\u0131r. Bu kural, envanterin do\u011fru y\u00f6netilmesi ve m\u00fc\u015fterilere yanl\u0131\u015f vaatlerde bulunulmamas\u0131 i\u00e7in hayati \u00f6neme sahiptir. Bu senaryo i\u00e7in <code>URUNLER<\/code> (az \u00f6nce olu\u015fturdu\u011fumuz) ve yeni bir <code>SIPARIS_DETAY<\/code> tablosu kullanal\u0131m.<\/p>\n<p><code>SIPARIS_DETAY<\/code> tablosunu olu\u015ftural\u0131m:<\/p>\n<pre><code>\nCREATE TABLE SIPARIS_DETAY (\n    siparis_detay_id NUMBER PRIMARY KEY,\n    siparis_id NUMBER,\n    urun_id NUMBER,\n    miktar NUMBER(5),\n    FOREIGN KEY (urun_id) REFERENCES URUNLER(urun_id)\n);\n<\/pre>\n<p><\/code><\/p>\n<p>\u015eimdi, <code>SIPARIS_DETAY<\/code> tablosuna bir kay\u0131t eklenmeden \u00f6nce \u00e7al\u0131\u015facak ve sipari\u015f miktar\u0131n\u0131n stoktan fazla olup olmad\u0131\u011f\u0131n\u0131 kontrol edecek bir Trigger olu\u015ftural\u0131m:<\/p>\n<pre><code>\nCREATE OR REPLACE TRIGGER trg_siparis_miktar_kontrol\nBEFORE INSERT ON SIPARIS_DETAY\nFOR EACH ROW\nDECLARE\n    v_mevcut_stok NUMBER(5);\nBEGIN\n    -- Sipari\u015f edilen \u00fcr\u00fcn\u00fcn mevcut stok miktar\u0131n\u0131 al\n    SELECT stok_miktari\n    INTO v_mevcut_stok\n    FROM URUNLER\n    WHERE urun_id = :NEW.urun_id;\n\n    -- E\u011fer sipari\u015f miktar\u0131 mevcut stoktan fazlaysa hata f\u0131rlat\n    IF :NEW.miktar > v_mevcut_stok THEN\n        RAISE_APPLICATION_ERROR(-20001, 'HATA: Sipari\u015f edilen miktar (' || :NEW.miktar || \n                                        ') mevcut stoktan (' || v_mevcut_stok || \n                                        ') fazla olamaz. Urun ID: ' || :NEW.urun_id);\n    END IF;\nEXCEPTION\n    WHEN NO_DATA_FOUND THEN\n        RAISE_APPLICATION_ERROR(-20002, 'HATA: Sipari\u015f edilen \u00fcr\u00fcn bulunamad\u0131. Urun ID: ' || :NEW.urun_id);\n    WHEN OTHERS THEN\n        RAISE_APPLICATION_ERROR(-20003, 'Sipari\u015f miktar\u0131 kontrol\u00fcnde beklenmeyen bir hata olu\u015ftu: ' || SQLERRM);\nEND;\n\/\n<\/pre>\n<p><\/code><\/p>\n<p>Bu Trigger'\u0131n \u00f6zellikleri:<\/p>\n<ul>\n<li><code>BEFORE INSERT ON SIPARIS_DETAY<\/code>: Bu Trigger, <code>SIPARIS_DETAY<\/code> tablosuna bir sat\u0131r eklenmeden hemen \u00f6nce tetiklenecektir. Bu, verinin kaydedilmesini engellemek i\u00e7in ideal bir zamand\u0131r.<\/li>\n<li><code>FOR EACH ROW<\/code>: Her bir yeni sipari\u015f detay\u0131 sat\u0131r\u0131 i\u00e7in ayr\u0131 ayr\u0131 kontrol yapar.<\/li>\n<li><code>RAISE_APPLICATION_ERROR(-20001, ...)<\/code>: Bu fonksiyon, belirli bir hata kodu ve mesaj\u0131yla PL\/SQL hata f\u0131rlatmak i\u00e7in kullan\u0131l\u0131r. Bu hata, i\u015flemi durdurur ve geri al\u0131r. Kullan\u0131c\u0131ya a\u00e7\u0131klay\u0131c\u0131 bir hata mesaj\u0131 iletilir.<\/li>\n<li>Hata Yakalama (EXCEPTION): <code>NO_DATA_FOUND<\/code> ve <code>OTHERS<\/code> ile \u00fcr\u00fcn bulunamamas\u0131 veya ba\u015fka bir beklenmeyen hata durumlar\u0131 da ele al\u0131nm\u0131\u015ft\u0131r.<\/li>\n<\/ul>\n<p>Trigger'\u0131 test edelim:<\/p>\n<pre><code>\n-- Ge\u00e7erli sipari\u015f (stok yeterli)\nINSERT INTO SIPARIS_DETAY (siparis_detay_id, siparis_id, urun_id, miktar) VALUES (1, 100, 1, 10);\nCOMMIT; -- Bu i\u015flem ba\u015far\u0131l\u0131 olmal\u0131\n\n-- Ge\u00e7ersiz sipari\u015f (stok yetersiz - Urun ID 5 (4K Monit\u00f6r) i\u00e7in stok 4)\nINSERT INTO SIPARIS_DETAY (siparis_detay_id, siparis_id, urun_id, miktar) VALUES (2, 100, 5, 5);\n-- Bu sat\u0131r yukar\u0131daki Trigger nedeniyle hata verecek ve ROLLBACK olacakt\u0131r.\n-- Hata mesaj\u0131: ORA-20001: HATA: Sipari\u015f edilen miktar (5) mevcut stoktan (4) fazla olamaz. Urun ID: 5\n\n-- Olmayan \u00fcr\u00fcn i\u00e7in sipari\u015f\nINSERT INTO SIPARIS_DETAY (siparis_detay_id, siparis_id, urun_id, miktar) VALUES (3, 101, 999, 1);\n-- Hata mesaj\u0131: ORA-20002: HATA: Sipari\u015f edilen \u00fcr\u00fcn bulunamad\u0131. Urun ID: 999\n<\/pre>\n<p><\/code><\/p>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi, ikinci <code>INSERT<\/code> i\u015flemi, Trigger taraf\u0131ndan yakalan\u0131r ve stok yetersizli\u011fi nedeniyle ba\u015far\u0131s\u0131z olur. Bu, veritaban\u0131 seviyesinde veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fcn nas\u0131l g\u00fc\u00e7l\u00fc bir \u015fekilde korunabilece\u011fine dair m\u00fckemmel bir \u00f6rnektir. Bu t\u00fcr Trigger'lar, karma\u015f\u0131k i\u015f kurallar\u0131n\u0131n do\u011fru ve tutarl\u0131 bir \u015fekilde uygulanmas\u0131n\u0131 garantiler, uygulama katman\u0131ndaki hatalar\u0131n veritaban\u0131na ula\u015fmas\u0131n\u0131 engeller ve genel sistem kararl\u0131l\u0131\u011f\u0131n\u0131 art\u0131r\u0131r.<\/p>\n<h2>Cursor ve Trigger Kullan\u0131m\u0131nda \u0130leri D\u00fczey \u0130pu\u00e7lar\u0131 ve En \u0130yi Uygulamalar<\/h2>\n<p>Cursor'lar ve Trigger'lar Oracle veritaban\u0131 programlamas\u0131nda g\u00fc\u00e7l\u00fc ara\u00e7lar olsa da, bu ara\u00e7lar\u0131n yanl\u0131\u015f veya a\u015f\u0131r\u0131 kullan\u0131m\u0131 performans sorunlar\u0131na, karma\u015f\u0131kl\u0131\u011fa ve hata ay\u0131klama zorluklar\u0131na yol a\u00e7abilir. Bu nedenle, bunlar\u0131 etkin ve verimli bir \u015fekilde kullanmak i\u00e7in baz\u0131 ileri d\u00fczey ipu\u00e7lar\u0131n\u0131 ve en iyi uygulamalar\u0131 anlamak kritik \u00f6neme sahiptir. Bu b\u00f6l\u00fcmde, hem performans optimizasyonuna hem de kod kalitesine odaklanarak bu ara\u00e7lar\u0131 nas\u0131l daha iyi kullanabilece\u011finizi ele alaca\u011f\u0131z. Veritaban\u0131 sistemlerinin s\u00fcrekli olarak y\u00fcksek performansla \u00e7al\u0131\u015fmas\u0131, \u00f6zellikle b\u00fcy\u00fck \u00f6l\u00e7ekli ve yo\u011fun i\u015flem g\u00f6ren ortamlarda hayati bir gereksinimdir. Trigger'lar gibi otomatikle\u015fen mekanizmalar\u0131n veya Cursor'lar gibi sat\u0131r baz\u0131nda i\u015flem yapan yap\u0131lar\u0131n bilin\u00e7sizce kullan\u0131lmas\u0131, t\u00fcm sistem \u00fczerinde domino etkisi yaratabilecek performans darbo\u011fazlar\u0131na neden olabilir. Dolay\u0131s\u0131yla, bu ara\u00e7lar\u0131 sadece ne i\u015fe yarad\u0131klar\u0131n\u0131 bilmek de\u011fil, ayn\u0131 zamanda ne zaman ve nas\u0131l kullan\u0131lmalar\u0131 gerekti\u011fini de derinlemesine kavramak gerekmektedir. \u0130leri d\u00fczey uygulamalar genellikle daha karma\u015f\u0131k senaryolar\u0131 kapsar ve bu senaryolarda do\u011fru ara\u00e7 se\u00e7imi, projenin ba\u015far\u0131s\u0131 i\u00e7in belirleyici olabilir. Ayr\u0131ca, g\u00fcvenlik ve s\u00fcrd\u00fcr\u00fclebilirlik gibi konular da bu ara\u00e7lar\u0131n tasar\u0131m\u0131 ve uygulanmas\u0131 s\u0131ras\u0131nda g\u00f6z \u00f6n\u00fcnde bulundurulmal\u0131d\u0131r.<\/p>\n<p>Bir di\u011fer \u00f6nemli nokta ise, Cursor'lar ve Trigger'lar aras\u0131nda do\u011fru dengeyi kurmakt\u0131r. Cursor'lar, belirli veri k\u00fcmeleri \u00fczerinde detayl\u0131 ve programatik kontrol sa\u011flarken, Trigger'lar olay tabanl\u0131 otomasyon sunar. Her birinin kendine \u00f6zg\u00fc g\u00fc\u00e7l\u00fc y\u00f6nleri ve s\u0131n\u0131rlamalar\u0131 vard\u0131r. \u00d6rne\u011fin, b\u00fcy\u00fck veri k\u00fcmeleri \u00fczerinde sat\u0131r baz\u0131nda i\u015flem yap\u0131lmas\u0131 gereken ancak veritaban\u0131 sistem kaynaklar\u0131n\u0131n k\u0131s\u0131tl\u0131 oldu\u011fu durumlarda Cursor'lar\u0131n performans\u0131 dikkatle de\u011ferlendirilmelidir. Benzer \u015fekilde, \u00e7ok say\u0131da Trigger'\u0131n ayn\u0131 tablo \u00fczerinde \u00e7al\u0131\u015fmas\u0131, bir DML i\u015flemi ger\u00e7ekle\u015fti\u011finde beklemeyen bir i\u015flem zincirine yol a\u00e7abilir, bu da performans\u0131 d\u00fc\u015f\u00fcr\u00fcr ve hata ay\u0131klamay\u0131 son derece karma\u015f\u0131k hale getirir. Bu nedenle, bu ara\u00e7lar\u0131 tasarlarken sadece mevcut ihtiyac\u0131 kar\u015f\u0131lamakla kalmay\u0131p, gelecekteki \u00f6l\u00e7eklenebilirlik, bak\u0131m kolayl\u0131\u011f\u0131 ve olas\u0131 performans etkilerini de hesaba katmak ak\u0131ll\u0131ca olacakt\u0131r. En iyi uygulamalar\u0131 takip etmek, daha robust (sa\u011flam), daha y\u00f6netilebilir ve daha performansl\u0131 Oracle \u00e7\u00f6z\u00fcmleri geli\u015ftirmenize yard\u0131mc\u0131 olacakt\u0131r.<\/p>\n<h3>Performans Optimizasyonu<\/h3>\n<ol>\n<li><strong>Cursor'lar i\u00e7in Set Tabanl\u0131 \u0130\u015flemleri Tercih Edin:<\/strong> M\u00fcmk\u00fcn oldu\u011funca, tek bir <code>UPDATE<\/code>, <code>INSERT<\/code> veya <code>DELETE<\/code> sorgusu ile t\u00fcm veri k\u00fcmesini i\u015fleyin. Cursor'lar her sat\u0131r i\u00e7in Oracle ile PL\/SQL aras\u0131nda ba\u011flam de\u011fi\u015ftirme (context switching) maliyeti getirir, bu da performans\u0131 d\u00fc\u015f\u00fcr\u00fcr. E\u011fer bir Cursor kullanmak zorundaysan\u0131z, <code>FOR UPDATE<\/code> gibi ifadelerle sat\u0131rlar\u0131 kilitlerken dikkatli olun, \u00e7\u00fcnk\u00fc bu e\u015fzamanl\u0131l\u0131\u011f\u0131 etkileyebilir.<\/li>\n<li><strong><code>FOR<\/code> D\u00f6ng\u00fcs\u00fc Cursor'lar\u0131 Kullan\u0131n:<\/strong> A\u00e7\u0131k Cursor'lar\u0131n <code>DECLARE<\/code>, <code>OPEN<\/code>, <code>FETCH<\/code>, <code>CLOSE<\/code> ad\u0131mlar\u0131n\u0131 manuel olarak y\u00f6netmek yerine, <code>FOR ... IN ... LOOP<\/code> yap\u0131s\u0131n\u0131 tercih edin. Bu, PL\/SQL'in Cursor y\u00f6netimini otomatik olarak yapmas\u0131n\u0131 sa\u011flar ve daha temiz, daha az hataya a\u00e7\u0131k kod yazman\u0131za yard\u0131mc\u0131 olur.\n<pre><code>\n-- FOR d\u00f6ng\u00fcs\u00fc Cursor \u00f6rne\u011fi\nFOR rec IN (SELECT urun_adi, stok_miktari FROM URUNLER WHERE stok_miktari < 10) LOOP\n    DBMS_OUTPUT.PUT_LINE('D\u00fc\u015f\u00fck Stok: ' || rec.urun_adi || ' - ' || rec.stok_miktari);\nEND LOOP;\n        <\/pre>\n<p><\/code>\n    <\/li>\n<li><strong>Bulk Collect ve Forall Kullan\u0131m\u0131:<\/strong> B\u00fcy\u00fck veri k\u00fcmelerini i\u015flerken, Cursor'lar\u0131 <code>BULK COLLECT<\/code> ile toplu olarak belle\u011fe alabilir ve <code>FORALL<\/code> ile toplu DML i\u015flemleri yapabilirsiniz. Bu, ba\u011flam de\u011fi\u015ftirme say\u0131s\u0131n\u0131 \u00f6nemli \u00f6l\u00e7\u00fcde azaltarak performans\u0131 art\u0131r\u0131r.\n<pre><code>\nDECLARE\n    TYPE t_urun_bilgi IS TABLE OF URUNLER%ROWTYPE INDEX BY PLS_INTEGER;\n    v_urunler t_urun_bilgi;\nBEGIN\n    SELECT *\n    BULK COLLECT INTO v_urunler\n    FROM URUNLER\n    WHERE stok_miktari < 10;\n\n    FORALL i IN 1 .. v_urunler.COUNT\n        UPDATE URUNLER\n        SET stok_miktari = stok_miktari + 5\n        WHERE urun_id = v_urunler(i).urun_id;\n    COMMIT;\nEND;\n\/\n        <\/pre>\n<p><\/code>\n    <\/li>\n<li><strong>Trigger'larda Ko\u015fullu Mant\u0131k:<\/strong> Trigger'lar\u0131n\u0131z\u0131 her zaman ko\u015fullu olarak \u00e7al\u0131\u015ft\u0131rmaya \u00e7al\u0131\u015f\u0131n. \u00d6rne\u011fin, sadece belirli bir s\u00fctun g\u00fcncellendi\u011finde tetiklenmesini istiyorsan\u0131z <code>WHEN (OLD.kolon_adi != NEW.kolon_adi)<\/code> veya <code>IF UPDATING('kolon_adi')<\/code> gibi ko\u015fullar ekleyin. Bu, gereksiz Trigger tetiklenmelerini ve dolay\u0131s\u0131yla performans\u0131 etkileyen i\u015f y\u00fck\u00fcn\u00fc azalt\u0131r.<\/li>\n<\/ol>\n<h3>Hata Y\u00f6netimi<\/h3>\n<p>Hem Cursor'larda hem de Trigger'larda sa\u011flam hata y\u00f6netimi \u00e7ok \u00f6nemlidir. \u00d6zellikle Trigger'lar, bir veritaban\u0131 i\u015fleminin bir par\u00e7as\u0131 olduklar\u0131 i\u00e7in, i\u00e7lerindeki bir hata t\u00fcm i\u015flemi geri alabilir (ROLLBACK) ve uygulama katman\u0131nda beklenmeyen davran\u0131\u015flara neden olabilir.<\/p>\n<ol>\n<li><strong>EXCEPTION Bloklar\u0131 Kullan\u0131n:<\/strong> PL\/SQL bloklar\u0131n\u0131zda her zaman <code>EXCEPTION<\/code> bloklar\u0131n\u0131 kullanarak olas\u0131 hatalar\u0131 yakalay\u0131n ve uygun \u015fekilde ele al\u0131n. Bu, beklenmedik sistem \u00e7\u00f6k\u00fc\u015flerini engeller.<\/li>\n<li><strong>A\u00e7\u0131k Cursor'lar\u0131 Kapatma Garantisi:<\/strong> A\u00e7\u0131k Cursor kullan\u0131yorsan\u0131z, <code>EXCEPTION<\/code> blo\u011funda bile olsa Cursor'\u0131n kapat\u0131ld\u0131\u011f\u0131ndan emin olun (<code>IF c_cursor_adi%ISOPEN THEN CLOSE c_cursor_adi; END IF;<\/code>). Aksi takdirde, a\u00e7\u0131k kalan Cursor'lar kaynak s\u0131z\u0131nt\u0131s\u0131na yol a\u00e7abilir.<\/li>\n<li><strong><code>RAISE_APPLICATION_ERROR<\/code>:<\/strong> Trigger'larda i\u015f kural\u0131 ihlalleri gibi durumlarda \u00f6zel hata mesajlar\u0131 d\u00f6nd\u00fcrmek i\u00e7in <code>RAISE_APPLICATION_ERROR<\/code> kullan\u0131n. Bu, uygulama katman\u0131n\u0131n hatay\u0131 anlamas\u0131na ve kullan\u0131c\u0131ya daha anlaml\u0131 geri bildirim sa\u011flamas\u0131na yard\u0131mc\u0131 olur.<\/li>\n<\/ol>\n<div class=\"expert-tip\">\n  Uzman \u0130pucu: Trigger'lar zincirleme etkiler yaratabilir. Bir Trigger'\u0131n ba\u015fka bir Trigger'\u0131 tetikledi\u011fi durumlar, hem performans hem de hata ay\u0131klama a\u00e7\u0131s\u0131ndan karma\u015f\u0131kl\u0131\u011f\u0131 art\u0131r\u0131r. Bu t\u00fcr durumlarda dikkatli olun ve Trigger zincirlerini m\u00fcmk\u00fcn oldu\u011funca k\u0131sa tutmaya \u00e7al\u0131\u015f\u0131n. G\u00fcvenlik a\u00e7\u0131s\u0131ndan, Trigger'lar\u0131 sadece yetkili kullan\u0131c\u0131lar\u0131n olu\u015fturabilmesini ve de\u011fi\u015ftirebilmesini sa\u011flay\u0131n.\n<\/div>\n<h2>Ger\u00e7ek D\u00fcnya Senaryosu: Stok Y\u00f6netiminde Cursor ve Trigger Entegrasyonu<\/h2>\n<p>Modern i\u015f uygulamalar\u0131nda, veritaban\u0131 i\u015flemlerinin otomatikle\u015ftirilmesi ve veri tutarl\u0131l\u0131\u011f\u0131n\u0131n sa\u011flanmas\u0131 hayati \u00f6neme sahiptir. Bu b\u00f6l\u00fcmde, bir e-ticaret platformunun stok y\u00f6netim sisteminde hem Cursor'lar\u0131n hem de Trigger'lar\u0131n nas\u0131l entegre edilebilece\u011fine dair kapsaml\u0131 bir ger\u00e7ek d\u00fcnya senaryosu inceleyece\u011fiz. Bu senaryo, \u00fcr\u00fcnlerin sat\u0131\u015f i\u015flemlerine g\u00f6re stok miktar\u0131n\u0131n otomatik g\u00fcncellenmesini ve belirli bir stok seviyesinin alt\u0131na d\u00fc\u015fen \u00fcr\u00fcnlerin otomatik olarak yeniden sipari\u015f i\u00e7in i\u015faretlenmesini i\u00e7ermektedir. Bu entegrasyon, manuel m\u00fcdahaleyi azaltarak operasyonel verimlili\u011fi art\u0131r\u0131r ve stok tutars\u0131zl\u0131klar\u0131ndan kaynaklanabilecek m\u00fc\u015fteri memnuniyetsizli\u011fini \u00f6nler.<\/p>\n<p>Bu senaryonun karma\u015f\u0131kl\u0131\u011f\u0131, sadece bir \u00fcr\u00fcn sat\u0131ld\u0131\u011f\u0131nda stok miktar\u0131n\u0131 d\u00fc\u015f\u00fcrmekle kalmay\u0131p, ayn\u0131 zamanda belirli e\u015fik de\u011ferlere g\u00f6re ek aksiyonlar al\u0131nmas\u0131n\u0131 da gerektirmesidir. \u00d6rne\u011fin, bir \u00fcr\u00fcn\u00fcn stoku kritik seviyenin alt\u0131na d\u00fc\u015ft\u00fc\u011f\u00fcnde, otomatik olarak tedarik\u00e7iye bildirim g\u00f6nderme veya bir \"yeniden sipari\u015f\" listesine ekleme gibi i\u015flemler Trigger'lar ve Cursor'lar arac\u0131l\u0131\u011f\u0131yla kusursuzca y\u00f6netilebilir. Bu, \u00f6zellikle binlerce \u00fcr\u00fcn ve g\u00fcnl\u00fck y\u00fczlerce sipari\u015f ile \u00e7al\u0131\u015fan b\u00fcy\u00fck perakende i\u015fletmeleri i\u00e7in b\u00fcy\u00fck bir avantaj sa\u011flar. Veritaban\u0131 seviyesinde otomasyon, uygulama katman\u0131n\u0131n daha sade ve odakl\u0131 kalmas\u0131na yard\u0131mc\u0131 olurken, ayn\u0131 zamanda i\u015f kurallar\u0131n\u0131n istikrarl\u0131 bir \u015fekilde uygulanmas\u0131n\u0131 garanti eder. Bu entegrasyon, yaln\u0131zca operasyonel faydalar sa\u011flamakla kalmaz, ayn\u0131 zamanda veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc g\u00fc\u00e7lendirir ve envanter y\u00f6netimini \u00e7ok daha proaktif hale getirir.<\/p>\n<p>Senaryomuz i\u00e7in iki ana bile\u015fenimiz olacak:<\/p>\n<ol>\n<li><strong>Trigger:<\/strong> Bir sipari\u015f detay\u0131 eklendi\u011finde (yani bir \u00fcr\u00fcn sat\u0131ld\u0131\u011f\u0131nda), ilgili \u00fcr\u00fcn\u00fcn stok miktar\u0131n\u0131 otomatik olarak d\u00fc\u015f\u00fcrecek ve e\u011fer stok kritik seviyenin alt\u0131na d\u00fc\u015ferse bir bildirim veya log kayd\u0131 olu\u015fturacak bir Trigger.<\/li>\n<li><strong>Cursor:<\/strong> Belirli periyotlarla \u00e7al\u0131\u015ft\u0131r\u0131larak (\u00f6rne\u011fin gece batch i\u015fi), stok miktar\u0131 \u00e7ok d\u00fc\u015f\u00fck olan \u00fcr\u00fcnleri tespit edecek ve bunlar\u0131 \"yeniden sipari\u015f\" tablosuna ekleyecek bir Cursor.<\/li>\n<\/ol>\n<p>Tablolar\u0131m\u0131z (<code>URUNLER<\/code> ve <code>SIPARIS_DETAY<\/code> daha \u00f6nce olu\u015fturulmu\u015ftu):<\/p>\n<pre><code>\n-- Stok kritik seviye uyar\u0131s\u0131\/yeniden sipari\u015f i\u00e7in yeni tablo\nCREATE TABLE YENIDEN_SIPARIS_LISTESI (\n    liste_id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY,\n    urun_id NUMBER,\n    talep_edilen_miktar NUMBER(5),\n    talep_tarihi TIMESTAMP DEFAULT SYSTIMESTAMP,\n    durum VARCHAR2(20) DEFAULT 'Beklemede',\n    FOREIGN KEY (urun_id) REFERENCES URUNLER(urun_id)\n);\n<\/pre>\n<p><\/code><\/p>\n<h3>Ad\u0131m 1: Sat\u0131\u015f Oldu\u011funda Stok D\u00fc\u015f\u00fcren Trigger<\/h3>\n<p>Bu Trigger, <code>SIPARIS_DETAY<\/code> tablosuna her yeni sat\u0131r eklendi\u011finde (yani bir \u00fcr\u00fcn sat\u0131ld\u0131\u011f\u0131nda) tetiklenecek. \u0130lgili \u00fcr\u00fcn\u00fcn stok miktar\u0131n\u0131 d\u00fc\u015f\u00fcrecek ve e\u011fer d\u00fc\u015fen stok kritik bir seviyenin alt\u0131ndaysa <code>YENIDEN_SIPARIS_LISTESI<\/code> tablosuna bir kay\u0131t ekleyecektir.<\/p>\n<pre><code>\nCREATE OR REPLACE TRIGGER trg_stok_guncelle_ve_uyari\nAFTER INSERT ON SIPARIS_DETAY\nFOR EACH ROW\nDECLARE\n    PRAGMA AUTONOMOUS_TRANSACTION; -- Trigger i\u00e7inde ba\u011f\u0131ms\u0131z i\u015flem ba\u015flatmak i\u00e7in\n    v_critical_stok_limit CONSTANT NUMBER := 5; -- Kritik stok e\u015fi\u011fi\n    v_current_stok NUMBER;\nBEGIN\n    -- \u00dcr\u00fcn\u00fcn stok miktar\u0131n\u0131 d\u00fc\u015f\u00fcr\n    UPDATE URUNLER\n    SET stok_miktari = stok_miktari - :NEW.miktar\n    WHERE urun_id = :NEW.urun_id\n    RETURNING stok_miktari INTO v_current_stok; -- G\u00fcncel stok miktar\u0131n\u0131 al\n\n    -- E\u011fer stok kritik seviyenin alt\u0131na d\u00fc\u015ft\u00fcyse veya \u00e7ok d\u00fc\u015f\u00fckse, yeniden sipari\u015f listesine ekle\n    IF v_current_stok <= v_critical_stok_limit THEN\n        -- E\u011fer bu \u00fcr\u00fcn zaten listede ve beklemedeyse tekrar ekleme\n        BEGIN\n            INSERT INTO YENIDEN_SIPARIS_LISTESI (urun_id, talep_edilen_miktar, durum)\n            VALUES (:NEW.urun_id, 10, 'Beklemede'); -- \u00d6rnek: Her seferinde 10 adet talep et\n            COMMIT; -- Autonomous Transaction'\u0131 commit et\n        EXCEPTION\n            WHEN DUP_VAL_ON_INDEX THEN\n                -- Zaten listede var, do nothing or update quantity if needed\n                NULL; \n            WHEN OTHERS THEN\n                -- Hata durumunda loglama veya bildirim\n                DBMS_OUTPUT.PUT_LINE('Yeniden sipari\u015f listesine eklerken hata: ' || SQLERRM);\n                ROLLBACK; -- Autonomous Transaction'\u0131 rollback et\n        END;\n    END IF;\n\n    -- Ana i\u015flem transaction'\u0131 devam ediyor, burada COMMIT\/ROLLBACK yapm\u0131yoruz\n    -- Autonomous transaction kendi ba\u015f\u0131na y\u00f6netilir.\nEND;\n\/\n<\/pre>\n<p><\/code><\/p>\n<p>Burada <code>PRAGMA AUTONOMOUS_TRANSACTION<\/code> kullan\u0131ld\u0131 \u00e7\u00fcnk\u00fc bir Trigger'\u0131n i\u00e7inde, ana DML i\u015flemiyle ayn\u0131 transaction i\u00e7inde bir <code>COMMIT<\/code> veya <code>ROLLBACK<\/code> yapamazs\u0131n\u0131z. Yeniden sipari\u015f listesine ekleme i\u015flemi ayr\u0131 bir transaction'da ger\u00e7ekle\u015fti\u011fi i\u00e7in bu pragmaya ihtiya\u00e7 duyulur. Bu, ana sipari\u015f i\u015flemi ba\u015far\u0131s\u0131z olsa bile loglaman\u0131n veya yeniden sipari\u015f kayd\u0131n\u0131n kal\u0131c\u0131 olmas\u0131n\u0131 sa\u011flar (veya tam tersi, ana i\u015flem ba\u015far\u0131l\u0131 olsa bile loglama ba\u015far\u0131s\u0131z olursa ana i\u015flemi etkilemez).<\/p>\n<h3>Ad\u0131m 2: D\u00fc\u015f\u00fck Stoklu \u00dcr\u00fcnleri \u0130\u015fleyen Cursor (Batch \u0130\u015flemi)<\/h3>\n<p>Bu Cursor, belirli aral\u0131klarla (\u00f6rne\u011fin, bir Oracle Scheduler i\u015fi ile her gece) \u00e7al\u0131\u015ft\u0131r\u0131larak, halihaz\u0131rda kritik seviyede olan ancak hen\u00fcz <code>YENIDEN_SIPARIS_LISTESI<\/code>'ne eklenmemi\u015f \u00fcr\u00fcnleri tespit edecek ve bu listeye ekleyecektir. Bu, Trigger'\u0131n ka\u00e7\u0131rm\u0131\u015f olabilece\u011fi veya sistemin genel bir stok kontrol\u00fc i\u00e7in ek bir g\u00fcvenlik katman\u0131 sa\u011flar.<\/p>\n<pre><code>\nDECLARE\n    CURSOR c_dusuk_stok_urunler IS\n        SELECT u.urun_id, u.urun_adi, u.stok_miktari\n        FROM URUNLER u\n        LEFT JOIN YENIDEN_SIPARIS_LISTESI ysl ON u.urun_id = ysl.urun_id AND ysl.durum = 'Beklemede'\n        WHERE u.stok_miktari <= 5 -- Kritik stok e\u015fi\u011fi\n          AND ysl.urun_id IS NULL; -- Hen\u00fcz yeniden sipari\u015f listesinde beklemede olmayanlar\n          \n    v_talep_miktar NUMBER := 10; -- Her \u00fcr\u00fcn i\u00e7in talep edilecek standart miktar\nBEGIN\n    DBMS_OUTPUT.PUT_LINE('D\u00fc\u015f\u00fck stoklu \u00fcr\u00fcnlerin kontrol\u00fc ba\u015flat\u0131ld\u0131.');\n    \n    FOR r_urun IN c_dusuk_stok_urunler LOOP\n        DBMS_OUTPUT.PUT_LINE('\u00dcr\u00fcn ID: ' || r_urun.urun_id || ', Ad\u0131: ' || r_urun.urun_adi || \n                             ', Stok: ' || r_urun.stok_miktari || ' - Yeniden sipari\u015f listesine ekleniyor.');\n        \n        INSERT INTO YENIDEN_SIPARIS_LISTESI (urun_id, talep_edilen_miktar, durum)\n        VALUES (r_urun.urun_id, v_talep_miktar, 'Beklemede');\n        \n    END LOOP;\n    \n    COMMIT; -- Cursor i\u015flemi sonunda de\u011fi\u015fiklikleri kaydet\n    DBMS_OUTPUT.PUT_LINE('D\u00fc\u015f\u00fck stoklu \u00fcr\u00fcnlerin kontrol\u00fc tamamland\u0131.');\n\nEXCEPTION\n    WHEN OTHERS THEN\n        DBMS_OUTPUT.PUT_LINE('Batch i\u015fleminde hata olu\u015ftu: ' || SQLERRM);\n        ROLLBACK;\nEND;\n\/\n<\/pre>\n<p><\/code><\/p>\n<h3>Senaryo Testi:<\/h3>\n<p>Mevcut <code>URUNLER<\/code> ve <code>SIPARIS_DETAY<\/code> tablolar\u0131m\u0131zla test edelim:<\/p>\n<pre><code>\n-- Urun ID 1 (Diz\u00fcst\u00fc Bilgisayar) - Stok: 15\n-- Urun ID 5 (4K Monit\u00f6r) - Stok: 4 (Zaten d\u00fc\u015f\u00fck)\n-- Urun ID 6 (Kamera) - Stok: 2 (Zaten d\u00fc\u015f\u00fck)\n\n-- 1. Sat\u0131\u015f yap (Urun ID 1, miktar 10)\nINSERT INTO SIPARIS_DETAY (siparis_detay_id, siparis_id, urun_id, miktar) VALUES (10, 1000, 1, 10);\n-- Trigger tetiklenir: URUNLER.stok_miktari -> 5.\n-- Stok kritik seviye (5) oldu\u011fu i\u00e7in YENIDEN_SIPARIS_LISTESI'ne 1 numaral\u0131 \u00fcr\u00fcn eklenir.\n\n-- Kontrol:\nSELECT * FROM URUNLER WHERE urun_id = 1; -- Stok 5 olmal\u0131\nSELECT * FROM YENIDEN_SIPARIS_LISTESI WHERE urun_id = 1; -- Kay\u0131t olmal\u0131\n\n-- 2. Sat\u0131\u015f yap (Urun ID 1, miktar 1)\nINSERT INTO SIPARIS_DETAY (siparis_detay_id, siparis_id, urun_id, miktar) VALUES (11, 1001, 1, 1);\n-- Trigger tetiklenir: URUNLER.stok_miktari -> 4.\n-- YENIDEN_SIPARIS_LISTESI'ne zaten eklenmi\u015f oldu\u011fu i\u00e7in DUP_VAL_ON_INDEX hatas\u0131 al\u0131p NULL olarak ge\u00e7i\u015ftirir.\n\n-- Kontrol:\nSELECT * FROM URUNLER WHERE urun_id = 1; -- Stok 4 olmal\u0131\nSELECT * FROM YENIDEN_SIPARIS_LISTESI WHERE urun_id = 1; -- Hala tek kay\u0131t olmal\u0131\n\n-- 3. Cursor batch i\u015fini \u00e7al\u0131\u015ft\u0131r\n-- Yukar\u0131daki DECLARE \/ BEGIN \/ END blo\u011funu \u00e7al\u0131\u015ft\u0131r\u0131n.\n-- Urun ID 5 (stok 4) ve Urun ID 6 (stok 2) zaten d\u00fc\u015f\u00fck oldu\u011fu ve YENIDEN_SIPARIS_LISTESI'nde hen\u00fcz olmad\u0131\u011f\u0131 i\u00e7in,\n-- bu \u00fcr\u00fcnler listeye eklenecektir.\n\n-- Kontrol:\nSELECT * FROM YENIDEN_SIPARIS_LISTESI; -- 1, 5 ve 6 numaral\u0131 \u00fcr\u00fcnler listede olmal\u0131.\n\nCOMMIT;\n<\/pre>\n<p><\/code><\/p>\n<p>Bu senaryo, Cursor ve Trigger'lar\u0131n birle\u015fik g\u00fcc\u00fcn\u00fc g\u00f6sterir. Trigger, anl\u0131k olaylara tepki vererek stok g\u00fcncellemelerini ve acil durum uyar\u0131lar\u0131n\u0131 yaparken, Cursor daha b\u00fcy\u00fck \u00f6l\u00e7ekli ve periyodik stok kontrolleri i\u00e7in kullan\u0131l\u0131r. Bu entegrasyon, bir veritaban\u0131n\u0131n sadece veri depolamakla kalmay\u0131p, ayn\u0131 zamanda karma\u015f\u0131k i\u015f mant\u0131\u011f\u0131n\u0131 ve otomasyonu etkin bir \u015fekilde y\u00f6netebilece\u011fini kan\u0131tlar.<\/p>\n<h2>Sonu\u00e7: Oracle Veritaban\u0131 Y\u00f6netiminde G\u00fc\u00e7l\u00fc Ara\u00e7lar<\/h2>\n<p>Oracle veritabanlar\u0131nda Cursor'lar ve Trigger'lar, veri \u00fczerinde derinlemesine kontrol sa\u011flayan ve i\u015f s\u00fcre\u00e7lerini otomatikle\u015ftiren iki temel PL\/SQL mekanizmas\u0131d\u0131r. Bu makale boyunca, bu g\u00fc\u00e7l\u00fc ara\u00e7lar\u0131n ne olduklar\u0131n\u0131, nas\u0131l \u00e7al\u0131\u015ft\u0131klar\u0131n\u0131 ve ger\u00e7ek d\u00fcnya senaryolar\u0131nda nas\u0131l etkin bir \u015fekilde kullan\u0131labileceklerini detayl\u0131ca inceledik. Cursor'lar, \u00f6zellikle bir sorgu taraf\u0131ndan d\u00f6nd\u00fcr\u00fclen veri k\u00fcmesini sat\u0131r sat\u0131r i\u015fleme ihtiyac\u0131 duydu\u011fumuzda bize programatik bir kontrol imkan\u0131 sunar. B\u00f6ylece, her bir veri sat\u0131r\u0131 \u00fczerinde karma\u015f\u0131k hesaplamalar, ko\u015fullu g\u00fcncellemeler veya \u00f6zel veri aktar\u0131m i\u015flemleri ger\u00e7ekle\u015ftirebiliriz. Di\u011fer yandan, Trigger'lar, veritaban\u0131nda belirli bir olay\u0131n (INSERT, UPDATE, DELETE gibi DML i\u015flemleri veya DDL\/Sistem olaylar\u0131) meydana gelmesi durumunda otomatik olarak tetiklenen kod bloklar\u0131d\u0131r. Bu otomasyon yetene\u011fi, veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc korumak, denetim kay\u0131tlar\u0131 olu\u015fturmak, i\u015f kurallar\u0131n\u0131 veritaban\u0131 seviyesinde zorlamak ve \u00e7apraz tablo g\u00fcncellemeleri gibi kritik g\u00f6revleri verimli bir \u015fekilde yerine getirmemizi sa\u011flar. Her iki arac\u0131n da do\u011fru ve bilin\u00e7li kullan\u0131m\u0131, veritaban\u0131 uygulamalar\u0131n\u0131n performans\u0131n\u0131, g\u00fcvenilirli\u011fini ve s\u00fcrd\u00fcr\u00fclebilirli\u011fini \u00f6nemli \u00f6l\u00e7\u00fcde art\u0131r\u0131r.<\/p>\n<p>Ancak, bu ara\u00e7lar\u0131n her zaman en iyi \u00e7\u00f6z\u00fcm olmad\u0131\u011f\u0131n\u0131 ve yanl\u0131\u015f kullan\u0131ld\u0131\u011f\u0131nda performans d\u00fc\u015f\u00fc\u015flerine veya beklenmeyen yan etkilere yol a\u00e7abilece\u011fini de unutmamak gerekir. Cursor'lar i\u00e7in m\u00fcmk\u00fcn oldu\u011funca set tabanl\u0131 SQL i\u015flemlerini tercih etmek, Trigger'lar i\u00e7in ise sadece ger\u00e7ekten ihtiya\u00e7 duyuldu\u011funda ve m\u00fcmk\u00fcn oldu\u011funca basit tutmak, iyi bir uygulama geli\u015ftirme prati\u011fidir. \u00d6zellikle b\u00fcy\u00fck veri k\u00fcmeleriyle \u00e7al\u0131\u015f\u0131rken, <code>BULK COLLECT<\/code> ve <code>FORALL<\/code> gibi ileri d\u00fczey PL\/SQL \u00f6zellikleri, Cursor'lar\u0131n performans maliyetini d\u00fc\u015f\u00fcrmeye yard\u0131mc\u0131 olabilir. Trigger'larda ise ko\u015fullu mant\u0131k ve otonom transaction'lar gibi yap\u0131lar, karma\u015f\u0131k senaryolar\u0131n \u00fcstesinden gelmek i\u00e7in esneklik sunar. K\u0131sacas\u0131, Oracle Cursor'lar\u0131 ve Trigger'lar\u0131, veritaban\u0131 y\u00f6neticileri ve PL\/SQL geli\u015ftiricileri i\u00e7in vazge\u00e7ilmez beceriler sunar. Bu ara\u00e7lara hakim olmak, sadece daha sa\u011flam ve verimli veritaban\u0131 \u00e7\u00f6z\u00fcmleri olu\u015fturman\u0131za yard\u0131mc\u0131 olmakla kalmayacak, ayn\u0131 zamanda Oracle ekosistemindeki yetkinli\u011finizi de \u00f6nemli \u00f6l\u00e7\u00fcde art\u0131racakt\u0131r. Unutmay\u0131n, her ara\u00e7 gibi, Cursor ve Trigger'lar\u0131n da ne zaman ve nas\u0131l kullan\u0131laca\u011f\u0131n\u0131 bilmek, onlar\u0131 etkin bir \u015fekilde kullanman\u0131n anahtar\u0131d\u0131r.<\/p>\n<h3>S\u0131k\u00e7a Sorulan Sorular (SSS)<\/h3>\n<div class=\"faq-item\">\n<p class=\"faq-question\">1. Cursor'lar veritaban\u0131 performans\u0131n\u0131 d\u00fc\u015f\u00fcr\u00fcr m\u00fc?<\/p>\n<div class=\"faq-answer\">\n<p>Evet, genellikle d\u00fc\u015f\u00fcr\u00fcr. Cursor'lar her sat\u0131r i\u00e7in Oracle ile PL\/SQL aras\u0131nda ba\u011flam de\u011fi\u015ftirme (context switching) maliyeti getirir. Bu, set tabanl\u0131 SQL i\u015flemlerine (\u00f6rne\u011fin tek bir <code>UPDATE<\/code> veya <code>INSERT INTO ... SELECT<\/code> sorgusu) k\u0131yasla daha yava\u015f olabilir. M\u00fcmk\u00fcn oldu\u011funda set tabanl\u0131 i\u015flemleri tercih etmek, performans a\u00e7\u0131s\u0131ndan daha verimli bir yakla\u015f\u0131md\u0131r. Ancak, karma\u015f\u0131k sat\u0131r baz\u0131nda i\u015f mant\u0131\u011f\u0131 gerektiren durumlarda veya <code>BULK COLLECT<\/code> ve <code>FORALL<\/code> gibi tekniklerle kullan\u0131ld\u0131\u011f\u0131nda Cursor'lar optimize edilebilir.<\/p>\n<\/p><\/div>\n<\/div>\n<div class=\"faq-item\">\n<p class=\"faq-question\">2. Trigger'lar ne zaman kullan\u0131lmamal\u0131d\u0131r?<\/p>\n<div class=\"faq-answer\">\n<p>Trigger'lar, a\u015f\u0131r\u0131 kullan\u0131ld\u0131\u011f\u0131nda veya k\u00f6t\u00fc tasar\u0131mland\u0131\u011f\u0131nda sorunlara yol a\u00e7abilir. Trigger'lar\u0131 kullanmaman\u0131z gereken baz\u0131 durumlar \u015funlard\u0131r:<\/p>\n<ul>\n<li><strong>Basit Veri Do\u011frulama:<\/strong> Bir s\u00fctunun bo\u015f olmamas\u0131 veya belirli bir aral\u0131kta olmas\u0131 gibi basit k\u0131s\u0131tlamalar i\u00e7in <code>NOT NULL<\/code>, <code>CHECK<\/code> k\u0131s\u0131tlamalar\u0131 veya <code>FOREIGN KEY<\/code> gibi bildirimsel b\u00fct\u00fcnl\u00fck k\u0131s\u0131tlamalar\u0131n\u0131 tercih edin.<\/li>\n<li><strong>Uygulama Katman\u0131 Mant\u0131\u011f\u0131:<\/strong> \u0130\u015f mant\u0131\u011f\u0131n\u0131n \u00e7o\u011funu uygulama katman\u0131nda y\u00f6netmek genellikle daha \u015feffaf ve hata ay\u0131klamas\u0131 daha kolayd\u0131r. Trigger'lar sadece veritaban\u0131 seviyesinde zorlanmas\u0131 gereken kurallar i\u00e7in kullan\u0131lmal\u0131d\u0131r.<\/li>\n<li><strong>Performans Kritik \u0130\u015flemler:<\/strong> \u00c7ok yo\u011fun DML i\u015flemlerinin oldu\u011fu tablolarda karma\u015f\u0131k Trigger'lar, her i\u015flemde ek maliyet yaratarak performans\u0131 ciddi \u015fekilde d\u00fc\u015f\u00fcrebilir.<\/li>\n<li><strong>Zincirleme Trigger'lar:<\/strong> Bir Trigger'\u0131n ba\u015fka bir Trigger'\u0131 tetikledi\u011fi ve bu durumun kontrol edilemez bir zincir olu\u015fturdu\u011fu senaryolardan ka\u00e7\u0131n\u0131lmal\u0131d\u0131r, bu durum hata ay\u0131klamay\u0131 zorla\u015ft\u0131r\u0131r ve beklenmeyen davran\u0131\u015flara neden olabilir.<\/li>\n<\/ul><\/div>\n<\/div>\n<div class=\"faq-item\">\n<p class=\"faq-question\">3. Implicit (\u00f6rt\u00fck) ve Explicit (a\u00e7\u0131k) Cursor aras\u0131ndaki fark nedir?<\/p>\n<div class=\"faq-answer\">\n<p>\u0130ki t\u00fcr Cursor vard\u0131r:<\/p>\n<ul>\n<li><strong>Implicit Cursor:<\/strong> Oracle, her SQL sorgusu (<code>SELECT<\/code>, <code>INSERT<\/code>, <code>UPDATE<\/code>, <code>DELETE<\/code>) i\u00e7in dahili olarak bir Cursor olu\u015fturur ve y\u00f6netir. Buna \u00f6rt\u00fck Cursor denir. \u00d6rne\u011fin, bir <code>SELECT INTO<\/code> ifadesi kullan\u0131ld\u0131\u011f\u0131nda Oracle arka planda bir \u00f6rt\u00fck Cursor kullan\u0131r. Geli\u015ftiricinin bu Cursor \u00fczerinde do\u011frudan bir kontrol\u00fc yoktur ancak <code>SQL%ROWCOUNT<\/code> veya <code>SQL%NOTFOUND<\/code> gibi niteliklerle sonu\u00e7lar\u0131 kontrol edebilir.<\/li>\n<li><strong>Explicit Cursor:<\/strong> Geli\u015ftiricinin kendi PL\/SQL kodunda <code>CURSOR ... IS SELECT ...<\/code> yap\u0131s\u0131yla a\u00e7\u0131k\u00e7a tan\u0131mlad\u0131\u011f\u0131 ve <code>OPEN<\/code>, <code>FETCH<\/code>, <code>CLOSE<\/code> gibi komutlarla manuel olarak y\u00f6netti\u011fi Cursor'lard\u0131r. Explicit Cursor'lar, birden fazla sat\u0131r d\u00f6nd\u00fcren sorgular\u0131n sonu\u00e7 k\u00fcmesi \u00fczerinde sat\u0131r baz\u0131nda daha detayl\u0131 kontrol ve i\u015flem yapmak gerekti\u011finde kullan\u0131l\u0131r.<\/li>\n<\/ul><\/div>\n<\/div>\n<div class=\"faq-item\">\n<p class=\"faq-question\">4. Bir Trigger i\u00e7inde neden <code>PRAGMA AUTONOMOUS_TRANSACTION<\/code> kullan\u0131r\u0131z?<\/p>\n<div class=\"faq-answer\">\n<p>Bir Trigger, tetiklendi\u011fi ana DML i\u015flemiyle ayn\u0131 i\u015flem (transaction) i\u00e7inde \u00e7al\u0131\u015f\u0131r. Bu, Trigger i\u00e7inde yap\u0131lan herhangi bir <code>COMMIT<\/code> veya <code>ROLLBACK<\/code> i\u015fleminin ana i\u015flemi de etkileyece\u011fi anlam\u0131na gelir ki bu genellikle istenmeyen bir durumdur. <code>PRAGMA AUTONOMOUS_TRANSACTION<\/code> kullan\u0131ld\u0131\u011f\u0131nda, Trigger i\u00e7indeki kod ayr\u0131, ba\u011f\u0131ms\u0131z bir i\u015flem olarak \u00e7al\u0131\u015f\u0131r. Bu sayede, Trigger kendi i\u00e7inde <code>COMMIT<\/code> veya <code>ROLLBACK<\/code> yapabilir ve bu, ana DML i\u015flemini etkilemez. Bu \u00f6zellik genellikle denetim (auditing) kay\u0131tlar\u0131 gibi, ana i\u015flem ba\u015far\u0131l\u0131 olsa da olmasa da kal\u0131c\u0131 olmas\u0131 istenen i\u015flemler i\u00e7in kullan\u0131l\u0131r.<\/p>\n<\/p><\/div>\n<\/div>\n<div class=\"faq-item\">\n<p class=\"faq-question\">5. Trigger'larda <code>:NEW<\/code> ve <code>:OLD<\/code> ne i\u015fe yarar?<\/p>\n<div class=\"faq-answer\">\n<p><code>:NEW<\/code> ve <code>:OLD<\/code>, sat\u0131r baz\u0131nda (<code>FOR EACH ROW<\/code>) tetiklenen Trigger'larda kullan\u0131lan s\u00f6zde (pseudo) kay\u0131tlard\u0131r:<\/p>\n<ul>\n<li><strong><code>:NEW<\/code>:<\/strong> <code>INSERT<\/code> veya <code>UPDATE<\/code> i\u015fleminden sonraki sat\u0131r\u0131n yeni de\u011ferlerini temsil eder. Bir <code>INSERT<\/code> Trigger'\u0131nda eklenen sat\u0131r\u0131n de\u011ferlerini, bir <code>UPDATE<\/code> Trigger'\u0131nda ise g\u00fcncellenmi\u015f de\u011ferleri i\u00e7erir. <code>BEFORE INSERT\/UPDATE<\/code> Trigger'lar\u0131nda bu de\u011ferler de\u011fi\u015ftirilebilir.<\/li>\n<li><strong><code>:OLD<\/code>:<\/strong> <code>UPDATE<\/code> veya <code>DELETE<\/code> i\u015fleminden \u00f6nceki sat\u0131r\u0131n eski de\u011ferlerini temsil eder. Bir <code>UPDATE<\/code> Trigger'\u0131nda s\u00fctunlar\u0131n g\u00fcncellenmeden \u00f6nceki de\u011ferlerini, bir <code>DELETE<\/code> Trigger'\u0131nda ise silinen sat\u0131r\u0131n de\u011ferlerini i\u00e7erir. <code>:OLD<\/code> de\u011ferleri Trigger i\u00e7inde de\u011fi\u015ftirilemez.<\/li>\n<\/ul>\n<p>Bu s\u00f6zde kay\u0131tlar, Trigger'lar\u0131n veri de\u011fi\u015fikliklerini analiz etmesi ve buna g\u00f6re aksiyon almas\u0131 i\u00e7in hayati \u00f6neme sahiptir.<\/p>\n<\/p><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"Oracle veritabanlar\u0131nda veri manip\u00fclasyonu ve otomasyon s\u00fcre\u00e7lerini bir \u00fcst seviyeye ta\u015f\u0131mak m\u0131 istiyorsunuz? Bu makale, Cursor ve Trigger&hellip;","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1505],"tags":[],"class_list":{"0":"post-31250","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-sql-2","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Mastering SQL: Oracle&#039;da Cursor ve Trigger&#039;lar ile Pratik Veritaban\u0131 Y\u00f6netimi<\/title>\n<meta name=\"description\" content=\"Oracle veritabanlar\u0131nda veri manip\u00fclasyonu ve otomasyon s\u00fcre\u00e7lerini bir \u00fcst seviyeye ta\u015f\u0131mak m\u0131 istiyorsunuz? Bu makale, Cursor ve Trigger gibi g\u00fc\u00e7l\u00fc PL\/SQL ara\u00e7lar\u0131n\u0131 kullanarak veritaban\u0131 y\u00f6netimini nas\u0131l daha etkin hale getirece\u011finizi ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Mastering SQL: Oracle&#039;da Cursor ve Trigger&#039;lar ile Pratik Veritaban\u0131 Y\u00f6netimi\" \/>\n<meta property=\"og:description\" content=\"Oracle veritabanlar\u0131nda veri manip\u00fclasyonu ve otomasyon s\u00fcre\u00e7lerini bir \u00fcst seviyeye ta\u015f\u0131mak m\u0131 istiyorsunuz? Bu makale, Cursor ve Trigger gibi g\u00fc\u00e7l\u00fc PL\/SQL ara\u00e7lar\u0131n\u0131 kullanarak veritaban\u0131 y\u00f6netimini nas\u0131l daha etkin hale getirece\u011finizi ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-10-07T17:32:11+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"33 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Mastering SQL: Oracle&#8217;da Cursor ve Trigger&#8217;lar ile Pratik Veritaban\u0131 Y\u00f6netimi\",\"datePublished\":\"2025-10-07T17:32:11+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/\"},\"wordCount\":5245,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"SQL\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/\",\"name\":\"Mastering SQL: Oracle'da Cursor ve Trigger'lar ile Pratik Veritaban\u0131 Y\u00f6netimi\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-10-07T17:32:11+00:00\",\"description\":\"Oracle veritabanlar\u0131nda veri manip\u00fclasyonu ve otomasyon s\u00fcre\u00e7lerini bir \u00fcst seviyeye ta\u015f\u0131mak m\u0131 istiyorsunuz? Bu makale, Cursor ve Trigger gibi g\u00fc\u00e7l\u00fc PL\/SQL ara\u00e7lar\u0131n\u0131 kullanarak veritaban\u0131 y\u00f6netimini nas\u0131l daha etkin hale getirece\u011finizi ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Mastering SQL: Oracle&#8217;da Cursor ve Trigger&#8217;lar ile Pratik Veritaban\u0131 Y\u00f6netimi\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Mastering SQL: Oracle'da Cursor ve Trigger'lar ile Pratik Veritaban\u0131 Y\u00f6netimi","description":"Oracle veritabanlar\u0131nda veri manip\u00fclasyonu ve otomasyon s\u00fcre\u00e7lerini bir \u00fcst seviyeye ta\u015f\u0131mak m\u0131 istiyorsunuz? Bu makale, Cursor ve Trigger gibi g\u00fc\u00e7l\u00fc PL\/SQL ara\u00e7lar\u0131n\u0131 kullanarak veritaban\u0131 y\u00f6netimini nas\u0131l daha etkin hale getirece\u011finizi ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/","og_locale":"tr_TR","og_type":"article","og_title":"Mastering SQL: Oracle'da Cursor ve Trigger'lar ile Pratik Veritaban\u0131 Y\u00f6netimi","og_description":"Oracle veritabanlar\u0131nda veri manip\u00fclasyonu ve otomasyon s\u00fcre\u00e7lerini bir \u00fcst seviyeye ta\u015f\u0131mak m\u0131 istiyorsunuz? Bu makale, Cursor ve Trigger gibi g\u00fc\u00e7l\u00fc PL\/SQL ara\u00e7lar\u0131n\u0131 kullanarak veritaban\u0131 y\u00f6netimini nas\u0131l daha etkin hale getirece\u011finizi ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.","og_url":"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-10-07T17:32:11+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"33 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Mastering SQL: Oracle&#8217;da Cursor ve Trigger&#8217;lar ile Pratik Veritaban\u0131 Y\u00f6netimi","datePublished":"2025-10-07T17:32:11+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/"},"wordCount":5245,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["SQL"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/","url":"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/","name":"Mastering SQL: Oracle'da Cursor ve Trigger'lar ile Pratik Veritaban\u0131 Y\u00f6netimi","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-10-07T17:32:11+00:00","description":"Oracle veritabanlar\u0131nda veri manip\u00fclasyonu ve otomasyon s\u00fcre\u00e7lerini bir \u00fcst seviyeye ta\u015f\u0131mak m\u0131 istiyorsunuz? Bu makale, Cursor ve Trigger gibi g\u00fc\u00e7l\u00fc PL\/SQL ara\u00e7lar\u0131n\u0131 kullanarak veritaban\u0131 y\u00f6netimini nas\u0131l daha etkin hale getirece\u011finizi ad\u0131m ad\u0131m a\u00e7\u0131kl\u0131yor.","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/mastering-sql-oracleda-cursor-ve-triggerlar-ile-pratik-veritabani-yonetimi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Mastering SQL: Oracle&#8217;da Cursor ve Trigger&#8217;lar ile Pratik Veritaban\u0131 Y\u00f6netimi"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/31250","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=31250"}],"version-history":[{"count":0,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/31250\/revisions"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=31250"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=31250"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=31250"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}