← Database Management System Ana Sayfa
SQL Kapsamlı Konu Anlatımı
📘 SQL Lab Notları

SQL Konu Anlatımı

Oracle SQL tabanlı kapsamlı ders notları. Temel SELECT sorgularından trigger'lara kadar tüm konular örneklerle detaylıca açıklanmıştır.

13 Ana Konu
13 Örnek Egzersiz
50+ SQL Örneği
📋

Kullanılan Tablolar

Bu anlatımda kullanılan örnek veri yapısı

Tüm örnekler klasik Oracle örnek veritabanı olan EMP, DEPT ve SALGRADE tablolarını kullanmaktadır.

EMP Tablosu — Çalışan Bilgileri

Sütun Tür Açıklama
EMPNO NUMBER(4) Çalışan numarası (Primary Key)
ENAME VARCHAR2(10) Çalışan adı
JOB VARCHAR2(9) Meslek (PRESIDENT, MANAGER, ANALYST, SALESMAN, CLERK)
MGR NUMBER(4) Yöneticinin EMPNO'su
HIREDATE DATE İşe başlama tarihi
SAL NUMBER(7,2) Maaş
COMM NUMBER(7,2) Komisyon (bazıları NULL)
DEPTNO NUMBER(2) Bölüm numarası (Foreign Key)
📊 EMP Tablo Verilerini Göster
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7839 KING PRESIDENT 17-NOV-81 5000 10
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7566 JONES MANAGER 7839 02-APR-81 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30
7900 JAMES CLERK 7698 03-DEC-81 950 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7902 FORD ANALYST 7566 03-DEC-81 3000 20
7369 SMITH CLERK 7902 17-DEC-80 800 20
7788 SCOTT ANALYST 7566 09-DEC-82 3000 20
7876 ADAMS CLERK 7788 12-JAN-83 1100 20
7934 MILLER CLERK 7782 23-JAN-82 1300 10

DEPT Tablosu — Bölüm Bilgileri

Sütun Açıklama
DEPTNO Bölüm numarası (10, 20, 30, 40)
DNAME Bölüm adı (ACCOUNTING, RESEARCH, SALES, OPERATIONS)
LOC Şehir (NEW YORK, DALLAS, CHICAGO, BOSTON)
📊 DEPT Tablo Verilerini Göster
DEPTNO DNAME LOC
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

SALGRADE Tablosu — Maaş Dereceleri

GRADE LOSAL (Alt Sınır) HISAL (Üst Sınır)
1 700 1200
2 1201 1400
3 1401 2000
4 2001 3000
5 3001 9999
📊 SALGRADE Tablo Verilerini Göster
GRADE LOSAL HISAL
1 700 1200
2 1201 1400
3 1401 2000
4 2001 3000
5 3001 9999
01

Temel SQL SELECT Deyimleri

Writing Basic SQL Statements

SELECT Deyiminin Kapasiteleri

SQL SELECT deyimi üç temel işlem gerçekleştirir:

  • Selection (Seçim): Bir tablodan sadece istenen satırları getirir. WHERE koşulu ile filtreleme yapılır.
  • Projection (Projeksiyon): Tablodaki tüm sütunlar yerine yalnızca belirli sütunları seçer.
  • Join (Birleştirme): İki veya daha fazla tablodan verileri birleştirir.

Temel SELECT Sözdizimi

SQL Sözdizimi
SELECT   [DISTINCT] {*, column [alias], ...}
FROM     table;
  • SELECT: Hangi sütunları getireceğini belirtir.
  • FROM: Hangi tablodan getireceğini belirtir.
  • * (asterisk): Tüm sütunları seçmek için kullanılır.

Tüm Sütunları Seçmek — SELECT *

Bir tablodaki tüm sütun ve satırları görmek için * kullanılır.

SQL
SELECT *
FROM   dept;
DEPTNO DNAME LOC ------ -------------- ------------- 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON

Belirli Sütunları Seçmek

Sadece istediğimiz sütunları virgülle ayırarak belirtiriz.

SQL
SELECT deptno, loc
FROM   dept;

Aritmetik Operatörler

SQL'de sayısal sütunlar üzerinde aritmetik işlemler yapılabilir: +, -, *, /

SQL
-- Maaşa 300 ekle
SELECT ename, sal, sal+300
FROM   emp;

Operatör Önceliği

Matematikteki öncelik kuralları geçerlidir: Çarpma ve bölme, toplama ve çıkarmadan önce yapılır.

Parantez Yok
SELECT 12*sal+100
FROM   emp;
-- KING: 12*5000+100 = 60100
Parantez ile
SELECT 12*(sal+100)
FROM   emp;
-- KING: 12*(5000+100) = 61200

NULL Değerleri

NULL, kullanılamaz, atanmamış, bilinmeyen veya uygulanamaz bir değeri temsil eder. Boş string veya 0 ile aynı değildir.

⚠️
Kritik Kural: NULL İçeren Aritmetik

NULL değer içeren herhangi bir aritmetik ifadenin sonucu her zaman NULL'dur. Örneğin: 12 * SAL + COMM — COMM sütunu NULL ise sonuç da NULL olur.

SQL
SELECT ename, 12*sal+comm
FROM   emp
WHERE  ename='KING';
-- KING'in COMM değeri NULL olduğundan sonuç NULL döner

Sütun Takma Adları (Column Aliases)

Sorgu sonucunda sütunlara daha okunabilir isimler vermek için alias kullanılır.

SQL
-- AS anahtar kelimesiyle veya doğrudan boşlukla
SELECT ename AS name, sal salary
FROM   emp;

-- Boşluk içeren alias için çift tırnak kullanılır
SELECT ename "Name",
       sal*12 "Annual Salary"
FROM   emp;
💡
Alias Kuralları

Alias büyük/küçük harf duyarsızdır. Ancak boşluk, özel karakter veya büyük/küçük harf hassasiyeti istenirse çift tırnak ("...") kullanılmalıdır. Tek tırnak ('...') string değerler içindir, alias için değil.

Tekrarlayan Satırları Kaldırmak — DISTINCT

Varsayılan olarak tüm satırlar (tekrarlar dahil) gösterilir. DISTINCT anahtar kelimesi tekrarlayan satırları kaldırır.

Tekrarlı
SELECT deptno
FROM   emp;
-- 10, 30, 10, 20 ... 14 satır
Tekrarsız
SELECT DISTINCT deptno
FROM   emp;
-- 10, 20, 30 — sadece 3 satır
✏️ Egzersiz 1 — Çalışan Adı ve Maaşı

Tüm çalışanların adını ve maaşını görüntüleyin.

✅ Çözüm 1
SQL
SELECT ENAME, SAL
FROM   EMP;
✏️ Egzersiz 2 — Tekrarsız Meslek Listesi

EMP tablosundan tekrarlayan meslekler olmaksızın tüm meslekleri listeleyin.

✅ Çözüm 2
SQL
SELECT DISTINCT JOB
FROM   EMP;
02

Veriyi Kısıtlama ve Sıralama

Restricting and Sorting Data

WHERE Cümlesi ile Satır Filtreleme

WHERE cümlesi, döndürülen satırları koşula göre sınırlandırır. FROM cümlesinden sonra gelir.

Sözdizimi
SELECT [DISTINCT] {* | column [alias], ...}
FROM   table
[WHERE condition(s)];
SQL — Meslek Filtresi
SELECT ename, job, deptno
FROM   emp
WHERE  job='CLERK';
ℹ️
Karakter ve Tarih Değerleri

Karakter stringleri ve tarih değerleri tek tırnak içine alınır ('CLERK'). Karakter değerleri büyük/küçük harf duyarlıdır. Tarih değerleri format duyarlıdır. Varsayılan tarih formatı DD-MON-YY'dir. (Örnek: 17-NOV-81)

Karşılaştırma Operatörleri

Operatör Anlamı Örnek
= Eşittir job = 'CLERK'
> Büyüktür sal > 2000
>= Büyük eşittir sal >= 1000
< Küçüktür sal < 3000
<= Küçük eşittir sal <= comm
<> veya != Eşit değildir deptno <> 20

Diğer Karşılaştırma Operatörleri

BETWEEN ... AND ... — Aralık Operatörü

İki değer arasındaki satırları getirir. Alt ve üst sınırlar dahildir (inclusive).

SQL
SELECT ename, sal
FROM   emp
WHERE  sal BETWEEN 1000 AND 1500;
-- 1000 ve 1500 dahil tüm maaşları getirir
-- MARTIN(1250), TURNER(1500), WARD(1250), ADAMS(1100), MILLER(1300)

IN(list) — Liste Operatörü

Belirtilen listedeki herhangi bir değerle eşleşen satırları getirir.

SQL
SELECT empno, ename, sal, mgr
FROM   emp
WHERE  mgr IN (7902, 7566, 7788);
-- Yöneticisi 7902, 7566 veya 7788 olan çalışanlar

LIKE — Desen Eşleştirme Operatörü

Wildcard karakterlerle metin deseni arama yapar:

  • % (yüzde): Sıfır veya daha fazla karakteri temsil eder.
  • _ (alt çizgi): Tam olarak bir karakteri temsil eder.
SQL
-- 'S' harfiyle başlayan isimler
SELECT ename FROM emp
WHERE  ename LIKE 'S%';
-- SMITH, SCOTT

-- İkinci harfi 'A' olan isimler (herhangi biriyle başlar)
SELECT ename FROM emp
WHERE  ename LIKE '_A%';
-- MARTIN, JAMES, WARD

IS NULL — Null Kontrol Operatörü

NULL değer kontrolü için = kullanılamaz; IS NULL veya IS NOT NULL kullanılır.

SQL
-- Yöneticisi olmayan çalışanlar (KING)
SELECT ename, mgr
FROM   emp
WHERE  mgr IS NULL;

Mantıksal Operatörler (AND, OR, NOT)

Operatör Açıklama
AND Her iki koşul da TRUE olmalıdır
OR Koşullardan en az biri TRUE olmalıdır
NOT Koşulun olumsuzunu alır (FALSE ise TRUE döner)
AND Operatörü
-- Hem maaşı 1100+ hem mesleği CLERK olanlar
SELECT empno, ename, job, sal
FROM   emp
WHERE  sal>=1100
AND    job='CLERK';
-- ADAMS(1100), MILLER(1300)
NOT Operatörü
-- Mesleği CLERK, MANAGER veya ANALYST OLMAYAN çalışanlar
SELECT ename, job
FROM   emp
WHERE  job NOT IN ('CLERK', 'MANAGER', 'ANALYST');
-- NOT BETWEEN, NOT LIKE, NOT NULL ile de kullanılabilir

ORDER BY Cümlesi ile Sıralama

Sonuçların sırası belirsizdir. ORDER BY ile sıralama yapılır.

  • ASC: Artan sıralama (varsayılan, yazılmak zorunda değil)
  • DESC: Azalan sıralama
SQL
-- İşe alım tarihine göre artan sıralama
SELECT ename, job, deptno, hiredate
FROM   emp
ORDER BY hiredate;

-- Azalan tarih sıralaması
SELECT ename, hiredate
FROM   emp
ORDER BY hiredate DESC;

-- Alias ile sıralama
SELECT empno, ename, sal*12 annsal
FROM   emp
ORDER BY annsal;

-- Çoklu sütunla sıralama (önce deptno, sonra sal azalan)
SELECT ename, deptno, sal
FROM   emp
ORDER BY deptno, sal DESC;
💡
İpucu

ORDER BY ile SELECT listesinde olmayan sütunlara göre de sıralama yapılabilir. Çoklu sıralamada önce yazılan sütun birincil, sonraki sütunlar ikincil sıralama kriteridir.

✏️ Egzersiz 3 — Maaş Filtresi

Maaşı 1000'den fazla olan ve departman numarası 10 veya 20'de çalışan çalışanların adını ve maaşını 'Name' ve 'Monthly Salary' sütun adlarıyla listeleyin.

✅ Çözüm 3
SQL
SELECT ENAME "NAME", SAL "MONTHLY SALARY"
FROM   EMP
WHERE  SAL > 1000
AND    DEPTNO IN(10, 20);
✏️ Egzersiz 4 — Alfabetik Sıralama

Meslekleri PRESIDENT veya MANAGER olan çalışanların adlarını ve departman numaralarını isme göre alfabetik sıralayarak listeleyin.

✅ Çözüm 4
SQL
SELECT ename, deptno
FROM   emp
WHERE  job IN ('PRESIDENT', 'MANAGER')
ORDER BY ename;
✏️ Egzersiz 5 — NOT IN Kullanımı

Maaşı 1000, 3000 veya 5000 olmayan tüm çalışanların adını, mesleğini ve maaşını görüntüleyin.

✅ Çözüm 5
SQL
SELECT ename, job, sal
FROM   emp
WHERE  sal NOT IN (1000, 3000, 5000);
03

Tek Satır Fonksiyonları

Single-Row Functions

Tek satır fonksiyonlar her satır için bir sonuç döndürür. SELECT, WHERE ve ORDER BY cümlelerinde kullanılabilirler.

Büyük/Küçük Harf Dönüşüm Fonksiyonları

Fonksiyon Açıklama Örnek Sonuç
UPPER(str) Tümü büyük harfe çevirir UPPER('hello') HELLO
LOWER(str) Tümü küçük harfe çevirir LOWER('HELLO') hello
INITCAP(str) İlk harfi büyük yapar INITCAP('hello world') Hello World
SQL
-- WHERE koşulunda büyük/küçük harf sorununu çöz
SELECT empno, ename, deptno
FROM   emp
WHERE  ename = UPPER('blake');
-- Kullanıcı 'blake' yazsa da UPPER sayesinde 'BLAKE' olarak aranır

Karakter Manipülasyon Fonksiyonları

Fonksiyon Açıklama Örnek
CONCAT(s1, s2) İki stringi birleştirir (|| ile de yapılabilir) CONCAT('MARTIN','SALESMAN')MARTINSALESMAN
SUBSTR(str, pos, len) Alt string alır (pos'tan başlayıp len karakter) SUBSTR('SALESMAN',1,5)SALES
LENGTH(str) Karakterin uzunluğunu döndürür LENGTH('MARTIN')6
INSTR(str, substr) Alt stringin ilk konumunu döndürür INSTR('MARTIN','A')2
SQL — Birden Fazla Fonksiyon
SELECT ename,
       CONCAT(ename, job),
       LENGTH(ename),
       INSTR(ename, 'A')
FROM   emp
WHERE  SUBSTR(job, 1, 5) = 'SALES';
-- Mesleği SALES ile başlayan çalışanlar için çeşitli karakter işlemleri

Tarih Aritmetiği

Oracle'da tarihler üzerinde aritmetik işlemler yapılabilir. İki tarih arasındaki fark gün cinsindendir.

SQL
-- Çalışanın kaç haftadır çalıştığını hesapla
SELECT ename,
       (SYSDATE - hiredate) / 7 WEEKS
FROM   emp
WHERE  deptno = 10;
-- SYSDATE: Geçerli sistem tarih ve saatini döndürür
-- Gün farkını 7'ye bölerek hafta sayısı bulunur
📅
SYSDATE Fonksiyonu

SYSDATE, veritabanı sunucusunun anlık tarih ve saatini döndürür. Parametre almaz. INSERT işlemlerinde de kullanışlıdır: işe başlama tarihi olarak SYSDATE yazılabilir.

04

Birden Fazla Tablodan Veri Görüntüleme

Displaying Data from Multiple Tables — JOIN'ler

JOIN Nedir?

JOIN, birden fazla tabloyu ortak sütunlar aracılığıyla birleştirip tek bir sonuç kümesi oluşturmaktır. JOIN koşulu WHERE cümlesine yazılır.

SQL Sözdizimi
SELECT   table1.column, table2.column
FROM     table1, table2
WHERE    table1.column1 = table2.column2;
⚠️
Sütun Adı Çakışması

Aynı sütun adı birden fazla tabloda varsa, hangi tabloya ait olduğunu belirtmek için tablo_adi.sutun_adi formatı kullanılır. Aksi halde SQL hatası oluşur.

Equijoin (Eşit Join)

İki tablo arasında eşitlik koşuluyla yapılan birleştirmedir. En yaygın JOIN türüdür. EMP tablosundaki DEPTNO (foreign key) ile DEPT tablosundaki DEPTNO (primary key) eşlenerek birleştirilir.

SQL
SELECT   emp.empno, emp.ename, emp.deptno,
         dept.deptno, dept.loc
FROM     emp, dept
WHERE    emp.deptno = dept.deptno;

Tablo Alias'ı Kullanmak

Sorguları kısaltmak ve okunabilirliği artırmak için tablolara takma ad verilir.

SQL — Tablo Alias
SELECT   e.empno, e.ename, e.deptno,
         d.deptno, d.loc
FROM     emp e, dept d
WHERE    e.deptno = d.deptno;
-- 'e' emp tablosunu, 'd' dept tablosunu temsil eder

Non-Equijoin (Eşitsizlik Joini)

Eşitlik dışındaki koşullarla yapılan birleştirmedir. EMP tablosundaki SAL ile SALGRADE tablosundaki LOSAL-HISAL arasındaki ilişki buna örnektir — EMP'de SALGRADE'e doğrudan eşleşen bir sütun yoktur.

SQL
-- Her çalışanın maaş derecesini bul
SELECT   e.ename, e.sal, s.grade
FROM     emp e, salgrade s
WHERE    e.sal BETWEEN s.losal AND s.hisal;
-- SAL, LOSAL ile HISAL arasında olduğunda eşleşme sağlanır

Outer Join (Dış Birleştirme)

Normal JOIN'de eşleşmeyen satırlar sonuçta görünmez. Outer Join, eşleşmese bile bir tablodaki TÜM satırları göstermek için kullanılır. Oracle sözdiziminde (+) operatörü "eksik tarafı tamamla" anlamına gelir.

SQL
-- Çalışanı olmayan bölümler de dahil tüm bölümleri göster
SELECT   e.ename, d.deptno, d.dname
FROM     emp e, dept d
WHERE    e.deptno(+) = d.deptno
ORDER BY e.deptno;
-- (+) eksik taraftaki tabloya eklenir (burada EMP tarafı)
-- OPERATIONS departmanı çalışan olmasa da görünür
💡
Outer Join Mantığı

(+) operatörü, satırı eksik olan (az veri içeren) tablonun tarafına konur. Bu sayede diğer tablo tam olarak listelenir. Modern SQL'de bunun karşılığı LEFT JOIN, RIGHT JOIN veya FULL OUTER JOIN'dir.

Self Join (Öz Birleştirme)

Bir tablonun kendisiyle birleştirilmesidir. Hiyerarşik ilişkileri sorgulamak için kullanılır. EMP tablosunda her çalışanın MGR sütunu, aynı tablodaki başka bir çalışanın EMPNO'suna referans verir.

SQL — Çalışan-Yönetici İlişkisi
-- "X, Y için çalışıyor" çıktısı
SELECT   worker.ename || ' works for ' || manager.ename
FROM     emp worker, emp manager
WHERE    worker.mgr = manager.empno;
-- EMP tablosu hem 'worker' hem 'manager' alias'ıyla kullanılıyor
-- Çıktı: BLAKE works for KING, CLARK works for KING, vs.
✏️ Egzersiz 6 — İsminde 'K' Geçenler

İsminde 'K' geçen tüm çalışanların adını ve çalıştıkları departmanın adını görüntüleyin.

✅ Çözüm 6
SQL
SELECT e.ename, d.dname
FROM   emp e, dept d
WHERE  e.deptno = d.deptno
AND    e.ename LIKE '%K%';
✏️ Egzersiz 7 — Üç Tablo JOIN

Tüm çalışanlar için çalışan adı, meslek, departman adı, maaş ve maaş derecesini görüntüleyin.

✅ Çözüm 7
SQL — 3 Tablo JOIN
SELECT e.ename, e.job, d.dname, e.sal, s.grade
FROM   emp e, dept d, salgrade s
WHERE  e.deptno = d.deptno
AND    e.sal BETWEEN s.losal AND s.hisal;
05

Gruplama Fonksiyonları ile Veri Toplama

Aggregating Data Using Group Functions

Gruplama Fonksiyonları Nedir?

Gruplama (aggregate) fonksiyonları, satır kümeleri üzerinde işlem yaparak her grup için tek bir sonuç döndürür. COUNT(*) dışındaki tüm gruplama fonksiyonları NULL değerleri yok sayar.

Fonksiyon Açıklama
AVG(col) Ortalama değeri hesaplar
COUNT(*) Tüm satır sayısını döndürür (NULL dahil)
COUNT(col) NULL olmayan satır sayısını döndürür
MAX(col) Maksimum değeri döndürür
MIN(col) Minimum değeri döndürür
SUM(col) Toplam değeri hesaplar
STDDEV(col) Standart sapmayı hesaplar
VARIANCE(col) Varyansı hesaplar
SQL — AVG, MAX, MIN, SUM
-- Satıcıların maaş istatistikleri
SELECT AVG(sal), MAX(sal),
       MIN(sal), SUM(sal)
FROM   emp
WHERE  job LIKE 'SALES%';

COUNT Fonksiyonu

SQL
-- Departman 30'daki çalışan sayısı (NULL dahil tüm satırlar)
SELECT COUNT(*)
FROM   emp
WHERE  deptno = 30;
-- Sonuç: 6

-- Komisyonu NULL olmayan satır sayısı
SELECT COUNT(comm)
FROM   emp
WHERE  deptno = 30;
-- Sonuç: 4 (sadece NULL olmayanlar sayılır)

NULL Değerler ve NVL Fonksiyonu

Gruplama fonksiyonları NULL değerleri atlar. Eğer NULL değerleri de hesaba katmak istiyorsak NVL fonksiyonu kullanılır.

SQL
-- NULL'ları yok sayarak ortalama (sadece 4 kişi üzerinden)
SELECT AVG(comm) FROM emp;
-- Sonuç: 550 (2200/4 — NULL olanlar sayılmaz)

-- NULL'ları 0 sayarak tüm çalışanlar üzerinden ortalama
SELECT AVG(NVL(comm, 0)) FROM emp;
-- Sonuç: 157.14 (2200/14 — tüm 14 çalışan sayılır)

GROUP BY Cümlesi ile Gruplama

Tabloyu küçük gruplara bölmek için kullanılır. SELECT listesinde gruplama fonksiyonu dışındaki tüm sütunların GROUP BY'da belirtilmesi gerekir.

SQL
-- Her departmandaki ortalama maaş
SELECT   deptno, AVG(sal)
FROM     emp
GROUP BY deptno;
-- Sonuç: 10→2916.67, 20→2175, 30→1566.67

-- Departman ve meslekle çoklu gruplama
SELECT   deptno, job, SUM(sal)
FROM     emp
GROUP BY deptno, job;
🚫
Dikkat: GROUP BY Kuralı

SELECT'te bulunan deptno gibi düz sütunlar GROUP BY'da belirtilmezse ORA-00979 hatası alınır. Gruplama fonksiyonu (AVG, SUM vs.) olan sütunlar GROUP BY'a girmez.

HAVING Cümlesi ile Grup Filtreleme

WHERE bireysel satırları filtreler. HAVING ise gruplanmış sonuçları filtreler. Gruplama fonksiyonlarını WHERE'de kullanamazsınız; bunun için HAVING kullanılır.

SQL
-- Maksimum maaşı 2900'den yüksek olan departmanlar
SELECT   deptno, MAX(sal)
FROM     emp
GROUP BY deptno
HAVING   MAX(sal) > 2900;
-- Dept 10 (5000) ve Dept 20 (3000)

-- WHERE + GROUP BY + HAVING + ORDER BY birlikte
SELECT   job, SUM(sal) PAYROLL
FROM     emp
WHERE    job NOT LIKE 'SALES%'
GROUP BY job
HAVING   SUM(sal) > 5000
ORDER BY SUM(sal);

Gruplama Fonksiyonlarını İç İçe Kullanmak

Gruplama fonksiyonları iç içe kullanılabilir. Bu şekilde "grupların grubu" hesaplanabilir.

SQL
-- Departman ortalamalarının en yükseği
SELECT   MAX(AVG(sal))
FROM     emp
GROUP BY deptno;
-- Önce her dept ortalanır: 2916.67, 2175, 1566.67
-- Sonra bunların maksimumu alınır: 2916.67
✏️ Egzersiz 8 — Departman Sayısı

Yalnızca EMP tablosunu kullanarak kaç departman numarası olduğunu görüntüleyin.

✅ Çözüm 8 & 9
SQL
-- Egzersiz 8: Toplam dept sayısı (tekrarlar dahil)
SELECT COUNT(deptno) FROM emp;

-- Egzersiz 9: Benzersiz dept sayısı
SELECT COUNT(DISTINCT deptno) FROM emp;
06

Alt Sorgular (Subqueries)

Subqueries

Alt Sorgu Nedir?

Alt sorgu, başka bir sorgunun içine gömülmüş SELECT sorgusudur. İç sorgu (subquery) önce çalışır ve sonucu dış sorgu (main query) tarafından kullanılır. WHERE veya HAVING cümlesinde, hatta FROM cümlesinde kullanılabilir.

Sözdizimi
SELECT   select_list
FROM     table
WHERE    expr operator
         (SELECT   select_list
          FROM     table);
Örnek — Jones'ten fazla kazanan çalışanlar
SELECT ename
FROM   emp
WHERE  sal >
       (SELECT sal
        FROM   emp
        WHERE  empno = 7566);
-- İç sorgu Jones'in maaşını (2975) döndürür
-- Dış sorgu 2975'ten fazla kazananları getirir: KING, FORD, SCOTT

Alt Sorgu Türleri

🔹 Tek Satır Alt Sorgu

İç sorgu yalnızca bir satır döndürür. =, >, <, >=, <=, <> operatörleriyle kullanılır.

🔸 Çok Satırlı Alt Sorgu

İç sorgu birden fazla satır döndürür. IN, ANY, ALL operatörleriyle kullanılır.

Tek Satır — Çoklu Koşul
-- Mesleği Smith ile aynı VE maaşı Adams'tan yüksek olan çalışanlar
SELECT   ename, job
FROM     emp
WHERE    job = (SELECT job
                 FROM   emp
                 WHERE  empno = 7369)
AND      sal > (SELECT sal
                 FROM   emp
                 WHERE  empno = 7876);
-- Sonuç: MILLER

Gruplama Fonksiyonu ile Alt Sorgu

SQL
-- En düşük maaşlı çalışan
SELECT   ename, job, sal
FROM     emp
WHERE    sal = (SELECT MIN(sal)
                 FROM   emp);
-- Sonuç: SMITH, CLERK, 800

Çok Satırlı Alt Sorgular: IN, ANY, ALL

Operatör Anlamı
IN Listedeki herhangi bir değere eşit
<ANY Listedeki maksimumdan küçük
>ANY Listedeki minimumdan büyük
=ANY IN ile eşdeğer
>ALL Listedeki maksimumdan büyük
<ALL Listedeki minimumdan küçük
ANY Operatörü
-- CLERK olmayan ama herhangi bir CLERK'ten az kazananlar
SELECT   empno, ename, job
FROM     emp
WHERE    sal < ANY
         (SELECT sal
          FROM   emp
          WHERE  job = 'CLERK')
AND      job <> 'CLERK';
-- <ANY = maksimumdan az (en yüksek CLERK maaşından az)
ALL Operatörü
-- Her departman ortalamasından yüksek maaş kazananlar
SELECT   empno, ename, job
FROM     emp
WHERE    sal > ALL
         (SELECT AVG(sal)
          FROM   emp
          GROUP BY deptno);
-- >ALL = tüm değerlerden büyük = maksimumdan büyük
-- KING, JONES, FORD, SCOTT

FROM Cümlesinde Alt Sorgu (Inline View)

FROM cümlesinde bir alt sorgu kullanılabilir. Bu yapıya Inline View denir. Sanki geçici bir tablo gibi davranır.

SQL — Inline View
-- Departman ortalamasından fazla kazanan çalışanlar
SELECT   a.ename, a.sal, a.deptno, b.salavg
FROM     emp a,
         (SELECT deptno, AVG(sal) salavg
          FROM   emp
          GROUP BY deptno) b
WHERE    a.deptno = b.deptno
AND      a.sal > b.salavg;
🚫
Yaygın Hata: Tek Satır Beklenen Yerde Çok Satır Dönmek

Eğer = operatörüyle kullandığınız alt sorgu birden fazla satır döndürürse ORA-01427: single-row subquery returns more than one row hatası alırsınız. Bu durumda IN veya diğer çok satır operatörlerini kullanın.

✏️ Egzersiz 10 — Jones ile Aynı Meslek

Mesleği Jones ile aynı olan VE Jones'tan sonra işe başlayan çalışanların adı ve maaşını görüntüleyin.

✅ Çözüm 10
SQL
SELECT ename, sal
FROM   emp
WHERE  job      = (SELECT job
                     FROM   emp
                     WHERE  ename LIKE 'JONES')
AND    hiredate > (SELECT hiredate
                     FROM   emp
                     WHERE  ename LIKE 'JONES');
✏️ Egzersiz 11 — Ortalamanın Üstünde Maaş

Ortalama maaştan fazla kazanan tüm çalışanların numarasını ve adını görüntüleyin.

✅ Çözüm 11
SQL
SELECT empno, ename
FROM   emp
WHERE  sal > (SELECT AVG(sal) FROM emp);
✏️ Egzersiz 12 — Departman Minimumları

Her departmandaki minimum maaşı departman numarasına göre sıralayarak görüntüleyin.

✅ Çözüm 12
SQL
SELECT   deptno, MIN(sal)
FROM     emp
GROUP BY deptno
ORDER BY deptno;
✏️ Egzersiz 13 — En Kalabalık Departman

En fazla çalışana sahip departmanın numarasını bulun.

✅ Çözüm 13 (İki Yöntem)
Yöntem 1 — Inline View ile
SELECT DISTINCT e.deptno
FROM   emp e,
       (SELECT deptno, COUNT(empno) numberofemp
        FROM   emp
        GROUP BY deptno) c
WHERE  c.numberofemp = (SELECT MAX(COUNT(empno))
                         FROM   emp
                         GROUP BY deptno)
AND    e.deptno = c.deptno;
Yöntem 2 — HAVING ile
SELECT   e.deptno
FROM     emp e
GROUP BY e.deptno
HAVING   COUNT(empno) = (SELECT MAX(COUNT(empno))
                           FROM   emp
                           GROUP BY deptno);
07

Çok Sütunlu Alt Sorgular

Multiple-Column Subqueries

Çok Sütunlu Alt Sorgu Nedir?

Alt sorgunun birden fazla sütun döndürdüğü durumlardır. Ana sorgu bu çok sütunlu değerlerle karşılaştırma yapar. Sütunlar parantez içinde eşleştirilir.

SQL
-- 605 numaralı siparişle hem aynı ürünü hem aynı miktarı içeren diğer siparişler
SELECT   ordid, prodid, qty
FROM     item
WHERE    (prodid, qty) IN
         (SELECT prodid, qty
          FROM   item
          WHERE  ordid = 605)
AND      ordid <> 605;

NULL Değer ve NOT IN ile Oluşan Sorun

NOT IN operatörü içeren alt sorgu NULL değer döndürürse, sonuç her zaman boş döner. Bunun nedeni NOT IN'in !=ALL'a eşdeğer olmasıdır ve NULL karşılaştırması her zaman FALSE üretir.

Dikkat Gerektiren Durum
-- Hiç astı olmayan çalışanları bulmaya çalışıyoruz
SELECT ename
FROM   emp employee
WHERE  empno NOT IN
       (SELECT mgr
        FROM   emp manager);
-- SORUN: MGR sütununda NULL var (KING'in yöneticisi yok)
-- Bu yüzden hiç satır dönmez!
-- ÇÖZÜM: WHERE mgr IS NOT NULL koşulu eklenmelidir
08

Veri Manipülasyonu — DML

Manipulating Data — INSERT, UPDATE, DELETE

INSERT — Yeni Satır Ekleme

INSERT INTO deyimi tabloya yeni satır ekler. Bu sözdizimde bir seferde yalnızca tek satır eklenir.

Sözdizimi
INSERT INTO table [(column [, column...])]
VALUES      (value [, value...]);
SQL — Tüm Sütunlarla
-- Sütun listesi belirterek (güvenli yöntem)
INSERT INTO dept (deptno, dname, loc)
VALUES      (50, 'DEVELOPMENT', 'DETROIT');

NULL Değer Eklemek

SQL
-- Örtük yöntem: LOC sütununu atla (NULL olur)
INSERT INTO dept (deptno, dname)
VALUES      (60, 'MIS');

-- Açık yöntem: NULL anahtar kelimesini yaz
INSERT INTO dept
VALUES      (70, 'FINANCE', NULL);

SYSDATE ile Tarih Eklemek

SQL
INSERT INTO emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
VALUES      (7196, 'GREEN', 'SALESMAN', 7782, SYSDATE, 2000, NULL, 10);

TO_DATE ile Belirli Tarih Formatı

SQL
INSERT INTO emp
VALUES      (2296, 'AROMANO', 'SALESMAN', 7782,
             TO_DATE('FEB 3, 1997', 'MON DD, YYYY'),
             1300, NULL, 10);

Alt Sorgu ile Çok Satır Eklemek

SQL
-- Meslekleri MANAGER olan tüm çalışanları başka tabloya kopyala
INSERT INTO managers(id, name, salary, hiredate)
    SELECT empno, ename, sal, hiredate
    FROM   emp
    WHERE  job = 'MANAGER';
-- VALUES cümlesi kullanılmaz, sütun sayıları eşleşmeli

UPDATE — Mevcut Satırları Güncelleme

Tablodaki mevcut satırları değiştirmek için kullanılır. WHERE olmadan tüm satırlar güncellenir.

SQL
-- Belirli satırı güncelle
UPDATE emp
SET    deptno = 20
WHERE  empno = 7782;

-- Çok sütunlu alt sorgu ile güncelleme
UPDATE emp
SET    (job, deptno) =
       (SELECT job, deptno
        FROM   emp
        WHERE  empno = 7499)
WHERE  empno = 7698;
-- 7499'un meslek ve departmanını 7698'e kopyalar
⚠️
WHERE Olmadan UPDATE Tehlikesi

WHERE cümlesi belirtilmezse tablodaki tüm satırlar güncellenir. Bu geri alınabilir ancak çok büyük bir yanlışlık olabilir. Her zaman dikkatli olun.

DELETE — Satır Silme

Tablodan mevcut satırları kaldırır. WHERE olmadan tüm satırlar silinir.

SQL
-- Belirli bir satırı sil
DELETE FROM department
WHERE       dname = 'DEVELOPMENT';

-- Alt sorgu ile başka tablodaki değere göre sil
DELETE FROM employee
WHERE       deptno =
            (SELECT deptno
             FROM   dept
             WHERE  dname = 'SALES');
-- SALES departmanındaki tüm çalışanları siler (6 satır)

COMMIT, ROLLBACK ve SAVEPOINT — İşlem Kontrolü

DML işlemleri (INSERT, UPDATE, DELETE) otomatik olarak veritabanına kaydedilmez; bir transaction (işlem) içinde bekler.

Komut Açıklama
COMMIT Tüm bekleyen değişiklikleri kalıcı olarak veritabanına yazar
ROLLBACK Tüm bekleyen değişiklikleri geri alır
SAVEPOINT name Transaction içinde bir geri dönüş noktası oluşturur
ROLLBACK TO name Belirtilen savepoint'e kadar geri alır

COMMIT Öncesi Durum

  • Önceki veri kurtarılabilir durumdadır.
  • Mevcut kullanıcı SELECT ile değişiklikleri görebilir.
  • Diğer kullanıcılar değişiklikleri göremez.
  • Etkilenen satırlar kilitlidir (diğerleri değiştiremez).

COMMIT Sonrası Durum

  • Değişiklikler kalıcı olarak veritabanına yazılır.
  • Önceki veri geri getirilemez.
  • Tüm kullanıcılar sonuçları görebilir.
  • Kilitlenen satırlar serbest bırakılır.
  • Tüm savepoint'ler silinir.
SQL — Transaction Örneği
UPDATE emp
SET    deptno = 10
WHERE  empno = 7782;

COMMIT; -- Değişiklik kalıcı hale geldi

-- Hata yapıldı, tüm değişiklikleri geri al
DELETE FROM employee;
ROLLBACK; -- 14 satır geri geldi!
09

Tablo Oluşturma ve Yönetme

Creating and Managing Tables — DDL

CREATE TABLE — Tablo Oluşturma

Tablo oluşturmak için CREATE TABLE yetkisi ve depolama alanı gereklidir.

Sözdizimi
CREATE [GLOBAL TEMPORARY] TABLE [schema.]table
       (column datatype [DEFAULT expr][, ...]);
SQL
CREATE TABLE dept
       (deptno NUMBER(2),
        dname  VARCHAR2(14),
        loc    VARCHAR2(13));

-- Tablo yapısını doğrula
DESCRIBE dept;

Oracle Veri Tipleri

Tip Açıklama
VARCHAR2(size) Değişken uzunluklu karakter verisi. En yaygın kullanılan string tipidir.
CHAR(size) Sabit uzunluklu karakter verisi (eksik kısımlar boşlukla doldurulur)
NUMBER(p,s) Sayısal veri. p: toplam basamak sayısı, s: ondalık basamak sayısı
DATE Tarih ve saat bilgisi (DD-MON-YY formatı)
LONG 2 GB'a kadar değişken uzunluklu karakter
CLOB 4 GB'a kadar tek baytlı karakter verisi
BLOB 4 GB'a kadar ikili (binary) veri
RAW / LONG RAW Ham ikili veri
BFILE Harici dosyada saklanan ikili veri (4 GB'a kadar)

Alt Sorgu ile Tablo Oluşturma

CREATE TABLE ve SELECT'i birleştirerek hem tablo oluşturulabilir hem de veri eklenebilir.

SQL
CREATE TABLE dept30
AS
   SELECT empno, ename, sal*12 ANNSAL, hiredate
   FROM   emp
   WHERE  deptno = 30;
-- dept30 tablosu oluşturulur VE Dept 30 çalışanları eklenir

ALTER TABLE — Tablo Değiştirme

Mevcut tabloya sütun ekleme, sütun değiştirme ve sütun silme için kullanılır.

SQL
-- Sütun ekleme (ADD)
ALTER TABLE dept30
ADD         (job VARCHAR2(9));
-- Yeni sütun tablonun sonuna eklenir, değerleri NULL olur

-- Sütun boyutunu değiştirme (MODIFY)
ALTER TABLE dept30
MODIFY      (ename VARCHAR2(15));
-- Boyut artırılabilir; küçültme için sütun boş olmalı

-- Sütun silme (DROP COLUMN)
ALTER TABLE dept30
DROP COLUMN job;

DROP TABLE — Tablo Silme

SQL
DROP TABLE dept30;
⚠️
DROP TABLE Kalıcıdır!

DROP TABLE tablo yapısını ve tüm veriyi siler. Bekleyen tüm işlemler COMMIT edilir. Tüm index'ler kaldırılır. Bu işlem geri alınamaz (ROLLBACK edilemez). Çok dikkatli kullanılmalıdır.

10

Kısıtlamalar (Constraints)

Including Constraints

Kısıtlamalar, tablo seviyesinde veri bütünlüğünü sağlayan kurallardır. Tablo oluştururken veya sonradan ALTER TABLE ile eklenebilirler.

Kısıtlama Türleri

NOT NULL — Boş Değer Yasağı

O sütuna NULL değer girilmesini engeller. Yalnızca sütun düzeyinde tanımlanır.

SQL
CREATE TABLE emp(
     empno    NUMBER(4),
     ename    VARCHAR2(10) NOT NULL,  -- zorunlu alan
     deptno   NUMBER(7,2) NOT NULL);

UNIQUE KEY — Benzersizlik Kısıtlaması

Sütundaki tüm değerlerin benzersiz olmasını sağlar. NULL değerlere izin verilir (birden fazla NULL olabilir çünkü NULL = NULL değildir).

SQL
CREATE TABLE dept(
     deptno  NUMBER(2),
     dname   VARCHAR2(14),
     loc     VARCHAR2(13),
     CONSTRAINT dept_dname_uk UNIQUE(dname));
-- Aynı departman adı iki kez girilemez

PRIMARY KEY — Birincil Anahtar

Satırı benzersiz olarak tanımlayan anahtardır. NULL olamaz ve benzersiz olmalıdır. Her tabloda yalnızca bir PRIMARY KEY olabilir ancak birden fazla sütunu kapsayabilir (bileşik anahtar).

SQL
CREATE TABLE dept(
     deptno  NUMBER(2),
     dname   VARCHAR2(14),
     loc     VARCHAR2(13),
     CONSTRAINT dept_dname_uk UNIQUE (dname),
     CONSTRAINT dept_deptno_pk PRIMARY KEY(deptno));

FOREIGN KEY — Yabancı Anahtar

Bir tablodaki değerin başka bir tablonun primary key değerleriyle uyumlu olmasını zorunlu kılar. Referans bütünlüğünü sağlar.

SQL
CREATE TABLE emp(
     empno   NUMBER(4),
     ename   VARCHAR2(10) NOT NULL,
     deptno  NUMBER(7,2) NOT NULL,
     CONSTRAINT emp_deptno_fk FOREIGN KEY (deptno)
                REFERENCES dept (deptno));
🔗
ON DELETE CASCADE

FOREIGN KEY tanımına ON DELETE CASCADE eklenirse, parent tablodaki (üst tablo) bir satır silindiğinde buna bağlı child tablodaki (alt tablo) satırlar da otomatik silinir.

CHECK — Koşul Kısıtlaması

Her satırın karşılaması gereken bir koşul tanımlar. Diğer satırlara referans veremez, SYSDATE, ROWNUM gibi pseudosütunları kullanamaz.

SQL
deptno NUMBER(2),
CONSTRAINT emp_deptno_ck
      CHECK (DEPTNO BETWEEN 10 AND 99)

Kısıtlama Yönetimi

SQL — Kısıtlama Ekle / Kaldır / Devre Dışı Bırak / Etkinleştir
-- Kısıtlama ekleme
ALTER TABLE emp
ADD CONSTRAINT emp_mgr_fk
         FOREIGN KEY(mgr) REFERENCES emp(empno);

-- Kısıtlama kaldırma
ALTER TABLE emp
DROP CONSTRAINT emp_mgr_fk;

-- PRIMARY KEY kaldırma + bağlı FK'ları da kaldır
ALTER TABLE dept
DROP PRIMARY KEY CASCADE;

-- Kısıtlamayı geçici devre dışı bırakma
ALTER TABLE emp
DISABLE CONSTRAINT emp_empno_pk CASCADE;

-- Kısıtlamayı tekrar etkinleştirme
ALTER TABLE emp
ENABLE CONSTRAINT emp_empno_pk;

Kısıtlamaları Görüntüleme

SQL — Data Dictionary Sorguları
-- Tablodaki tüm kısıtlamalar
SELECT constraint_name, constraint_type, search_condition
FROM   user_constraints
WHERE  table_name = 'EMP';

-- Kısıtlamaların hangi sütunlara uygulandığı
SELECT constraint_name, column_name
FROM   user_cons_columns
WHERE  table_name = 'EMP';
11

View (Görünüm)

Views

View Nedir?

View, bir SELECT sorgusunun sonucuna dayanan sanal bir tablodur. Gerçek veri içermez; veriyi altındaki tablolardan türetir. "Saklanmış sorgu" olarak da düşünülebilir.

  • Bir veya daha fazla tablonun özelleştirilmiş sunumudur.
  • Veri bütünlüğü için ek güvenlik katmanı sağlar (belirli sütun/satırları gizler).
  • Karmaşık sorguları basitleştirir.
  • Veri içermez, her sorguda altındaki tablolardan çeker.

View Oluşturma

Sözdizimi
CREATE VIEW view_name AS
SELECT column_name(s)
FROM   table_name
WHERE  condition;
Örnek — CLERK View'ı
-- Mesleği CLERK olan çalışanların adı ve maaşını gösteren view
CREATE VIEW Clerk AS
SELECT ename, sal
FROM   emp
WHERE  job = 'CLERK';
Örnek — Çok Tablolu View
CREATE VIEW EmpDepartments AS
SELECT emp.ename, dept.deptno, dept.dname
FROM   emp, dept
WHERE  emp.deptno = dept.deptno;

View'da Sütun Yeniden Adlandırma

SQL
CREATE VIEW Clerk (clerkName, clerkSalary) AS
SELECT ename, sal
FROM   emp
WHERE  job = 'CLERK';
-- View sütunları: clerkName, clerkSalary

View'ı Sorgulamak

View, normal tablo gibi sorgulanır. İçine fonksiyon, JOIN vs. ekleyerek kullanıcıya tam ihtiyacı olan veriyi sunar.

SQL
-- View üzerinden sorgu
SELECT ename
FROM   Clerk
WHERE  sal > 1000;

-- Bu sorgu şuna eşdeğerdir:
SELECT ename
FROM   emp
WHERE  job = 'CLERK' AND sal > 1000;

View'ı Güncellemek (DML İşlemleri)

Bazı view'lar güncellenebilirdir. View üzerindeki DML işlemi doğrudan altındaki tabloya yansır.

Güncellenemeyen View Koşulları

Şu yapıları içeren view'lar güncellenemez:

Aggregate Fonksiyonlar DISTINCT GROUP BY HAVING ROWNUM
INSERT — View Üzerinden
-- Güncellenebilir Clerk view'ı (empno dahil)
CREATE VIEW Clerk AS
SELECT empno, ename, job, sal
FROM   emp
WHERE  job = 'CLERK';

INSERT INTO Clerk
VALUES      (1234, 'SUE', 'CLERK', 8000);
-- emp tablosuna da eklenir!
DELETE ve UPDATE — View Üzerinden
-- View üzerinden silme → emp tablosundan da silinir
DELETE FROM Clerk
WHERE       ename LIKE '%MS%';

-- View üzerinden güncelleme → emp tablosunda güncellenir
UPDATE Clerk
SET    sal = 1000
WHERE  ename = 'JAMES';

WITH READ ONLY — Salt Okunur View

DML işlemlerinin (INSERT, UPDATE, DELETE) yapılmasını engelleyen view'lardır.

SQL
CREATE VIEW Manager AS
     SELECT empno, ename, sal
     FROM   emp
     WHERE  job = 'MANAGER'
     WITH READ ONLY;

-- Hata verir: ORA-42399
DELETE FROM Manager WHERE ename = 'JONES';

DROP VIEW — View Silme

SQL
DROP VIEW Clerk;
-- Sadece view tanımı silinir, emp tablosu etkilenmez!
-- Ancak DROP TABLE emp yapılırsa Clerk view'ı kullanılamaz hale gelir.
12

Trigger (Tetikleyici)

Triggers

Trigger Nedir?

Trigger, belirli bir olay gerçekleştiğinde otomatik olarak çalışan (ateşlenen) saklı PL/SQL birimidir. Kullanıcı müdahalesi gerektirmez.

Temel Yapı
TRIGGER trigger_name
    triggering_event
    [ trigger_restriction ]
BEGIN
      triggered_action;
END;

Trigger Olayları

Olay Türü Örnekler Kullanım
DML Events INSERT, UPDATE, DELETE Tablo üzerindeki veri değişiklikleri
DDL Events CREATE, ALTER Şema değişikliklerini denetleme
System Events Database startup/shutdown Sistem başlatma/kapatma işlemleri
User Events User login/logout Oturum açma/kapama denetimi

Oracle Trigger Kullanım Alanları

  • İş Kuralı Zorunluluğu: UNIQUE, NOT NULL, CHECK ile tanımlanamayan karmaşık kurallar.
  • Hata Önleme: Geçersiz işlemleri durdurar, veri kalitesini artırır.
  • İstatistik Toplama: Tablo kullanım verilerini toplar.
  • Otomatik Değer Hesaplama: Türetilen sütun değerlerini otomatik doldurur.
  • Denetim (Audit): Güvenlik ve uyum için değişiklikleri kayıt altına alır.

Trigger Oluşturma Sözdizimi

SQL — Tam Sözdizimi
CREATE [OR REPLACE] TRIGGER trigger_name
    {BEFORE | AFTER} triggering_event [OF column_name] ON
     table_name
    [REFERENCING <old or new values alias list>]
    [FOR EACH ROW]
    [FOLLOWS | PRECEDES another_trigger]
    [ENABLE / DISABLE]
    [WHEN condition]
    DECLARE
        declaration statements
    BEGIN
        executable statements
    EXCEPTION
        exception_handling statements
    END;
Parametre Açıklama
BEFORE | AFTER Trigger olaydan önce mi sonra mı çalışır?
FOR EACH ROW Satır seviyesi trigger. Her etkilenen satır için çalışır. Yoksa statement seviyesidir.
:new.column Yeni (girilecek veya güncellenecek) değer
:old.column Eski (mevcut) değer
WHEN condition Trigger'ın yalnızca belirli koşulda çalışması için filtre
OR REPLACE Aynı adda trigger varsa üzerine yazar

Örnek 1 — Otomatik Komisyon Hesaplama

Maaş güncellendiğinde yeni maaş 3000'den büyükse komisyonu eski maaşın %5'i olarak ayarla.

SQL — Trigger Örnek 1
CREATE OR REPLACE TRIGGER CommUpdate
BEFORE UPDATE OF sal ON emp
REFERENCING old as oldrow new as newrow
FOR EACH ROW
WHEN (newrow.sal > 3000)
BEGIN
   :newrow.comm := :oldrow.sal / 20;  -- %5 komisyon
END;
Test
-- SMITH'in (7369) maaşını 3500'e yükselt
UPDATE emp
SET    sal = 3500
WHERE  empno = 7369;
-- 3500 > 3000 koşulu sağlandığı için trigger çalışır
-- comm = eski_maaş / 20 = 800 / 20 = 40 olarak ayarlanır

Örnek 2 — Maaş Derecesi Doğrulama

Eklenen veya güncellenen maaş, SALGRADE tablosundaki herhangi bir dereceyle eşleşmiyorsa hata fırlat.

SQL — Trigger Örnek 2 (Yöntem 1)
CREATE OR REPLACE TRIGGER emp_salary_check
BEFORE INSERT OR UPDATE OF sal ON emp
FOR EACH ROW
DECLARE
  sal_grade NUMBER;
BEGIN
  SELECT grade INTO sal_grade
  FROM   Salgrade
  WHERE  :new.sal BETWEEN losal AND hisal;
EXCEPTION
 WHEN NO_DATA_FOUND THEN
  RAISE_APPLICATION_ERROR(-20001, 'Salary does not match any defined grade.');
END;
SQL — Trigger Örnek 2 (Yöntem 2)
CREATE OR REPLACE TRIGGER emp_salary_check
BEFORE INSERT OR UPDATE OF sal ON emp
FOR EACH ROW
DECLARE
  grade_count NUMBER;
BEGIN
  SELECT COUNT(grade) INTO grade_count
  FROM   Salgrade
  WHERE  :new.sal BETWEEN losal AND hisal;

  IF grade_count = 0 THEN
     RAISE_APPLICATION_ERROR(-20002, 'Salary does not match any defined grade.');
  END IF;
END;
Test
-- KING'in (7839) maaşını 15000 yap → SALGRADE'de yok
UPDATE emp
SET    sal = 15000
WHERE  empno = 7839;
-- HATA: 15000, SALGRADE tablosundaki hiçbir dereceyle eşleşmiyor (max 9999)

Örnek 3 — Denetim (Audit) Trigger'ı

EMP tablosunda UPDATE veya DELETE yapıldığında, yapılan işlemi bir denetim (audit) tablosuna kaydet.

Adım 1 — Audit Tablosu Oluştur
CREATE TABLE audits (
   audit_id         NUMBER GENERATED BY DEFAULT AS IDENTITY
PRIMARY KEY,
   table_name       VARCHAR2(255),
   transaction_name VARCHAR2(10),
   by_user          VARCHAR2(30),
   transaction_date DATE
);
Adım 2 — Audit Trigger'ı Oluştur
CREATE OR REPLACE TRIGGER emp_audit_trg
AFTER UPDATE OR DELETE ON emp
FOR EACH ROW
DECLARE
  l_transaction VARCHAR2(10);
BEGIN
  -- İşlem türünü belirle
  l_transaction := CASE
     WHEN UPDATING THEN 'UPDATE'
     WHEN DELETING THEN 'DELETE'
  END;

  -- Audit tablosuna kayıt ekle
  INSERT INTO audits (table_name, transaction_name, by_user, transaction_date)
  VALUES ('EMP', l_transaction, USER, SYSDATE);
END;
Test
-- SMITH'in (7369) maaşını güncelle
UPDATE emp
SET    sal = 2000
WHERE  empno = 7369;
-- audits tablosuna otomatik kayıt eklenir:
-- table_name='EMP', transaction_name='UPDATE', by_user='HR', transaction_date=...
Trigger vs. Constraint Karşılaştırması

Kısıtlamalar (NOT NULL, UNIQUE, FK vs.) basit veri bütünlüğü kuralları için yeterlidir ve performanslıdır. Trigger'lar ise karmaşık iş kuralları, çapraz tablo kontrolleri, otomatik hesaplamalar ve denetim işlemleri için kullanılır. İkisi birbirini tamamlar.

13

Sınav Hazırlık ve Pratik

Öğrenilen tüm konuların pekiştirilmesi için kapsamlı sorular

Aşağıdaki sorular, daha önceki 12 bölümde anlatılan konuları kapsamakta olup, klasik sınav ve mülakat soruları tarzında hazırlanmıştır.

A. Açık Uçlu Soru ve Çözümleri

S1 En yüksek maaş alan çalışanın adını ve maaşını listeleyen SQL sorgusunu yazınız.
SELECT ename, sal FROM emp WHERE sal = (SELECT MAX(sal) FROM emp);
S2 Her departmandaki çalışan sayısını, departman adıyla birlikte listeleyiniz (Çalışanı olmayan departmanlar da listelensin).
SELECT d.dname, COUNT(e.empno) 
FROM dept d 
LEFT JOIN emp e ON d.deptno = e.deptno 
GROUP BY d.dname;
S3 Ortalamanın üzerinde maaş alan çalışanları ve yöneticilerinin isimlerini listeleyen sorgu yazınız.
SELECT e.ename AS "Çalışan", m.ename AS "Yönetici" 
FROM emp e 
LEFT JOIN emp m ON e.mgr = m.empno 
WHERE e.sal > (SELECT AVG(sal) FROM emp);
S4 İçinde 'A' harfi geçen çalışanların departmanlarının lokasyonlarını listeleyin (Tekrarsız).
SELECT DISTINCT d.loc 
FROM emp e 
JOIN dept d ON e.deptno = d.deptno 
WHERE e.ename LIKE '%A%';
S5 Hiç çalışanı olmayan departmanları listeleyen sorgu (Alt sorgu kullanarak).
SELECT dname 
FROM dept 
WHERE deptno NOT IN (SELECT DISTINCT deptno FROM emp WHERE deptno IS NOT NULL);
S6 Her maaş derecesindeki (SALGRADE) çalışan sayısını bulan sorgu yazınız.
SELECT s.grade, COUNT(e.empno) 
FROM emp e 
JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal 
GROUP BY s.grade;
S7 En son işe giren 3 çalışanı listeleyen sorgu yazınız.
SELECT * FROM (
  SELECT ename, hiredate 
  FROM emp 
  ORDER BY hiredate DESC
) WHERE ROWNUM <= 3;
S8 Maaşı, bağlı bulunduğu departmanın ortalama maaşından yüksek olan çalışanları listeleyin.
SELECT e.ename, e.sal, e.deptno 
FROM emp e 
WHERE e.sal > (SELECT AVG(sal) FROM emp WHERE deptno = e.deptno);
S9 SALES departmanındaki herhangi birinden daha yüksek maaş alan çalışanları listeleyin (ANY operatörü).
SELECT ename, sal 
FROM emp 
WHERE sal > ANY (
  SELECT sal FROM emp 
  JOIN dept ON emp.deptno = dept.deptno 
  WHERE dname = 'SALES'
);
S10 Yeni bir çalışan eklendiğinde veya güncellendiğinde maaşı negatif ise hata veren bir Trigger oluşturun.
CREATE OR REPLACE TRIGGER trg_check_sal 
BEFORE INSERT OR UPDATE ON emp 
FOR EACH ROW 
BEGIN 
  IF :NEW.sal < 0 THEN 
    RAISE_APPLICATION_ERROR(-20001, 'Maaş negatif olamaz'); 
  END IF; 
END;

B. Çoktan Seçmeli Test

1
Hangi fonksiyon NULL değerleri başka bir değere çevirmek için kullanılır?
💡 Cevabı Göster
Cevap: A
NVL(sütun, deger) şeklinde kullanılır ve NULL olan veriyi belirtilen değere dönüştürür.
2
GROUP BY kullanılan bir sorguda, grupların sonuçlarına göre filtreleme yapmak için hangi ifade kullanılır?
💡 Cevabı Göster
Cevap: B
Grup fonksiyonları (SUM, COUNT, AVG vb.) WHERE ile kullanılamaz, gruplandırılmış veriyi filtrelemek için HAVING gereklidir.
3
SELECT COUNT(COMM) FROM EMP; sorgusu neyi döndürür?
💡 Cevabı Göster
Cevap: C
COUNT(sütun_adi) ifadesi, o sütundaki NULL OLMAYAN satırları sayar. Tüm satırları saymak için COUNT(*) kullanılır.
4
WHERE ename LIKE '_A%' koşulu ne anlama gelir?
💡 Cevabı Göster
Cevap: C
Alt çizgi (_) tek bir karakteri temsil eder, yüzde (%) ise sıfır veya daha fazla karakteri temsil eder. _A% ifadesi "ilk karakter herhangi bir şey, ikinci karakter A ve sonrası herhangi bir şey" demektir.
5
Hangi kısıtlama (Constraint) bir sütundaki değerlerin benzersiz olmasını garanti eder ama NULL değerlere izin verir?
💡 Cevabı Göster
Cevap: B
UNIQUE kısıtlaması tekrarlı (mükerrer) değere izin vermez fakat birden fazla satırda NULL değer bulunabilir. PRIMARY KEY ise NULL'a kesinlikle izin vermez.
6
A tablosunda 5 satır, B tablosunda 4 satır varsa; SELECT * FROM A CROSS JOIN B; sorgusu kaç satır döndürür?
💡 Cevabı Göster
Cevap: C
Cross join (Kartezyen çarpım) tabloların tüm olasılıklarını birbirleriyle eşleştirir, yani satır sayıları çarpılır (5 x 4 = 20).
7
Bir View üzerinde DML işlemleri (INSERT, UPDATE) yapmak için view'in hangi özelliğe sahip olması şart DEĞİLDİR?
💡 Cevabı Göster
Cevap: C
ORDER BY, view içindeki verilerin sadece görüntüleme sırasını değiştirir ve DML işlemlerini engellemez. Ancak GROUP BY veya DISTINCT gibi özet/gruplama operasyonları view üzerinden DML (Veri manipülasyonu) yapılmasını engeller.
8
Bir satır eklendikten sonra (AFTER INSERT) çalışan Trigger'ın içinde :NEW.sütun = deger; ataması yapılırsa ne olur?
💡 Cevabı Göster
Cevap: B
AFTER trigger'larında :NEW değerleri değiştirilemez, sadece okunabilir. Yeni değer üzerinde manipülasyon yapmak isteniyorsa BEFORE trigger kullanılmalıdır.
9
Aşağıdaki veri tiplerinden hangisi Oracle'da bir sütun tipi değildir?
💡 Cevabı Göster
Cevap: D
Oracle'da tarih/zaman için DATE veya TIMESTAMP kullanılır. DATETIME daha çok SQL Server (T-SQL) ve MySQL gibi sistemlerde bulunur.
10
SELECT DECODE(deptno, 10, 'A', 20, 'B', 'C') FROM emp; ifadesi SQL standartlarındaki hangi ifadeyle eşdeğerdir?
💡 Cevabı Göster
Cevap: B
DECODE, Oracle'a özgü bir fonksiyondur ve SQL standartlarındaki CASE WHEN yapısının daha kısa halidir.

SQL Kapsamlı Konu Anlatımı  •  Oracle SQL Tabanlı  •  EMP / DEPT / SALGRADE Örnek Veritabanı

13 Konu  •  Temel SELECT'ten Trigger'lara  •  Tüm Egzersiz ve Çözümler Dahil