• Foruma hoş geldin 👋 Ziyaretçi

    Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

Arşiv Kapalı Excel Dosyasından Veri Alma (ADO)

aeGNoR

Destek Ekibi
Katılım
10 Mar 2021
Mesajlar
878
Çözümler
116
Aldığı beğeni
1,017
Excel V
Office 2021 TR
Arkadaşlar merhaba,
Excel kullanımı sırasında zaman zaman kullandığımız excel dışındaki dosyalara başvurmamız gerekebiliyor. VBA ile bu duruma çeşitli çözümler üretebiliyoruz elbette, fakat çözümler içerisinde çok pratik ve hızlı olan ama genelde dikkate alınmayan ADO yöntemini elimden geldiğince anlatmaya çalışacağım.

Öncelikle ADO'nun tanımı ile başlamakta fayda görüyorum;
ActiveX Data Object olarak adlandırdığımız VERİ NESNESİ'dir. Peki nedir bu veri nesnesi? Veri kaynağı ile kullandığımız arayüz arasında iletişimi kuran ve veri akışını sağlayan nesne olarak tanımlayabiliriz.

ADO nesnesini, vbe references penceresinden kullanıma açabiliyoruz;
References.jpg


ADO'yu kullanırken en sade hali ile 2 (iki) temel nesneye başvururuz.
Bunlardan bir tanesi "ADODB.Connection" nesnesidir.
Bir diğeri ise "ADODB.Recordset" nesnesidir.

Connection nesnesi adı üstünde veri kaynağımız ile bağlantı kurmamızı, iletişime geçmemizi sağlayan nesnedir.
Bir çok özellik, yordam içeriyor olmasına rağmen temelde işimize yarayacak özellik "ConnectionString" olacak.
Yine yordamlar içerisinde Open, Close yordamlarını sık sık kullanıyor olacağız.

Öncelikle connection nesnesinin değişken olarak tanımlama yöntemleri ile başlayalım. Bu yöntemler early binding ve late binding olarak ikiye ayrılır.

EarlyBindingLateBinding.jpg

ekran görüntüsünde de anlaşılacağı gibi early binding yönteminde dim tanımlaması yaparken nesnemizi oluşturmuş oluyoruz. Late binding yönteminde ise nesnemiz daha sonraki satır içinde set ile tanımlanmaktadır.

Late binding yönteminde ayrıca değişkenimiz önce object olarak tanımlanıp daha sonra CreateObject() ile de tanımlanabilir. Örnek;
Dim conn as Object
Set conn = CreateObject("ADODB.Connection")

aynı şeyler Recordset nesnemizi tanımlamak için de geçerli olacaktır.

(Bu süreçten sonra connection nesnemizden con olarak bahsedeceğim.)
nesnemizi tanımladıktan sonra sıra bağlantımızı açma ve kapamaya geldi. veritabanı ile bağlantı kurabilmek için kullanacağımız yöntem
con.open şeklinde olacaktır. Bağlantıyı gerçekleştirip yapmamız gereken işlemleri yaptıktan sonra ise con.close ile bağlantıyı kapatmamız gerekiyor.

con.open yönteminde ConnectionString parametresi ile veritabanı sağlayıcımızı, veri yolumuzu, güvenlik gibi bilgilerimizi tanımlamış olmamız gerekiyor. Bu tanımlamalarda herhangi bir hata yapmamız nesnemizin veri kaynağımıza bağlanamaması ile sonuçlanacaktır.

ConnectionString özelliğini önceden tanımlayabileceğimiz gibi bağlantı sırasında da tanımlayabiliyoruz.
Örnek olarak;
'bağlantı dizesini önceden tanımlama yöntemi
con.ConnectionString = "Bağlantı dizemiz"
con.open


'bağlantı dizesini bağlanırken tanımlama yöntemi
con.open "Bağlantı dizemiz"

Peki oldukça uzun olan bağlantı dizemizi ezberlememiz mi gerekiyor? Hayır. bunun için connectionstrings sitesinden bize uygun olan bağlantı dizesini bulup kopyalayabiliriz. Kopyaladığımız bağlantı içindeki veri yolunu kendi veritabanımıza göre düzenlememiz gerekir.

Önemli Not: anlatım sırasında örnekler, dosyalar paylaşacağım. Paylaştığım örneklerden kendi sistemime uygun bağlantı dizeleri gerçekleştireceğim. İnternette bulduğum örnek verisetleri üzerinde işlemler yapacağım.

Kaynaklar:
Verisetleri için başvurduğum kaynak
Kaynağım içerisinden örnek olarak kullandığım verisetleri; FoodSales, WorkOrders, Orders, InsurancePolicy olacaktır. Benimle birlikte bu örnekleri gerçekleştirmek isteyenlerin bu tabloları sisteminde hazır bulundurmalarında fayda vardır.

İlk konumu burada tamamlıyorum. Konunun devamını vakit buldukça "AYNI BAŞLIK" altında devam ettireceğim. Yaptığımız bu başlangıcın üzerine kata kata gideceğiz diye umuyorum.

Konuyu tamamlamadan önce veritabanımıza ilk erişimimizi yapalım ve öyle kapatalım.

İlk olarak FoodSales veritabanına erişelim. Benim FoodSales veritabamınım konumu "D:\VBA\ADO" şeklinde olduğu için ben bağlantı dizelerimde bu yolu kullanacağım.

Veritabanına bağlantı kodu;

CSS:
Private Sub ADOConnectionTest()
'www.excelcozum.com

    'Değişken tanımlamalarımız
    Dim con As New ADODB.Connection
    Dim ConStr As String
    
    'string türündeki bağlantı dizemizi tanımlama
    ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\VBA\ADO\FoodSales.xlsx;Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
    
    'veritabanına erişim sağlamak için bağlantıyı açıyoruz.
    con.Open ConStr
    
    'veritabanı ile ilgili işlemler con.open ve con.close kodları arasında gerçekleştirilecek ilerleyen zamanlarda.
    
    
    'veritabanı ile işimizi bitirdikten sonra con.close ile veritabanımıza veda ediyoruz.
    con.Close
    
End Sub
 
ADO nesnemiz kapalı excel dosyamızı veritabanı olarak kullanacağı için bir takım kurallara riayet etmemiz gerekiyor. Bu konuda en çok dikkat etmeniz gereken konu ise veritabanı normalizasyonu olacaktır.
En temelde iki farklı amaca hizmet eder; ilk olarak veri tekrarının önüne geçmek, ikinci olarak ise veri tutarlılığına zorlamak.

Her sayfa ADO için bir tablo niteliği taşımaktadır. Sayfa içerisindeki her bir satır recordset (kayıtseti), her bir sütun ise field (alan) olarak tanımlanmaktadır.
Verilerimizin normalizasyon kuralına uyması için her bir alanın bir veri türüne ayrılmış olması elzemdir. Yanlış ve Doğru kullanım için örnek verecek olursak;
YanlışAlanKullanımı.jpg
Her bir alan (sütun) bir veri türüne ayrılmış durumdadır. Bu veri türleri metin, sayı, para birimi, tarih gibi türler içerir. Üstteki resimde görüldüğü gibi 2. 3. ve 4. kayıt setlerinde OrderDate alanı veri normalizasyonu kuralımıza uymamaktadır. Tarih için ayrılmış alanımıza metin veri türünde değerler girilmiştir ve veritabanı işlemlerimizde hatalı sonuçlar almamıza yol açacaktır.
Doğru kullanım için;
DoğruAlanKullanımı.jpg
2. paylaştığım resimde ise verilerimiz doğru alanlara doğru şekilde girilmiştir.
Her bir alanın bir veri türüne ayrılması veri tutarlılığına zorlama amacına hizmet eder.

Ayrıca veritabanı yönetiminde tablolarımız primary key (birincil anahtar), foreign key (ikincil anahtar) ve unique key (benzersiz anahtar) anahtar alanlar içerebilir. Kullandığımız bir çok tabloda bu anahtarlara ihtiyacımız olacaktır.

Primary Key = Her kayıt için bir kimlik numarası niteliğinde benzersiz (birden fazla kayıt setinde tekrar etmeyen) değerler alabilir. Genel olarak 1 den başlayarak devam eden ardışık sayı değerleri alabildiği gibi benzersiz metin değerleri de alabilmektedir.

Primary Key için her bir vatandaşın sahip olduğu T.C. Kimlik Numaraları örnek olarak verilebilir.

Foreign Key = Kullanıldığı tabloda birden fazla kullanıma izin verebilen anahtardır. Bir başka tablo içindeki Primary Keyi referans alır. İlişkisel veritabanlarında tablolar arası ilişki kurmak için kullanılır.

Foreign Key için örnek olarak;
Elimizde SatisTemsilcisi adında bir tablo ve bir de Satislar adında bir tablo olsun. Herhangi bir satış temsilcisinin birincil anahtarı, temsilcimiz bir çok satış yapacağı için satış tablosundan birden fazla geçebilir. Satış tablosundaki her bir kaydı satış temsilcimiz ile ilişkilendirmiş oluyoruz.

Veritabanı normalizasyonu konusuna çok küçük de olsa bir giriş yaptık ve bundan sonraki konumuzda artık veritabanından veri getirmeyi öğrenmiş olacağız.
 
Şimdiye kadar anlatılanlar arasından anlaşılmayan konular olmuştur, bunu aşmak için biraz zamana ve sabıra ihtiyacımız var. Konular ilerledikçe bu problemi çözmüş olacağız.

Şimdiye kadar bağlantı oluşturmayı ve veritabanı normalizasyonu konularına değildik, bundan sonrası için ise SQL (Structured Query Language) Türkçesi ile (Yapılsal Sorgulama Dili) diline ihtiyacımız olacak.

Haydaaa VBA ile başa çıkamıyoruz nerden çıktı şimdi bu SQL dili? Demediğinizi varsayarak küçük bir giriş yapıyorum;
Sql sorgularında temel bir kaç sorgu türü vardır bunlar seçme sorguları, ekleme sorguları, silme sorguları ve güncelleme sorgularıdır.

Seçme sorguları SELECT ile, ekleme sorguları INSERT INTO ile, silme sorguları DELETE ile ve son olarak güncelleme sorguları UPDATE ile ifade edilir.

Son olarak veriler ile çalışmaya başlamadan önce değinmemiz gereken bir konu daha mevcut. Bu konuya kısaca bir değindikten sonra bir sonraki gönderide artık verilerle çalışmaya başlıyor olacağız. Ayrıca konunun girizgahı biraz sıkmış olabilir, uzun sürmüş olabilir ama konuyu sağlam temellere oturtmak açısından bu biraz gerekli bir durum malesef.

Recordset nesnemizden bahsetmiştik. Recordset nesnemiz de con nesnemiz gibi Open, Close yordamları ile çalıştırılır genelde. con nesnemizde nasıl connectionstring parametresine ihtiyaç duymuşsak rs (bundan sonrası için recordsetten rs olarak bahsedeceğim) nesnemizde de query yani sorgu parametresine ihtiyaç duyarız. İhtiyacımıza göre hazırlamış olduğumuz sorgumuzu rs.open yordamında kullanarak kayıtsetimize ne yapmaya çalıştığımızı anlatmış oluyoruz bir nevi.
con nesnesinden farklı olarak rs nesnemizde cursortype ve locktype parametrelerine de ihtiyaç duyuyoruz. Kısaca değinecek olursak.

CursorType:
adOpenForwardOnly=
Varsayılan olarak kullanılan cursordur. Yalnızca ileriye dönük işlem yapabilirsiniz. Bir kayıt kümesinde yalnızca ileriye dönük bir işlem yapma ihtiyacımız olduğunda performans açısında daha kullanışlı bir cursortype dır.

adOpenKeyset= Kayıtlar üzerinde ileri ve geri hareket edebilen cursordur fakat diğer kullanıcıların yaptığı değişiklikleri görmemizi sağlar, aynı zamanda yerel bir kopya üzerinde işlem yaptığımız için veriler üzerinde değişiklik yapamayız.

adOpenDynamic= Kayıtseti üzerinde herhangi bir değişiklik yapıldığında (yapılan değişikliği hangi kullanıcının yaptığından bağımsız olarak) yapılan değişikliğe anında erişim gerektiren durumlarda kullanılır. Birden çok kullanıcının vertabanına aynı anda işlem yapması gerektiği durumlarda kullanılır.

adOpenStatic= Veritabanı üzerindeki kayıtların statik bir kopyasını oluşturur ve daha önceki

LockType:
adLockReadOnly=
Veri üzerinde sadece okuma yapmaya izin verir.

adLockPessimistic= Güncelleme gerçekleştikten sonra kayıt kilitlenir.

adLockOptimistic= Sadece güncelleme sırasında kayıt kilitlenir.

Evet böylece anlaşılmayan, soyut kalan teknik terimlerden kurtulmuş oluyoruz. Bir sonraki anlatımlarımızda veriler üzerinde çalışmaya başlayacağız.
 
Artık ilk verimizi çekmenin zamanı geldi.
Şimdiye kadar öğrendiklerimize istinaden verileri görüntülemek istediğimiz excel dosyasında kullanacağımız kod yapısı aşağı yukarı aşağıdaki şekilde görünecektir.


CSS:
Private Sub ADOSelectTest1()

    'connection nesne tanımı
    Dim con As New ADODB.Connection
    'recordset nesne tanımı
    Dim rs As New ADODB.Recordset
    'sorgu ifadesinin string türünden tanımı
    Dim query As String
    'bağlantı dizesi ifadesinin string türünden tanımı
    Dim ConStr As String
    
    'bağlantı dizesi için gerekli olan ifadenin değişkene aktarılması. (buradaki data source özelliğini kendi veri yolunuza göre düzenleyebilirsiniz
    ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\VBA\ADO\FoodSales.xlsx;Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
    
    'veritabanı ile bağlantı kuruyoruz.
    con.Open ConStr
    
    'sorgu ifademizi tanımlıyoruz. burada SELECT, INSERT INTO, UPDATE gibi ifadeler yer alıyor.
    query = ""
    
    'sorgu ifademizi veritabanı üzerinde çalıştırıyoruz. ve (eğer varsa) sonuçları getiriyoruz.
    rs.Open query, con, adOpenKeyset, adLockPessimistic
    
    '--------------------------------------------------------------------------------------------------------------------------------------
    'bu alanda recordset ile getirdiğimiz veriler üzerinde işlemler yapıyoruz.
    '--------------------------------------------------------------------------------------------------------------------------------------
    'veritabanı bağlantımızı kapatıyoruz.
    con.Close
    
    'veritabanı ile ilişkili nesnelerimizle işimiz bittiğinde nothing olarak düzenlemek (bazı durumlarda) performans yönünden işimize etki edeceğinden
    'bu nesneleri de son olarak nothing olarak tanımlıyoruz.
    Set rs = Nothing
    Set con = Nothing
    
End Sub

genel yapımız bu şekilde görünecek.

Şimdi SQL ifadelerine kısa bir göz attıktan sonra ilk sorgumuzu çalıştıralım. Örnek olarak veritabanımızdaki FoodSales tablosunda bulunan bütün kayıtları getirme ile başlayalım. (Bütün alanları ve bütün kayıtları getirme ile başlayalım)

Kod:
Seçme sorgusu yapısı
SELECT [SEÇİLECEK ALANLAR] FROM [SEÇİLECEK TABLO]


query değişkenine atayacağımız seçme sorgusu;
Kod:
'bütün alanları seçeceğimiz sorgu.
"SELECT OrderDate, Region, City, Category, Product, Quantity, UnitPrice, TotalPrice FROM [FoodSales$]"
'sql sorgularında tabloda bulunan bütün alanları seçmek istediğimizde ise bütün alanların adını yazmak yerine * ifadesi kullanabiliriz.
SELECT * FROM [FoodSales$]

Şimdi gelin bu sorguyu uygulayıp aktif çalışma sayfamıza verileri getirelim.

Kod:
Private Sub ADOSelectTest1()

    'connection nesne tanımı
    Dim con As New ADODB.Connection
    'recordset nesne tanımı
    Dim rs As New ADODB.Recordset
    'sorgu ifadesinin string türünden tanımı
    Dim query As String
    'bağlantı dizesi ifadesinin string türünden tanımı
    Dim ConStr As String
    
    'bağlantı dizesi için gerekli olan ifadenin değişkene aktarılması. (buradaki data source özelliğini kendi veri yolunuza göre düzenleyebilirsiniz
    ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\VBA\ADO\FoodSales.xlsx;Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
    
    'veritabanı ile bağlantı kuruyoruz.
    con.Open ConStr
    
    'sorgu ifademizi tanımlıyoruz. burada SELECT, INSERT INTO, UPDATE gibi ifadeler yer alıyor.
    query = "SELECT * FROM [FoodSales$]"
    
    'sorgu ifademizi veritabanı üzerinde çalıştırıyoruz. ve (eğer varsa) sonuçları getiriyoruz.
    rs.Open query, con, adOpenKeyset, adLockPessimistic
    
    Worksheets("Sayfa1").Range("A2").CopyFromRecordset rs
    
    'veritabanı bağlantımızı kapatıyoruz.
    con.Close
    
    'veritabanı ile ilişkili nesnelerimizle işimiz bittiğinde nothing olarak düzenlemek (bazı durumlarda) performans yönünden işimize etki edeceğinden
    'bu nesneleri de son olarak nothing olarak tanımlıyoruz.
    Set rs = Nothing
    Set con = Nothing
    
End Sub

Bu kodu uyguladığımızda görebiliyoruz ki veritabanı olarak kullandığımız excelin açık olmasına gerek kalmadan bize gereken verileri alabiliyoruz.

Aktif çalışma sayfamızda A2 hücresinden itibaren sola ve aşağıya doğru bütün verilerimizi getirebildik.
 
Ellerinize sağlık. Oldukça güzel hazırlanmış emek verilmiş doyurucu bilgi içeren bir yazı. Teşekkürler
 
SELECT Sorgularında elbette tek yapabildiğimiz bütün kayıtları getirmek değil. Bu sorgu ile kendi belirlediğimiz kriterlere göre kayıtları filtreleyerek getirebiliyoruz.

Bu kriter belirlemeyi sorgu içerisinde WHERE ile gerçekleştiriyoruz. Bunun için WHERE tek başına yeterli olmadığı için WHERE deyimi ile birlikte "<", ">", "=", "IS NULL", "IS NOT NULL" gibi mantıksal operatörlere de ihtiyacımız var.

Şimdi gelin bir önceki örnekte yazmış olduğumuz
Kod:
"SELECT * FROM [FoodSales$]"
Sorgusuna WHERE şartı ekleyelim.

Kod:
SELECT [SEÇİLECEK ALANLAR] FROM [SEÇİM YAPILACAK TABLO] WHERE [ŞART UYGULANACAK ALAN] [MANTIKSAL OPERATÖR] [ŞART]
Yukarıda gördüğünüz mantıkta WHERE şartımızı kuralım. Bunun için Region alanını ve = operatörünü kullanalım.

Kod:
SELECT * FROM [FoodSales$] WHERE Region = 'West'
Region alanı "West" e eşit olanları filtreleyerek kayıt setimizin içine alacağız.

Bu bilgiler ışığında daha önce yazmış olduğumuz kod içerisinde sadece query değişkeni üzerinde değişiklik yapmamız yeterlidir.


Kod:
Public Sub ADOSelectTest2()

    Dim con As New ADODB.Connection
    Dim rs As New ADODB.Recordset
    Dim query As String
    Dim ConStr As String
    
    ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\VBA\ADO\FoodSales.xlsx;Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
    con.Open ConStr

    query = "SELECT * FROM [FoodSales$] WHERE Region = 'West'"
    
    rs.Open query, con, adOpenKeyset, adLockPessimistic
    
    UserForm1.ListBox1.Clear
    UserForm1.ListBox1.ColumnCount = rs.Fields.Count
    UserForm1.ListBox1.Column = rs.GetRows

    con.Close
    
    Set rs = Nothing
    Set con = Nothing
    
End Sub

Bir önceki kodun aksine kalabalık görünümü azaltmak için yorum satırlarını kaldırdım. Artık kodlarımızın hangisinin ne işe yaradığını biliyoruz. Ve bu paylaştığım kodu içeren çalışma kitabı ile Veritabanını dosya olarak paylaşacağım.
 

Ekli dosyalar

Bir önceki mesajımda paylaştığım dosyada Module1 üzerinde düzenleme yapıyoruz, sonuç almayı userform üzerindeki listbox üzerinde yapıyoruz.

Module1 üzerinde hazırlayacağımız kodların listesi userform üzerindeki combobox listesinde çıkacaktır. Bu combobox listesinden hazırladığımız kodları seçip sonuçlarını görüntüleyebiliriz.

Evet WHERE şartına devam edebilriz. Bir önceki derste bahsetmeyi unuttuğum bir konu var, hemen onunla başlayalım. WHERE şartında metin araması yaparken metnimizi ' (tek tırnak) işaretleri arasına yazmak durumundayız. Rakamsal değerler için buna ihtiyacımız yok.

Evet şartımızı göz önünde bulundurarak sorgumuzu yazdık ve sorgumuz bize doğru sonuçları getirdi. Peki bizim her zaman tek bir şartımız mı olacak? Birden fazla şartımız olması durumunda ne yapacağız? Bunun için WHERE şartı içinde AND operatörü ya da OR operatörünü kullanıyoruz.

Önemli Not: Yazdığım sorguları burada numaralandırıyorum. Paylaşacağım dosyadaki kodları da sorgularla aynı numara yapacağım, ve böylece hangi sorguyu nerede arayacağınızı bileceksiniz.

Şimdi FoodSales veritabanımızdan Region'u West olan ve Category'si Cookies olan verilerimizi getirelim. Bunun için Sorgumuz aşağıdaki gibi olacaktır.
No:1:
Kod:
SELECT * FROM [FoodSales$] WHERE Region ='West' AND Category='Cookies'

Evet iki şartımızın arasına AND operatörü koyarak elimizdeki tek kiriteri ikiye çıkarmış oluyoruz.


Şimdiki şartımızda ise Region'u yine West seçelim fakat diğer şartımıza da Quantity'nin 100 üzerinde olması olsun. Fakat verimizi getirmesi için ilk şarttan ya da ikinci şarttan herhangi birini yerine getiriyor olması yeterli olsun.

No:2:
Kod:
SELECT * FROM [FoodSales$] WHERE Region = 'West' OR Quantity>100
Daha önce hep = operatörü ile iş yapıyor iken şimdi büyüktür operatörünü görüyoruz. Bu operatör tek başına kullanıldığı gibi aynı zamanda ">=" ve "<=" şeklinde de kullanılabilir. Anlamları ise "Büyük Eşittir", "Küçük Eşittir"i temsil etmektedir.

Son olarak LIKE operatöründen den bahsederek konuya şimdilik son verelim. Metinsel ifadelerde şimdiye kadar hep = operatörünü kullandık fakat metinsel ifadelerde şartımız bazen metnin tamamı olduğu gibi bazen de metnin bir kısmı olabiliyor. Bunu gerçekleştirebilmek için LIKE operatörü ve yanında metinsel operatörleri kullanıyoruz.

Metinsel operatörler için temelde "%" ve "_" operatörleri kullanılır. Söz konusu operatörler ile ilgili bir kaç örnek sunmak gerekirse;
No:3:
Kod:
SELECT * FROM [FoodSales$] WHERE Category LIKE 'C%'
% işareti kendisinden sonra gelen herhangi bir değeri filtremize dahil eder. Yani yukarıdaki sorgumuz Category alanındaki değerin C ile başlamasına dikkat edecek ve geri kalan değerlerin ne olduğuna dikkat etmeyecek.

No:4:
Kod:
SELECT * FROM [FoodSales$] WHERE Product LIKE '%an%'
Yukarıdaki sorgumuz ise Product alanında kelime içerisinde herhangi bir yerde geçen "an" metinlerine dikkat edecek ve sadece söz konusu kayıtları getirecek.

No:5:
Kod:
SELECT * FROM [FoodSales$] WHERE Product LIKE '__an%'
"_" operatörü de "%" operatörü gibi harfin ne olduğuna bakmıyor fakat tek fark olarak tek bir karakter için bunu gerçekleştiriyor.
yani yukarıdaki sorgumuz 1. ve 2. harfinin karakterin ne olduğu önemli değil şartı , 3. ve 4. harfi "an "olsun şartı ve yine kelimenin geri kalanı ne kadar uzun olursa olsun, hangi karakter olursa olsun şartı getirir.

Anlatımlarla ilgili yaptığım çalışmayı dosya olarak paylaşıyorum. "%" ve "_" ile ilgili örnekleri deneme yanılma yolu ile dilediğiniz kadar çoğaltabilirsiniz. Zira en iyi öğrenme yolu (bana göre) deneme yanılma yoludur.
 

Ekli dosyalar

Şimdiye kadar SELECT ve WHERE sorgu ifadelerine göz attık. Biraz da kendi denemelerinizle konuyu biraz daha pekiştirdiğinizi düşünüyorum. Herhangi bir deneme için kurmuş olduğunuz sorgu ifadeleri çalışmadığında "ben yapamıyorum", "sorgu ifadesi kuramıyorum" gibi ümitsizliğe kapılmayın. Günlerce üzerinde çalışmış olmama rağmen ben de bir çok defa hatalar yaptım ve hala yapıyorum, fakat öğrenmek için yine de vazgeçmedim. Siz de vazgeçmeyin.

Eğer hatalar ile karşılaşıyorsanız ve sormak istediğiniz sorular var ise özel mesaj yolu ile ya da talep olursa "kapalı excel dosyasından veri alma ado soru" adında bir başlık açarak soru sorabilirsiniz.

Şimdi gelelim yeni konularımıza. Excelde bulunan =TOPLA(), =EĞER() işlevleri gibi SQL sorgu dilinde de bir takım fonksiyonlara yer verilmiştir. Bunlardan bazıları SUM, AVG, IIF, ISNULL, CONCAT, MONTH, YEAR gibi excel fonksiyonlarına benzeyen ifadelerdir. Kullanmak istediğimiz formülü uygulamak istediğimiz alanın başına yazarak kullanırız.
No:6
Kod:
SELECT SUM(Quantity) FROM [FoodSales$]
Bu sorgumuz bize sattığımız toplam miktarı vermektedir.

Peki Sattığım ürünlerin tamamını değil de sadece bir kısmını toplamak istersem ne yapmalıyım? Örnek bir sorgu ile konuyu netleştirelim;
no:7
Kod:
SELECT SUM(Quantity) FROM [FoodSales$] WHERE Product ='Carrot'
Belli bir kısım veriyi toplamak için daha önce öğrendiğimiz WHERE ifadesinden yardım alıyoruz. Sorgumuz önce Product alanında Carror değeri olan kayıt setlerini bizim için filtreledi ve filtrelediği değerlerin Qunatity değerlerini topladı. Böylece dilediğimiz alandaki rakamları toplamış olduk.

Yine Toplama işlemimizde Bir ifade için filtre yapabilmenin yanında birden fazla ifade için de filtre yapabiliriz.


no:8
Kod:
SELECT SUM(Quantity) FROM [FoodSales$] WHERE Product ='Carrot' OR Product = 'Bran'
Bu sorgumuzda Carrot ve Bran ürünlerinin toplamını aldırabiliyoruz. Bu sorgudan sonra akıllara bir soru gelmiş olabilir. Nedir o soru? Benim aynı alan içinde onlarca kriterim varsa bunlar için tek tek;
Kod:
WHERE Product='Veri' OR Product='Veri2' OR Product='Veri3'
sorgusundaki gibi arka arkaya OR kullanmam mı gerekir? Bu sorunun cevabı tabiki hayır olacaktır. Bu tür durumlar için IN ifadesine başvuruyoruz.

no:9
Kod:
SELECT SUM(Quantity) FROM [FoodSales$] WHERE Product IN ('Carrot', 'Bran')
Koşul ifademizden sonra alan adımızı kullanıyoruz. Ardından IN ifadesini kullandıktan sonra parantezi içinde aralarında virgül olacak şekilde değerlerimizi yazıyoruz.
9. ve 8. sorguları çalıştırdığımızda aralarında herhangi bir fark göremeyeceksiniz.

Son iki sorgumuzda Carrot ve Bran ürünlerinin toplamını tek bir veri içerisinde gördük. Her iki ürünün de toplamlarını farklı verisetleri içerisinde görmek istersek yeni bir sorgu ifadesine göz atmamız gerekecek. Yeni sorgu ifademiz GROUP BY bkz;

no10:
Kod:
SELECT Product, SUM(Quantity) FROM [FoodSales$] WHERE Product IN ('Carrot', 'Bran') GROUP BY Product
SUM() AVG() gibi formülleri tek bir alan seçerek kullandığımızda formüllerimiz sorunsuz çalışacaktır. Fakat SUM() işlemini yaptığımız alan dışında farklı alanlar seçtiğimizde SUM() ifadesi bize "toplam alayım ama hangi kritere göre toplam alayım" diyerek biraz bozulabilir. Dolayısıyla biz kullandığımız SUM() fonksiyonuna hangi kritere göre toplama yapacağını GROUP BY ifadesi ile söylüyoruz. Söz konusu ifade kendinden sonra gelen alan ad(lar)ına göre verilerimizi gruplayacaktır.

GROUP BY ifademizle bir alana göre gruplandırma uygulayabileceğimiz gibi birden fazla alana göre de gruplandırma uygulayabiliriz. Bkz;
no:11
Kod:
SELECT Region, Product, SUM(Quantity) FROM [FoodSales$] WHERE Product IN ('Carrot', 'Bran') GROUP BY Region, Product

10 no lu sorgumuzdan farklı olarak alan seçimimize Region alanını da dahil ederek toplam aldırdık. Fonksiyon kullandığımız bir sorguda Fonksiyon içermeyen bütün alanları GROUP BY içine dahil etmek ZORUNDAYIZ.

Yanlış kullanıma bir örnek;
Kod:
SELECT Region, Product, SUM(Quantity) FROM [FoodSales$] WHERE Product IN ('Carrot', 'Bran') GROUP BY Product
Bu ifademiz bize herhangi bir veri döndürmeyecektir. Hatta rs ifademiz açılmayacaktır.

GROUP BY ifadesindeki sıralamanın yaptığımız sorguda ne gibi değişikliklere yol açacak hadi bir de ona göz atalım;
no:12
Kod:
SELECT Region, Product, SUM(Quantity) FROM [FoodSales$] WHERE Product IN ('Carrot', 'Bran') GROUP BY Product, Region
Bir önceki ifademizde önce Region sonra Product alanlarını gruplandırma yapmıştık. Şimdi ise Önce Product sonra Region alanını gruplandırma yaptık. Bu sorgumuzda neye yol açtı?
İlk sorgumuz önce region değerlerini aldı ve regionlara göre product toplamlarını aldı, ikinci sorgumuz ise önce product alanlarını aldı ve product alanlarına göre region toplamlarını aldı. Bu ayrım hangisine göre sıralama yapacağımızı değiştirdi.

Sıralama demişken bu gönderimizde ORDER BY ifadesine değinmeden geçmeyelim. ORDER BY ifadesi sorgularımızda verilerimizi küçükten büyüğe, büyükten küçüğe sıralama yapacağı gibi A dan Z ye, Z den A ya sıralama yapabilmektedir.

no:13
Kod:
SELECT Product, SUM(Quantity) FROM [FoodSales$] GROUP BY Product ORDER BY Product ASC;

ORDER BY kullanırken ASC ve DESC ifadeleri karşımıza çıkar. ASC ifadesi küçükten büyüğe (A dan Z ye) DESC büyükten küçüğe (Z den A ya) sıralama yapar. fonksiyon ve GROUP BY kullandığımız ifadelerde ORDER BY kullanmasak da default olarak ASC olarak sıralayacaktır.

Kişisel Not: ADO bize performans sunmanın yanında veriler üzerinde kolaylıkla çalışmamızda da yardımcı oluyor. Şimdiye kadar paylaştığım dosyaların içindeki kodlara bakacak olursanız, birbirinin aynı kodlar içerisinde sadece sorgu ifadelerini değiştirerek bir çok farklı veriyi listeleme şansı elde ettik. Kişisel kanaatime göre ADO yu kullanmaktan ve öğrenmekten geri kalmayın. Elbette her projenin içine ADO yu sokuşturmak zorunda değiliz ama bir çok veri takibinde işimize fazlasıyla yarayabileceği aşikardır. Bu konuyu da burada bitiriyorum. Yeni sorgu ifadeleri ile yeni derslerde görüşmek üzere.

Son Not: Daha önce FoodSales verilerini içeren dosyayı paylaştığım için bu seferki mesajımda sadece Çalışma Sayfası dosyasını paylaşıyorum. Daha önce FoodSales verilerini içeren dosyayı indirmemiş olanlar önceki mesajımdaki zip dosyasına göz atabilirler.
 

Ekli dosyalar

Son düzenleme:
Şimdiye kadar epey ilerlememize rağmen biraz geriye dönüp; veri, veritabanı ve ilişkisel veritabanı gibi terimler üzerinde biraz durmak istiyorum. Çünkü ne kadar güzel bir kodlama yaparsak yapalım, ne kadar güzel sorgular yazarsak yazalım yaptığımız işin en başında kullanacağımız veritabanını doğru tasarlamazsak mutlaka bir yerlerde bu hatamız karşımıza ciddi sorunlar olarak çıkacaktır.

Konu başlığının "kapalı excel dosyasından veri alma" olduğuna bakmayın. Bu yöntemle SQL Server, Access, Azure DB vb. veritabanlarından veri alabiliyoruz. Hatta txt uzantılı text dosyalarını bile okuyabiliyoruz.

Veri Nedir?
wiki bize veriyi aşağıdaki gibi açıklamaktadır.

Kod:
Veri (İng. ve Lat. datum; ç. data), ham (işlenmemiş) gerçek enformasyon parçacığına verilen addır.[1] Veriler ölçüm, sayım, deney, gözlem ya da araştırma yolu ile elde edilmektedir. Ölçüm ya da sayım yolu ile toplanan ve sayısal bir değer bildiren veriler nicel veriler, sayısal bir değer bildirmeyen veriler de nitel veriler olarak adlandırılmaktadır. Her sembolik gösterim gibi, veri de belirli bir nesne, birey ya da olguya ilişkin bir soyutlamadır. Ancak enformasyon ve bilginin soyutluk düzeyleri ile karşılaştırıldığında, verilerin soyutluk düzeyi daha düşüktür. Bir verinin tek başına bir anlamı ve işlevi bulunmamaktadır. Veriler toplandıktan sonra gruplanarak, sıralanarak ve özetlenerek, elle ya da bilgisayarla işlenip enformasyona dönüştürüldüklerinde anlam kazanmakta; ait oldukları bağlamı açıklama gücüne kavuşmaktadır. Problem çözme ya da karar verme gibi bir amaca hizmet edebilecek duruma gelmektedir.

Açıklamadan da anlaşılacağı gibi veri tek başına herhangi bir şey ifade etmemektedir.
Daha anlaşılır olması açısından "10.03.2021" tarihi tek başına herhangi bir anlam ifade etmiyor. Fakat biz bu verimizi farklı bir veri ile eşleştirirsek biraz daha anlam kazanacaktır. Bu tarihi aşağıdaki gibi bir yapıya çevirirsek biraz daha anlam kazanmaya başlayacaktır;

Kullanıcı AdıKayıt Tarihi
aeGNoR10.03.2021
Yukarı da da görüldüğü gibi 10.03.2021 tarihi kullanıcı kayıt tarihi olarak anlam kazanmış durumdadır. Bu verileri diğer kullanıcıların da kayıt tarihleri ile doldurmaya başladığımızda işte bu verilerimizin tamamı veritabanı yapısına dönüşmektedir.

Veritabanı nedir?
wiki açıklaması ile başlayalım.
Kod:
Veri tabanları birbirleriyle ilişkili bilgilerin depolandığı alanlardır. Bilgi artışıyla birlikte bilgisayarda bilgi depolama ve bilgiye erişim konularında yeni yöntemlere ihtiyaç duyulmuştur. Veri tabanları; büyük miktardaki bilgileri depolamada geleneksel yöntem olan ‘‘dosya-işlem sistemine’’ alternatif olarak geliştirilmiştir. Telefonlarımızdaki kişi rehberi günlük hayatımızda çok basit bir şekilde kullandığımız veri tabanı örneği olarak kabul edilebilir. Bunların dışında internet sitelerindeki üyelik sistemleri, akademik dergilerin ve üniversitelerin tez yönetim sistemleri de veri tabanı kullanımına örnektir. Veri tabanları sayesinde bilgilere ulaşır ve onları düzenleyebiliriz. Veri tabanları genellikle bireysel olarak satın alınamayacak kadar yüksek meblağlara sahip olmasına karşın; ücretsiz kullanıma açılan akademik veri tabanları da bulunmaktadır. Akademik veri tabanları aracılığıyla bazen bibliyografik bilgi bazen de tam metinlere erişmek mümkündür. Veri tabanları, veri tabanı yönetim sistemleri aracılığıyla oluşturulur ve yönetilir. Bu sistemlere; Microsoft Access, MySQL, IBM DB2, Informix, Interbase, Microsoft SQL Server, PostgreSQL, Oracle ve Sysbase örnek olarak verilebilir.

Buradaki temel konumuz veritabanı tablolarında bulunan verilerin birbirleri ile ilişkisinin olmasıdır. Örnek verecek olursak bugün ülke genelindeki yaşanan depremlerin verisi ile telefonumuzdaki kişilerin e-posta bilgileri birbirleri ile ilişkili veriler değildir. Dolayısı ile veritabanımızdaki verilerin birbirleri ile ilişki içinde olması elzem bir konudur.

Burada yaşanabilecek problemlerden bir tanesine örnek verecek olursak;
(Log tutmayan bir veritabanı sisteminde) Bir poliklinik veritabanı tasarlıyoruz diyelim, bu veritabanında "tblHasta" adını verdiğimiz bir tablo olsun. Biz bu tabloda bulunan alanlara en başında "Oluşturma Tarihi" "Oluşturan Kişi" ve "Değiştirme Tarihi" "Değiştiren Kişi" gibi alanlar açmadığımızı varsayalım. Binlerce hasta kaydı bu veritabanına işlendikten sonra hastaların ilk kayıt tarihi ve kaydeden kişi, üzerinde değişiklik yapılma tarihi ve değişiklik yapan kişi bilgilerine erişme ihtiyacı doğarsa karşımıza ciddi bir sorun çıkmış demektir. Bundan sonraki süreç için veritabanımıza bu alanları ekleyebiliriz belki fakat daha önceki kayıtlarda bu bilgilere asla erişemeyiz.

Yukarıda verdiğim örnekte de görüleceği gibi bir veritabanı tasarımında ihtiyacımız olabilecek "her bilgi" mutlaka en ince ayrıntısına kadar düşünülmeli ve veritabanı yapımız (veritabanı şemamız) buna göre şekillenmelidir.

Veri modelleme?
wiki tanımına göz atalım.

Kod:
Veri modelleme, bir işletmenin, kurumun hatırlamaya değer bulduğu verilerin şekil ve metin olarak ifade edilmesidir. Diğer bir deyişle bir işletmede teknik ve teknik olmayan herkesin bilişim ihtiyaçlarını ifade etmeye çalışırken birbirini anlamada kullanabileceği görsel bir iletişim dilidir. Yazılım geliştirmenin en önemli süreçlerinden biri olan veri modelleme bilişim ihtiyaçlarının keşfedilmesi ve herkesin anlayabileceği bir şekilde belgelenmesi işlemidir. Bilişim ihtiyaçları, veriler ve işletme ihtiyaçlarını destekleyen işletme kurallarıdır. Bir veri modeli herhangi bir işletmenin veya bir yazılımın karmaşık bilişim ihtiyaçlarının tümünü yeterince ifade edebilmek için kullanılabilecek bir araçtır. Bir bilişim sistemi başlıca 3 ihtiyacı karşılar; çeşitli verilerin saklanması, işlenmesi ve görüntülenmesi (veya bu amaçla seçilmesi). Görüldüğü gibi bilişim sistemlerinin temelinde veri yer almaktadır. Veri Tabanı sistemleri ise en basit ifadeyle; verinin saklanması ve işlenmesi ile ilgili olarak geliştirilen genel amaçlı çeşitli yazılımlardır. Kısaca bilginin işlenmemiş hali olarak tanımlanan verinin modellenmesi herhangi bir bilişim sistemi geliştirmede neredeyse işin yarısını oluşturur. Verinin gerçek sahibi kullanıcıdır. Durum böyle olunca bilişim sistemlerinin geliştirilmesi sırasında kullanıcı temelli bir yaklaşım önem kazanmaktadır. Kullanıcı yönelimli bu yaklaşımın bazı yararları aşağıda sıralanmaktadır.

Kullanıcıların işin başından itibaren yazılım geliştirme sürecinde yer almaları nedeniyle yeni sisteme ve yeniye karşı olan dirençlerinin azaltılması
Çoğunlukla teknik açıdan olaylara yaklaşan yazılımcıların geliştireceği kurgu veya hayal ürünü veri ihtiyaçlarından kaçınılması
Kullanıcı eksenli geliştirilen sistemde bilişim ihtiyaçlarının daha iyi karşılanabilmesi
Geliştirilecek ürünün işletmede daha kolay benimsenmesi
Geliştirilecek yazılımın daha kısa sürede yazılması ve kalite faktörü
Teknik ayrıntıdan uzak, işletmede herkesin rahatlıkla anlayabileceği ve üzerinden iletişim kurabileceği görsel-grafik sembollerle ifade edilebilen veri modellerinin üretilebilmesi
Bilgisayar Destekli Yazılım Mühendisliği (CASE-Computer Assisted Software Engineering) araçlarıyla bu modeller hızlı şekilde veri tabanı tasarımına dönüştürülebilir
Yazılım geliştirme sürecinde dokümantasyon için çok yararlıdırlar

Oldukça uzun bir tanıma sahip olan veri modelleme bir kaç farklı konuya ayrılmaktadır. Burada sık kullanılan ilişkisel-veritabanı anlatılacaktır.

İlişkisel veritabanı?
her zamanki gibi wiki tanımına bakalım. Bu tanımı burada paylaşmaya lüzum görmüyorum. wiki bağlantısından görebilirsiniz.

Daha önce bahsettiğimiz gibi ilişkisel veritabanlarında veriler tablo şeklinde tutulurlar. Hemen bir örnekle anlatımı somutlaştıralım;
Bir kütüphane veritabanında "tblKitap" adında bir tablomuz var bu tabloda kitabın ISBN kodu, Adı, Yayın Tarihi vb. bilgileri tutuyoruz. Kütüphane envanterinde kayıtlı kitapların okuyuculara belirli bir süreliğine emanet verildiği sürenin sonunda geri alındığını biliyoruz. Biz bu bilgiyi "tblKitap" tablosunda tutmaya çalışırsak son emanete veriliş tarihini ve son emanetten alınış tarihini görebiliriz. Halbuki daha önceki emanete verilme ve alınma tarihlerine de ihtiyaç duyabiliriz. Bunun için "tblEmanet" tablosu oluşturup "tblKitap" tablosu ile ilişkilendirmemiz gerekecektir. (Buradaki örnek konuya özel olduğu için aslında ihtiyaç duyulan bir çok tabloyu dikkate almayacağız)

Screenshot_1.jpg
Yukarıdaki resimde de anlaşılacağı üzere "tblKitap" tablosundaki "ISBN" birincil anahtarımız "tblEmanet" tablosundaki "ISBN" ikincil anahtarımız ile ilişkilendirilmiştir. Böylece kütüphanemizde bulunan kitapları her emanete verdiğimizde yeni kayıt açılacak ve eskiye dönük emanet kayıtlarına erişebilmiş olacağız.
Bu örnekte olması gereken fakat anlatımı sade tutmak için oluşturmadığım bir çok tablo düşünülebilir. Bkz: "tblÜye", "tblPersonel", "tblKutuphane", "tblYayinci", "tblYazar", "tblTur" vb.


Bütün bu anlatımların sonunda anlaşılacağı üzere, daha sonra ihtiyacımız olacak bütün verileri tutmamızın önemli bir mesele olmasının yanında tutacağımız verilerin hangi koşullarda ve nasıl tutulacağı da bir o kadar önemli bir meseledir.

Bu konu benim anlatımımla (ya da bir başkasının) bizzat anlaşılabilecek meseleler olmayabilir. Çeşitli veritabanları tasarlayarak (bkz: "kütüphane", "hastahane", "stok", "muhasebe", "pazarlama", "satış" vb. ) ve tasarlanan bu veritabanları üzerinde kodlamalarla çalışmalar yürüterek anlaşılabilecektir.

Yine kişisel not: İyi bir anlatıcı olmadığımın farkındayım, dolayısıyla anlatımım konusunda eleştirilerinize her daim açığım. Buradaki maksadımızın sizlerin daha iyi anlaması olduğunu unutmayın.
 
Sorgulara verdiğimiz kısa bir aradan sonra tekrar devam ediyoruz.

SQL Sorgularında bulunan bütün fonksiyonları anlatmak oldukça uzun süreceği için üzerinde bir kaç tanesi ile çalışmak istiyorum sadece.
Şimdiye kadar SUM üzerinde çalıştık. Bundan sonrası için bir kaç farklı sorgu paylaşıp, paylaştığım sorgular altında sorgularımızın ne işe yaradıkları hakkında kısa kısa bilgiler vereceğim.

no:14
Kod:
SELECT COUNT(*) FROM [FoodSales$]
COUNT fonksiyonu ile ilk adımımızı atalım. COUNT fonksiyonu kelime anlamı itibariyle de (saymak,miktar) anlamına geliyor zaten. Yukarıda yazdığımız kod ise bize FoodSales tablosundaki verilerin sayısını vermektedir. Parantez içinde * kullanabileceğimiz gibi herhangi bir alan adını da yazsaydık sonuç bizim için değişmeyecekti.

no:15
Kod:
SELECT COUNT(*) FROM [FoodSales$] WHERE Region='West'
SUM fonksiyonunda kullandığımıza benzer şekilde, COUNT fonksiyonumuza da WHERE koşulları ekleyerek sadece belirli değerleri içeren kayıtları saydırabiliriz. Bu sorgumuzda Region değeri West olan kayıtlarımızın sayılarını bulmaya çalıştık.

Şimdiye kadar SUM sorgumuzda pek çok koşul ifadesine yer verdiğimiz için bundan sonra öğreneceğimiz COUNT sorgusunda hepsine tek tek değinmeyeceğim. Benzer şekilde sorgu kurulduğu için. Sadece günlük hayatta işimize yaraya bileceğini düşündüğüm bir kaç şeklini paylaşacağım sizlerle.

no:16
Kod:
SELECT Product, COUNT(Quantity) FROM [FoodSales$] WHERE Quantity>100 GROUP BY Product ORDER BY COUNT(Quantity) DESC

SUM konusunu anlatırken değinmediğim bir konu burada gözünüze çarpmış olabilir. SUM konusunu anlatırken ORDER BY ile sıraladığımız bütün sorgularda sıralama ölçütümüz hep fonksiyon kullanılmayan alanlardı. Şimdi ise fonksiyon uyguladığımız alan üzerinde ORDER BY uyguluyoruz. Herhangi bir şekilde SUM() AVG() COUNT() gibi fonksiyonları kullandığımız alanlara göre sıralama yapacaksak aynı fonksiyonu ORDER BY ifadesinden sonra da kullanmamız gerekir. Yazmış olduğumuz bu sorgu tam olarak "hangi üründen kaç defa 100 adetin üzerinde satış yaptık?" sorusunun cevabıdır.

no17:
Kod:
SELECT Product, COUNT(Quantity) FROM [FoodSales$] WHERE Quantity>100 GROUP BY Product ORDER BY COUNT(Quantity) DESC, Product ASC;
16. sorguda gördüğümüz ORDER BY içerisinde fonksiyon kullanmak zorunluluğunu öğrendikten sonra öğrenmemiz gereken konulardan biri ise sıralamanın sadece tek bir alana göre değil, birden çok alana göre de yapılabildiğidir. Sorgumuz birden fazla alana göre sıralama yapacak fakat önce hangi alanı dikkate alarak sıralama yapacak? Buradaki ayrım ise ORDER BY dan sonra kullanılan alan isimlerinin sıralamasında önemli bir hal alıyor. Hangi alanı diğer(ler)inden önce sıralamasını istiyorsanız o alanı diğer(ler)ine göre ORDER BY ifadesine daha yakın tutmalısınız. Ayrıca sıralama yapacağınız her alan için ASC ve DESC ifadelerini kullanmanız istediğiniz veri setine daha doğru şekilde ulaşmanıza yardımcı olacaktır.

18. sorgu ile birlikte toplama, sayma gibi fonksiyonların dışına çıkarak biraz daha farklı sorgular üzerinde çalışalım.
no18:
Kod:
SELECT Region + ' - ' + City, TotalPrice FROM [FoodSales$]
Bu sorgumuzda HESAPLANMIŞ ALAN kullandık. Nedir bu hesaplanmış alan? Veritabanımızda bulunan tabloda Region ve City değerlerini tek bir alanda gösteren bir alanımız olmamasına rağmen, böyle bir şeye ihtiyacımız olduğunda iki alanı birleştirerek kullandık. İki alanı birleştirmek için kullanacağımız ifade ise + ifadesidir.
NOT: + ifadesi string değer içeren alanları birleştirmek için kullanılırken sayısal değer içeren iki farklı alanda kullanıldığında TOPLAMA işlemi yapacaktır.

Hadi gelin biraz daha karmaşık hesaplanmış alan sorgusu yapalım.
no19:
Kod:
SELECT Product, TotalPrice, TotalPrice * 0.08, ((TotalPrice) + (TotalPrice * 0.08)) FROM [FoodSales$]
Bu sorgumuz ile birlikte biraz daha karmaşık olan sorgulara geçmişiz gibi görünüyor. Yazılışı biraz daha karmaşık gibi görünebilir fakat bu gözünüzü korkutmasın. Sorgumuzu parça parça ele alırsak aslında ne kadar da basit bir sorgu yazdığımız ortaya çıkacaktır.
Peki başlıyoruz, bu sorgumuzda biz ne yaptık?
1. alanda Product alanımızı seçtik
2. alanda TotalPrice alanımızı seçtik
3. alanda TotalPrice alanımızı seçtik fakat tek bir farkla, seçtiğimiz bu alanın 0.08 değeri ile çarpımını sonuç olarak getirmesini istedik. (Her ürüne %8 kdv uyguladık diyebiliriz.)
4. alanda ise gerçek TotalPrice değerimizi aldık, bu değeri yine TotalPrice'ın 0.08 ile çırpımı ile topladık. (Sonuç olarak TotalPrice değerimizin üzerinde %8 daha ekleyerek sonuç elde ettik.)

4. alan olarak kullandığımız hesaplanmış alandaki () parantezleri neye göre koyduğumuzu, koymanın zorunlu olup olmadığını merak edebilirsiniz. Hemen cevaplandıralım. Öncelikle bu parantezleri koymamız zorunlu değildir. Kendinden önceki "," den itibaren kendinden sonraki "," e kadar olan (ya da son seçilen alan ise FROM ifadesine kadar) sorgu alanı bizim için tek bir alanı ifade etmektedir. Yani biz seçimini yaptığımız son alanı TotalPrice + TotalPrice * 0.08 şeklinde de yazabilirdik.
Parantezleri neye göre koydumuza gelince açıkçası bu konu üzerinde çok kafa yormadım. Neye göre koyulur ve nasıl bir kuralı vardır bilmiyorum. Benim kendi mantığıma kullandığım ve şimdiye kadar hata almadığım yöntem "her bir alanı parantez içine alıp parantez içine alınan alanlar arasında herhangi bir işlem var ise onları da ayrıca dış parantez içine almak."
Konu hakkında daha detaylı bilgisi olan arkadaşlar fikir beyan edebilirler, mesajımı düzenleyerek isimlerini ve açıklamalarını ekleyebilirim.

Bu bize neyi gösteriyor? Elimizde satış ile ilgili bir tablo var ve bu tabloda kdv'ler ile ilgili herhangi bir veri tutulmamış ise yine de bu tür alanları hesaplanmış olarak kendimiz sorgular aracılığı ile üretebiliyoruz.
 
Şimdiye kadar WHERE deyimi ile koşullarımızı sorgumuza anlattık. Peki bütün koşullarımızı sadece WHERE ile mi anlatıyoruz? Hayır, bütün koşullarımızı sorgumuza sadece WHERE ile anlatmıyoruz. Bunu yapmanın bir yöntemi de HAVING kullanımıdır. Görüldüğü üzere HAVING adında yeni bir deyim ile karşı karşıyayız. Peki WHERE ile hemen hemen her koşulumuzu veritabanına anlatabiliyorken şimdi ne gerek vardı HAVING kullanmaya diyeceksiniz. Aslında gerek var.

WHERE SUM() COUNT() gibi gruplandırma işlemlerinden önceki değerleri seçmek için kullanılır.
HAVING ise gruplanmış değerler üzerinden koşullar üreterek bu koşulların sonuçlarını getirir.

Bir örnek ile konuyu biraz daha anlaşılır hale getirelim.
no:20
Kod:
SELECT MONTH(OrderDate), SUM(TotalPrice) FROM [FoodSales$] WHERE TotalPrice>150 GROUP BY MONTH(OrderDate)
Bu sorgumuzda SUM fonksiyonu ile toplam alıyoruz. Toplam almadaki şartımız ise TotalPrice değeri 150 üzerinde olanları almasıdır.
Ayrıca bu sorgumuz ile birlikte tarih fonksiyonu olan MONTH() fonksiyonunu da görmüş oluyoruz. MONTH(TarihAlani) şeklide kullanılan fonksiyon bize tarih değeri içerisindeki ay sayısını döndürür. Aynı mantıkla YEAR() ve DAY() fonksiyonlarını da kullanabiliyoruz.

no:21
Kod:
SELECT MONTH(OrderDate), SUM(TotalPrice) FROM [FoodSales$] WHERE TotalPrice>150 GROUP BY MONTH(OrderDate) HAVING SUM(TotalPrice) > 2000
Bu sorgumuzda da anlaşılacağı gibi ilk önce 20 sorgumuzda yaptığımız 150 üzeri kayıtları aylara göre gruplayarak topladık. Daha sonra ise HAVING ile toplamları 2000 üzeri olan kayıtları getirmesini istedik.

Hatalı kullanım:
Kod:
SELECT MONTH(OrderDate), SUM(TotalPrice) FROM [FoodSales$] WHERE TotalPrice>150 AND SUM(TotalPrice) > 2000 GROUP BY MONTH(OrderDate)
Aynı sorguda HAVING ile bu işlemi yapmak yerine yukarıdaki hatalı kullanımda bulunan WHERE koşulu gibi yapsaydık kayıtsetimiz bize veri getirmeyecekti. Çünkü henüz veriler üzerinde toplama yapıp gruplandırmamış olacaktı.

iki kriter belirleme deyimi arasındaki farkı küçük bir örnek ile anlatmış olduk. Bu dersimizi biraz kısa tutuyoruz fakat yeni öğrendiğimiz konuyu etkili bir örnek üzerinde anlattığımı düşünüyorum. Herhangi bir şekilde kafanıza takılan konular olursa sormaktan çekinmeyin.

Düzeltme: Yapılan çalışmalara ilişkin kodları içeren excel dosyasını ekledim. Bu mesajdan sonra farklı bir veritabanı oluşturup o veritabanı üzerinden devam edeceğiz.
 

Ekli dosyalar

Son düzenleme:
Bugüne kadar örnek FoodSales dosyası üzerinde çalıştık. Bundan sonrası için hem örnek olması açısından hem, hemde kullanabileceğiniz küçük bir uygulama yapma açısından yeni bir veritabanı ile çalışacağız. "Çalışma Dosyası.xlsm" dosyamızın yanındaki "FoodSales.xlsx" ile vedalaştıktan sonra "Rehber.accdb" dosyası oluşturalım.

Farkına vardığınız gibi konumuz "kapalı excel dosyasından veri alma" olmasına rağmen, biz "Rehber.accdb" dosyası oluşturduk.
ADO ister excel olsun, ister access olsun, ister MSSQL olsun bunların hepsini veritabanı olarak görür. Yani ado çalışma yaptığımız dosyanın türüne bakmaz sadece veri transferine odaklanır.

ADO ile kabaca kod yapımızın nasıl olduğunu tekrar paylaşarak hatırlatmakta fayda görüyorum.

Kod:
Public Sub ADOTest1()

    Dim con As New ADODB.Connection
    Dim rs As New ADODB.Recordset
    Dim query As String
    Dim ConStr As String
  
    ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.Path & "\Rehber.xlsx;Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
    con.Open ConStr

    query = "SELECT *SORGU İFADESİ YAZILACAK YER"
  
    rs.Open query, con, adOpenKeyset, adLockPessimistic
  
    con.Close
  
    Set rs = Nothing
    Set con = Nothing
  
End Sub

Şimdiye kadar SELECT sorguları üzerinde durduk artık bu çerçeveden çıkmanın zamandı geldi. (İlerleyen zamanlarda SELECT sorgularına tekrar döneceğiz)
Şimdi elimizde tertemiz hiç bir tablo barındırmayan "Rehber.accdb" dosyası mevcut, bu dosyamıza yeni tablolar açmanın zamanı geldi. Bunu hem dosyayı açıp manuel olarak gerçekleştirebiliyoruz hem de kullandığımız uygulama üzerinden kod ile gerçekleştirebiliyoruz.
Konumuz SQL SORGULARINA odaklı olduğu için biz kolaya kaçıp tablomuzu elle açmak yerine kodla açmayı deneyeceğiz.

NOT: SELECT sorguarı rs değişkenimizde bize veriler sundu ve biz de bu veriler üzerinde çalıştık. (Daha spesifik çalışma örneklerini ilerleyen zamanlarda anlatacağım) fakat bazı sorgular herhangi bir veri döndürmeden bazı olayları gerçekleştirdikten sonra kapanırlar.

Şimdi göreceğimiz sorgu deyimi CREATE TABLE deyimi.
Kod:
CREATE TABLE TabloAdi(SutunAdi1 VeriTuru, SutunAdi2 VeriTuru, SutunAdi3 VeriTuru....);
Genel kullanımı üstte gördüğünüz şekildedir. CREATE TABLE deyimini kullandıktan sonra tablo adı belirlenir. Daha sonra oluşturulacak alanlar Parantez içerisinde veri türlerini de içerir şekilde yazılır. Görüldüğü üzere bazı karmaşık kullanım şekilleri hariç basit bir yapısı vardır.

Biz Rehber.accdb adında bir veritabanı oluşturduk ve rehberimizdeki bilgileri tutmak istiyoruz.
Öncelikle Kisiler adında bir tabloya ihtiyacımız var. Bu tablo için nelere ihtiyacımız olduğunu göz atalım.
Hemen hemen her tablo (bazı istisnalar hariç) her kaydı ayrı ayrı tanımlayan benzersiz bir kimlik değeri içermek zorundadır. Biz buna kisiID diyelim ve veritipi olarak LONG seçelim. (Access veritabanına geçtik, access bize her alan için bir veri tipi sunar bu veri tiplerinin neler olduğuna kısaca göz atmak için bkz:w3schools), Adi alanımız olsun bunu Text olarak tanımlayalım. Soyadi Text olsun, Cinsiyet Text olsun, GSM1 Text, GSM2 Text, Faks Text, EPosta1 Text, EPosta2 Text olsun. (Bu tablo normalizasyon kurallarına uymuyor, uymak için uğraşırsak örneklerimiz hem karmaşıklaşır hem de sıkıcı bir şekilde çok uzar)

Şimdi sorgumuz içinde yukarıda bahsettiğimiz alanları kullanalım.
Kod:
CREATE TABLE Kisiler(KisiID LONG, Adi varchar(50), Soyadi varchar(50), Cinsiyet varchar(5), GSM1 varchar(15), GSM2 varchar(15), Faks varchar(15), EPosta1 varchar(100), EPosta2 varchar(100));
ID rakam olacağı için sayısal veritipi seçerek buna long dedik, soyadı metinsel ifade içereceği için varchar dedik. (varchar metisel ifadeler için kullanılır parantez içindeki rakam en fazla kaç karakter değer alabileceğini ifade eder) daha sonraki ifadeler için de benzer şekilde belirlemeler yaptık.

Şimdi kodumuzu oluşturup sorgumuzu çalıştıralım.
Kod:
Public Sub ADOTest1()

    Dim con As New ADODB.Connection
    Dim rs As New ADODB.Recordset
    Dim query As String
    Dim ConStr As String
   
    ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.Path & "\Rehber.accdb;Persist Security Info=false;"
    con.Open ConStr

    query = "CREATE TABLE Kisiler(KisiID LONG, Adi varchar(50), Soyadi varchar(50), Cinsiyet varchar(5), GSM1 varchar(15), GSM2 varchar(15), Faks varchar(15), EPosta1 varchar(100), EPosta2 varchar(100));"
   
    rs.Open query, con, adOpenKeyset, adLockPessimistic
   
    con.Close
   
    Set rs = Nothing
    Set con = Nothing
   
End Sub
Kodumuzu çalıştırdıktan sonra access dosyamızda Kisiler tablosunun oluştuğunu görebiliriz.

Şimdi buradaki önemli hususlardan birisi yukarıda da bahsettiğim gibi SELECT sorguları defalarca çalıştırılsa dahi çalışabilecek sorgulardır, fakat CREATE TABLE sorgusunu en fazla bir kere çalıştırabiliriz. Bunun sebebi kodu bir kere çalıştırdıktan sonra tablomuz veribanında oluşacaktır, 2. ve diğer çalıştırmalarda aynı tablodan bir tane daha açamayacağı için kod çalışırken hata üretecektir. (Bu tür hataların önüne geçmek için hem kod tarafında hem sorgu tarafından bir takım yöntemler var fakat şimdi onlara değinmeyeceğim. İlerleyen zamanlarda vakit bulursak konumuz çok uzamazsa değinebiliriz.)

NOT: Sorguyu en basit haliyle paylaştım, tablomuzda bulunması gereken Primary Key, Foreign Key gibi alanları Null değer alabilip alamayacağı ile ilgili kısımları da tanımlamak istersek kısaca bir örnek;

Kod:
CREATE TABLE Kisiler (
    KisiID int NOT NULL,
    Adi varchar(50) NOT NULL,
    Soyadi varchar(50) NOT NULL,
    Cinsiyet varchar(5),
    PRIMARY KEY (kisiID)
);
bu tablomuz Primary Key alanı tanımı yapar. Ayrıca KisiID alanının Primary Key değerini tanımlama için (KisiID int NOT NULL PRIMARY KEY, ...) şeklinde de yazabilirdik. Farkına varacağınız gibi alanların NULL değer alıp almayacağını ayarladık, dikkat ederseniz NOT NULL olmayan değer için NULL yazma ihtiyacı duymadık çünkü NULL ya da NOT NULL ayarı default olarak NULL gelir.

CREATE TABLE konusuna da olduk. Bundan sonrası için öğreneceğimiz sorgu ifadesi ise INSERT INTO ile tabloya veri ekleme olacak.
 

Ekli dosyalar

Son düzenleme:
@aeGNoR hocam çok başarılı bir çalışma gerçekleştirmişsiniz.
Artık ADO kullanma vakti gelmiştir.
Elinize yüreğinize sağlık.
Saygılarımla
 
Tablomuzu oluşturduk, şimdi tablomuza veri girişi yapma zamanı. Veri girişinde INSERT INTO ifadesini kullanıyoruz. Bu ifade veritabanındaki tablomuza bir adet Recordset yani kayıtseti ekleyebiliyor.

Kod:
INSERT INTO [TabloAdi] (Alan1, Alan2, Alan3, ...) VALUES (Alan1, Alan2, Alan3, ....)
Örnek üzerinde de görüldüğü gibi INSERT INTO çok basit bir mantıkla işlemektedir. INSERT INTO ifadesini kullandıktan sonra kayıt eklemek istediğimiz tablonun adını yazıyoruz. Daha sonra veri eklemek istediğimiz alanları parantez içerisinde yazıyoruz. Veri girilecek alanlar belirlendikten sonra VALUES deyimi ile yine parantez içinde girilecek değerler belirlenecek.

Örneğimizi Rehber veritabanımızı kullanarak biraz somutlaştıralım.

Kod:
INSERT INTO Kisiler(kisiID, Adi, Soyadi, Cinsiyet, GSM1, GSM2, Faks, EPosta1, EPosta2) VALUES (1, 'Mustafa', 'MUSTAFA', 'ERKEK', '0123456789', '1234567890', '2345678901', 'mustafa@mustafa.com', 'mustafa@excelcozum.com')
Yukarıda bahsettiğimiz mantıkla Rehber veritabanımıza veri girişi yapmış olduk. Şimdi aklımıza şöyle bir soru takılabilir; ben kayıt yaparken her defasında kaçıncı kişiyi kaydettiğimi bilmek zorunda mıyım? kisiID yi bizim yerimize kendisi her kayıt için 1 (bir) arttırsa olmaz mı? Evet olur çok da güzel olur. Fakat bu konuya değinebilmek için tablomuzu ilk oluştururken bilerek bir hata yaptım. Nedir o hata? KisiID alanını LONG olarak oluşturdum. Veritabanımızın bizim yerimize sayılar atayabilmesi için alanımızı AutoNumber olarak tanımlamalıydık. Telaş yapmaya gerek yok, veritabanını ve çalışma excel dosyamızı bu mesaj ile paylaşacağım. Paylaştığım dosyalarda kisiID autonumber olarak ayarlanmış olacaktır.

Şimdi tekrar dönelim INSERT INTO konumuza. Yukarıdaki örnekte görüldüğü gibi Kisiler tablosundan sonraki parantez içinde 9 adet alan seçildi ve yine VALUES ile değerleri girerken de 9 adet alana seçim sırasıyla değer girdik.
Peki 8 Alan seçip 9 değer yazmış olsaydım ne olacaktı? Hata verecekti.
Aynı mantıkla 9 alan seçip 8 değer yazmış olsaydım da hata verecekti.
Buradan şunu çıkarıyoruz seçilen alan ile girilen değerlerin sayısı aynı olmak zorundadır.

kisiID alanımız AutoNumber olsaydı;
Kod:
INSERT INTO Kisiler(Adi, Soyadi, Cinsiyet, GSM1, GSM2, Faks, EPosta1, EPosta2) VALUES ('Mustafa', 'MUSTAFA', 'ERKEK', '0123456789', '1234567890', '2345678901', 'mustafa@mustafa.com', 'mustafa@excelcozum.com')
görüldüğü gibi seçilen alanlardan ve girilen değerlerden kisiID kısmını kaldıracaktık ve işin o kısmını veritabanı bizim için halledecekti.

Burada akıllarda yine bir soru belirebilir. Kayıtseti kendini oluşturan alanların tamamı ile bir bütündü, ama biz yeni değer girerken alanlardan bir tanesini seçmedik bu nasıl mümkün olabilir? Veritabanımız bizim seçmediğimiz her alan için kendi içinde default bir değer verebilir. Yani ben kişi ekleme kaydımı
Kod:
INSERT INTO Kisiler(Adi, Soyadi) VALUES ('Mustafa', 'MUSTAFA')
şeklinde yapmış olsaydım GSM, EPosta gibi alanlara seçtiğimiz default değerleri girecekti (Default değerler belirlenmemişse Null (boş) olarak değer girecekti).
Burada sadece benzersiz değerler ile ilgili problem söz konusu olabilir. Yani bizim Kisiler tablomuzda TCKimlik adında bir alanımız olsaydı ve her kayıt için benzersiz olma şartı olsaydı INSERT INTO sorgumuza bu alanı eklemek zorundaydık.
 

Ekli dosyalar

Bir önceki dosyada paylaştığım veri ekleme örneği textboxlara bağlı değildi, gelin şimdi bu textboxlardan veri alarak yeni kayıt ekleyelim. Bunu yapmanın çok fazla yolu olmasına rağmen ben query değişkenini oluşturmayı bir fonksiyona bağlamayı tercih ediyorum. Şimdi bir örnekle bunu netleştirelim.

Userform üzerindeki textbox ve commandbutton nesnelerini adlandırdım. Şöyle ki txtEkleAdi, txtEkleSoyadi, cmdKaydet vb. Bunu örnek dosya eklediğimde daha net göreceksiniz.

Userform üzerindeki bütün kodlarımızı siliyoruz tamamını yeniden revize edeceğiz. Declarations kısmında bulunan;
Kod:
Dim con As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim query As String
Dim ConStr As String
Değişkenlerimiz sabit kalıyor.

Şimdi listbox nesnemizi doldurmak için initialize olayına yazdığımız kodları ayrıca;
Kod:
Private Sub RefreshListBox()

    con.Open ConStr
    query = "SELECT * FROM Kisiler"
    rs.Open query, con, 3, 1
    On Error Resume Next
    ListBox1.Clear
    ListBox1.Column = rs.GetRows
    con.Close
    
End Sub
Üstteki RefreshListBox prosedürüne çevirdik. Böylece listbox içindeki verilerimizi her yenilememiz gerektiğinde call RefrshListBox yaparak yenileyebileceğiz.

Formu açarken listbox'ı doldurmak için Initialize olayında call ile refreshlistbox prosedürünü aşağıdaki gibi çağırıyoruz;

Kod:
Private Sub UserForm_Initialize()

    ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.Path & "\Rehber.accdb;Persist Security Info=False;"
    Call RefreshListBox
    
End Sub

Şimdi veri query değişkenimizi inşa edecek fonksiyonu yazmaya geldi sıra(Fonksiyon yazmayı, fonksiyon üzerinde değişken kullanmayı bildiğinizi varsayıyorum);

Kod:
Private Function VeriEkleQuery(Adi As String, Soyadi As String, Cinsiyet As String, GSM1 As String, GSM2 As String, Faks As String, EPosta1 As String, EPosta2 As String) As String
    
    Dim strResult As String
    strResult = "INSERT INTO Kisiler(Adi, Soyadi, Cinsiyet, GSM1, GSM2, Faks, EPosta1, EPosta2) VALUES ("
    Adi = IIf(Trim(Adi) = "", "''", "'" & Adi & "'")
    Soyadi = IIf(Trim(Soyadi) = "", "''", "'" & Soyadi & "'")
    Cinsiyet = IIf(Trim(Cinsiyet) = "", "''", "'" & Cinsiyet & "'")
    GSM1 = IIf(Trim(GSM1) = "", "''", "'" & GSM1 & "'")
    GSM2 = IIf(Trim(GSM2) = "", "''", "'" & GSM2 & "'")
    Faks = IIf(Trim(Faks) = "", "''", "'" & Faks & "'")
    EPosta1 = IIf(Trim(EPosta1) = "", "''", "'" & EPosta1 & "'")
    EPosta2 = IIf(Trim(EPosta2) = "", "''", "'" & EPosta2 & "'")
    strResult = strResult & Adi & "," & Soyadi & "," & Cinsiyet & "," & GSM1 & "," & GSM2 & "," & Faks & "," & EPosta1 & "," & EPosta2 & ")"
    VeriEkleQuery = strResult
    
End Function

Query değişkenimizi yapılandıracak fonksiyonu da bu şekilde yazmış olduk. Query değişkenini oluşturmak için oluşturduğumuz fonksiyonu ekle butonu içerisinde kullanacağız böylece ekle butonumuz içerisindeki kodlarımızı karmaşıklaştırmamış alacağız.
Artık Kaydet butonu ile verilerimizi ekleyebilecek duruma geldik sayılır. Kaydet butonu içindeki kodlarımızı da ayarladıktan sonra artık veri kaydedebilir duruma geleceğiz.
Kaydet butonumuzun kodları ise aşağıdaki gibi olacaktır;
Kod:
Private Sub cmdKaydet_Click()

    con.Open ConStr
    query = VeriEkleQuery(txtEkleAdi.Value, txtEkleSoyadi.Value, txtEkleCinsiyeti.Value, txtEkleGSM1.Value, txtEkleGSM2.Value, txtEkleFaks.Value, txtEkleEPosta1.Value, txtEkleEPosta2.Value)
    Debug.Print query
    rs.Open query, con, 3, 1
    con.Close
    Call RefreshListBox
    
End Sub
Bu kodlarla con nesnemizi açıyoruz ve oluşturduğumuz fonksiyon ile query değişkenimizi yapılandırıyoruz belirlediğimiz parametreler ile. Daha sonra rs nesnemizi open yaparak kaydın gerçekleşmesini sağlıyoruz. (Bu tür kayıtlarda hata denetimleri yapılmak ZORUNDADIR fakat şimdilik konumuz tam olarak bu olmadığı için buna değinmiyorum.)
Ayrıca rs nesnemiz ile kaydı gerçekleştirdikten sonra listbox yenilemek için tekrar kod yazmak yerine daha önce yazdığımız RefreshListBox prosedürümüzü call komutu ile çağırıyoruz ve eklemiş olduğumuz kaydı listbox üzerinde anlık olarak görmüş oluyoruz.

INSERT INTO sorgusunun form üzerindeki nesneler ile ilişkilendirilerek nasıl kullanılabileceği hakkında bir örnek gerçekleştirmiş olduk.
Bugünlük bu kadar yeterli, daha sonraki derslerimizde görüşmek üzere.
 

Ekli dosyalar

Merhaba arkadaşlar,
Çok uzun bir aradan sonra rehber uygulamamıza güncelle ve sil butonlarını da ekleyelim. Farklı bir gelişme olmazsa bu anlatımla rehber uygulaması yapmayı sonlandırmak istiyorum. ADO'nun farklı özelliklerini daha farklı örneklerle anlatmayı planlıyorum.
UPDATE
Güncelle sorgumuz kabaca;
Kod:
UPDATE Tablo_Adı SET Kolon_Adı1 = Deger1, Kolon_Adı2 = Deger2... WHERE Şart
Şeklinde bir yapı bulunur. Bu yapıda önemli olan güncelleme yapılırken değişiklik yapacağımız sütunları SET etmeliyiz. Ayrıca çok önemli olarak güncelleme sorgumuza WHERE şartını mutlaka eklemeliyiz.
Örnek olarak;
Kod:
UPDATE Kisiler SET Faks = 000000000
Bu sorgudan Kisiler tablosunda bulunan Faks alanı üzerinde değişiklik yapılacağını anlıyoruz. Fakat bir problemimiz var ki, hangi kayıt setindeki Faks alanını değiştireceğimizi söylemedik. Bu çalıştırılan sorgu bize ciddi bir sıkıntı olarak geri dönecektir. Tablomuzda bulunan bütün kayıtsetlerinde bulunan faks alanlarına aynı numarayı yazacaktır. Dolayısıyla UPDATE Sorgumuzda WHERE şartı ciddi öneme sahitir.
Kod:
UPDATE Kisiler SET Faks = 000000000 WHERE KisiID=1
Doğru olan örnek kod yukarıdaki gibi olacaktır.
Not:Belli bir grup kayıt seti üzerinde değişiklik yapmayı düşünmüyorsak, tek bir kayıt seti üzerinde değişiklik yapmayı düşünüyorsak genelde ID kolonlarını WHERE şartına referans olarak gösteririz.
Not2:Bir grup kayıt üzerinde değişiklik yapmak istiyorsak WHERE şartımızı hangi gruba göre değişiklik yapacaksan ona göre kurmalıyız. Örneğin Rehber veritabanımızdaki kişileri gruplandırmak isteyip Grup diye bir alan eklemiş olsaydık şartımızı buradan yapmış olacaktık.
Kod:
UPDATE Kisiler SET Faks = 000000000 WHERE Grup='Arkadaşlar'
Bir grup kayıtseti üzerinde yapılacak olan değişikliğin örneği.

DELETE
DELETE
sorgularında ilk olarak anlamamız gereken şey WHERE şartına mutlaka ihtiyacımız olacak. Diyelim ki tablonuzda binlerce kayıt girdiniz ve şöyle bir silme sorgusu çalıştırdınız;
Kod:
DELETE FROM Tablo_Adı
Geçmiş olsun dileklerimizi size iletelim, çünkü herhangi bir yedeğiniz yoksa tablonuzdaki BÜTÜN KAYITLAR SİLİNDİ :)
UPDATE sorgularındaki gibi WHERE şartımız olmazsa olmaz bir gereklilik olarak karşımızda duruyor.
Doğru sorgu yapısı ise aşağıdaki gibi olmalıdır.
Kod:
DELETE FROM Tablo_Adı WHERE Şart

Silme sorgularının doğrusunu öğrendikten sonra genel kullanıma bir örnek verelim.
Kod:
DELETE FROM Kisiler WHERE kisiID=1
Bu örnekte 1 ID numaralı kişiyi silmiş oluyoruz.

Diyelim ki birden çok kayıtsetini silmek istiyoruz. Where şartımızı daha geniş kapsamlı tutarak silme işlemi yapabiliriz.
Kod:
DELETE FROM Kisiler WHERE Adi='Mustafa'
Bu örnekte ise Adi alanındaki 'Mustafa' değerine sahip bütün kayıtlarımız silinmiş olacaktır.

Bu son mesajımla; ayırabildiğim kısıtlı zaman içerisinde en azından temel konuları bitirmeye çalıştım diyelim. Biliyorum konuyu geçiştirmişim gibi duruyor ama son zamanlarda oldukça yoğun bir gündeme sahibim. Dolayısıyla ŞİMDİLİK bu anlatımı burada sonlandırıyorum. Umarım en kısa zamanda tekrar vakit bulabilir ve sizinle burada güzel işlere imza atabiliriz.
 
Geri
Üst