diff --git a/.DS_Store b/.DS_Store index bc9a467..d598cb9 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/Python-App-OzetNotlar-Ornekler.txt b/Python-App-OzetNotlar-Ornekler.txt index 0ada496..a066e2a 100644 --- a/Python-App-OzetNotlar-Ornekler.txt +++ b/Python-App-OzetNotlar-Ornekler.txt @@ -2182,7 +2182,7 @@ python -m timeit -n 100000 "'-'.join(str(i) for i in range(100))" SELECT student_name, student_no FROM student_info WHERE student_no > 600; - Burada numarası 600'den büyükolan öğrencilerin isimleri ve numaraları elde edilmektedir. Sütun istesi yerine * kullanılırsa bu + Burada numarası 600'den büyük olan öğrencilerin isimleri ve numaraları elde edilmektedir. Sütun istesi yerine * kullanılırsa bu durum "tüm sütunlar" anlamına gelmektedir. Örneğin: SELECT * FROM student_info WHERE student_no > 600; @@ -2447,8 +2447,8 @@ python -m timeit -n 100000 "'-'.join(str(i) for i in range(100))" #------------------------------------------------------------------------------------------------------------------------------------ SQL SELECT cümlesinin Python'da uygulanması üzerinde ayrıca durmak gerekir. Çünkü SELECT cümlesi ile biz VTYS'den kayıt çekmekteyiz. SELECT cümlesi yine diğer cümlelerde olduğu gibi Cursor sınıfının execute metodu ile işletilir. Kayıtlar Cursor sınıfının fetchone - ve fetchmany isimli metotlarıyla elde edilmektedir. fetchone metodu koşulu sağlayan kayıtlardan yalnızca bir tanesini, fetchmany ise - n tanesini elde etmekte kullanılmaktadır. Tabii bu metotlar birden fazla kez çağrılabilirler. fetchone kaydı tek bir demet olarak + ve fetchmany isimli metotlarıyla elde edilmektedir. fetchone metodu koşulu sağlayan kayıtlardan yalnızca bir tanesini, fetchmany + ise n tanesini elde etmekte kullanılmaktadır. Tabii bu metotlar birden fazla kez çağrılabilirler. fetchone kaydı tek bir demet olarak fetchmany ise kayıtları bir demet listesi olarak varmektedir. Demetlerin elemanları SELECT komutunda belirtilen sütun sıralarına göredir. @@ -2601,7 +2601,7 @@ s #------------------------------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------------------------------ - 10. Ders 06/04/2025 - Pazar + 10. Ders 06/04/2025 - Pazar #------------------------------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------------------------------ @@ -2624,8 +2624,8 @@ s #------------------------------------------------------------------------------------------------------------------------------------ INSERT, UPDATE, DELETE işlemleri sonucunda bu işlemlerden etkilenen kayıt sayısı Cursor sınıfının rowcount isimli örnek özniteliğinden - elde edilebilmektedir. Örneğin biz DELETE komutu ile bir grup kaydı silmişsek rowcount bize silinen kayıtların sayısını verir. - rowcount örnek özniteliği SELECT komutu uygulandığında set edilmemektedir. Yani biz SEELCT edilen satırların sayısını rowcount ile + elde edilebilmektedir. Örneğin biz DELETE komutu ile bir grup kaydı sildiğimizde rowcount bize silinen kayıtların sayısını verecektir. + rowcount örnek özniteliği SELECT komutu uygulandığında set edilmemektedir. Yani biz SELECT edilen satırların sayısını rowcount ile elde edemeyiz. Aşağıdaki örnekte biz veritabanına 1 kayıt insert ediyoruz. Dolayısıyla rowcount bize 1 değerini verecektir. @@ -2677,7 +2677,7 @@ except Exception as e: bir öğrenciyi INSERT ederken school tablosunda olmayan bir school_id girmemeliyiz. Bu tür kontoller şüphesiz manuel biçimde school tablosu sorgulanarak yapılabilir. Ancak VTYS'ler bu tür işlemleri kendi içlerinde yapabilmektedir. Bunlara "yabancı anahtar kısıtları (foreign key constraints)" denilmektedir. Yabancı anahtar kısıtları tablo yaratılırken CREATE TABLE komutunda komutun sonunda belirtilmektedir. - VTYS'ler arasında bu konuda farklılıklar bulunmaktadır. Örneğin SQLite'ta CREATE TABLE komutunda komutunun sonunda aşağıaki gibi kısıt + VTYS'ler arasında bu konuda farklılıklar bulunmaktadır. Örneğin SQLite'ta CREATE TABLE komutunda komutun sonuna aşağıaki gibi kısıt girilebilir: CREATE TABLE student ( @@ -2685,22 +2685,22 @@ except Exception as e: FOREIGN KEY (school_id) REFERENCES school(school_id) ) - Burada student tablosunaki school_id sütunu scool tablosundaki school_id ütunu ile foreign key temelinde ilişkilendirilmiştir. + Burada student tablosunaki school_id sütunu school tablosundaki school_id sütunu ile "foreign key" temelinde ilişkilendirilmiştir. Artık biz bir örenciyi eklerken school tablosunda olmayan bir scool_id girersek işlme başarısızlıkla sonuçlanacaktır. #------------------------------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------------------------------ - Bazı tablolarda bazı sütunlar "yabancı anahtar (foreign key)" durumundadır. Öğrenğin school tablosunun school_id elemanı hem PRIMARY KEY - durumundadır hem de student tablosu için FOREIGN KEY durumundadır. school tablosuna bir okul eklerken ekleyen kişinin school_id vermesi - zor bir kullanımdır. İşte bu tür durumlarda anımsanacağı gibi ilgili sütuna AUTOINCREMENT özelliği verilebilmektedir. AUTO INCREMENT - bir sütun söz konusu olduğunda eğer INSERT işleminde bu sütun belirtilmezse bu durumda VTYS en büyük numaranın bir fazlasını almaktadır. - SQLite'ta aslında PRIMARY KEY olan tamsayı alanları otomatik AUTOINCREMENT durumdadır. Ancak uygulamacı AUTOINCREMENT belirlemesini - yine yapabilir. + Bazı tablolarda bazı sütunlar "yabancı anahtar (foreign key)" durumundadır. Öğrenğin school tablosunun school_id elemanı hem + PRIMARY KEY durumundadır hem de student tablosu için FOREIGN KEY durumundadır. school tablosuna bir okul eklerken ekleyen kişinin + school_id vermesi zor bir kullanımdır. İşte bu tür durumlarda anımsanacağı gibi ilgili sütuna AUTOINCREMENT özelliği verilebilmektedir. + AUTOINCREMENT bir sütun söz konusu olduğunda eğer INSERT işleminde bu sütun belirtilmezse bu durumda VTYS en büyük numaranın bir + fazlasını almaktadır. SQLite'ta aslında PRIMARY KEY olan tamsayı alanları aynı zamanda AUTOINCREMENT durumdadır. Ancak uygulamacı + AUTOINCREMENT belirlemesini yine yapabilir. #------------------------------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------------------------------ Bazen veritabanı üzerinde birbirleriyle ilişkili olan işlemler yapılıyor olabilir. Bu tür işlemlerin "ya hep ya hiç" biçiminde - gereçekleştirilmesi gerelebilmektedir. İşte VTYS'lerde "bir grup eylemin sanki tek bir eylemmiş gibi peşi sıra gerçekleştirilmesine + gereçekleştirilmesi gerelebilmektedir. İşte VTYS'lerde bir grup eylemin sanki tek bir eylemmiş gibi peşi sıra gerçekleştirilmesine "transaction" denilmektedir. Örneğin bir grup bilginin birbirleriyle tutarlı bir biçimde üç farklı tabloya insert edilmek istendiğini düşünelim. Biz bu üç insert işlemi başarılıysa en sonunda commit yaparak bu işlemlerin veritabanına yansıtılmasını isteriz. Örneğin: @@ -2749,12 +2749,12 @@ except Exception as e: except sqlite3.Error as e: conn.rollback() - Özel bir durum olarak execute işleminde eğer SQL SELECT komutu uygulanmışsa bu durumda transcation otomatik başlatılmamaktadır. + Özel bir durum olarak execute işleminde eğer SELECT komutu uygulanmışsa bu durumda transcation otomatik başlatılmamaktadır. - Transaction kavramı ve rollback işlemi birden fazla INSERT, UPDATE ve DELETE komutlarının peşi sıra geldiği durumlarda önemli olmaktadır. - Yoksa tek bir INSERT, UPDATE ya da DELETE komutu için rollback uygulamaya gerek yoktur. Yukarıda da beirttiğimiz gibi rollback işlemi - bir grup peşi sıra yapılan işlemin bir tanesi başarısız ise onların hiçbirini yapmamayı sağlamaktadır. commit işlemi ise onların - hepsini tek bir işlemmiş gibi atomik yapmayı sağlar. + Transaction kavramı ve rollback işlemi birden fazla INSERT, UPDATE ve DELETE komutlarının peşi sıra geldiği durumlarda önemli + olmaktadır. Yoksa tek bir INSERT, UPDATE ya da DELETE komutu için rollback uygulamaya gerek yoktur. Yukarıda da belirttiğimiz gibi + rollback işlemi bir grup peşi sıra yapılan işlemin bir tanesi başarısız ise onların hiçbirini yapmamayı sağlamaktadır. commit işlemi + ise onların hepsini tek bir işlemmiş gibi atomik yapmayı sağlar. #------------------------------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------------------------------ @@ -2772,7 +2772,7 @@ except Exception as e: transaction'ı başlatan BEGIN (ya da BEGIN TRANSACTION) komutu eklenmelidr. Örneğin: cur.executescript(""" - BEGIN; + BEGIN TRANSACTION; CREATE TABLE person(firstname, lastname, age); CREATE TABLE book(title, author, published); CREATE TABLE publisher(name, address); @@ -2794,9 +2794,8 @@ except Exception as e: except sqlite3.Error as e: conn.rollback() - Tabii yukarıda da belirttiğimiz gibi execute, executemany ve exceutescript metotları zaten otomatik trnsaction oluşturmaktadır. - Python programcıları da genellikle commit ve rollback gibi işlemleri SQL komutlarının içerisinde değil metot çağrılarıyla - yapmaktadır. + Tabii yukarıda da belirttiğimiz gibi execute, executemany metotları zaten otomatik trnsaction oluşturmaktadır. Python programcıları + da genellikle commit ve rollback gibi işlemleri SQL komutlarının içerisinde değil metot çağrılarıyla yapmaktadır. #------------------------------------------------------------------------------------------------------------------------------------ import sqlite3 @@ -2832,242 +2831,331 @@ except Exception as e: etkisi olmayacaktır. #------------------------------------------------------------------------------------------------------------------------------------ -BURADA KALDIK +#------------------------------------------------------------------------------------------------------------------------------------ + 11. Ders 12/04/2025 - Cumartesi +#------------------------------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------------------------------ - Aşağıda "school" veritabanı üzerinde temel işleler yapan konsol tabanlı basit bir program verilmiştir. + Aşağıda "school" veritabanı üzerinde temel işlemler yapan konsol tabanlı basit bir program örneği verilmiştir. #------------------------------------------------------------------------------------------------------------------------------------ import sqlite3 -def main(): - try: - with sqlite3.connect(r'test.sqlite') as conn: - cur = conn.cursor() - create_tables(cur) - while True: - option = disp_menu() - if not option: - continue - match option: - case 1: - add_student(cur) - case 2: - add_school(cur) - case 3: - delete_student(cur) - case 4: - delete_school(cur) - case 5: - list_students(cur) - case 6: - list_school(cur) - case 7: - break - - except sqlite3.Error as e: - print(e) - def create_tables(cur): - cur.executescript(""" - CREATE TABLE IF NOT EXISTS school (school_id INTEGER PRIMARY KEY AUTOINCREMENT, school_name TEXT(64), school_type TEXT(64)); - CREATE TABLE IF NOT EXISTS student(student_no INTEGER, student_name VARCHAR(64), school_id INTEGER, FOREIGN KEY("school_id") REFERENCES "school"("school_id"), PRIMARY KEY("student_no" AUTOINCREMENT)); - """) - -def disp_menu(): - print('1) Öğrenci kaydı ekle') - print('2) Okul kaydı ekle') - print('3) Öğrenci sil') - print('4) Okul sil') - print('5) Öğrenci listele') - print('6) Okul listele') - print('7) Çıkış') - print() - try: - option = int(input('Seçiminiz:')) - if 1 <= option <= 7: - return option - raise ValueError() + script = """ + BEGIN; + CREATE TABLE IF NOT EXISTS school(school_id INTEGER PRIMARY KEY AUTOINCREMENT, school_name VARCHAR(128), school_city VARCHAR(32)); + CREATE TABLE IF NOT EXISTS student(student_id INTEGER PRIMARY KEY AUTOINCREMENT, student_no INTEGER, + student_name VARCHAR(64), school_id INTEGER); + """ + cur.executescript(script) except Exception as e: - print(f'Geçersiz giriş: {e}') - return 0 - -def add_student(cur): - try: - name = input('Öğrencinin adı soyadı:') - no = int(input('Öğrencinin numarası:')) - school_id = int(input("Öğrencinin okul id'si:")) - - cur.execute(f"SELECT school_id FROM school WHERE school_id = {school_id}") - if not cur.fetchall(): - raise ValueError("Geçersiz okul id'si") - - sqlcmd = f"INSERT INTO student(student_no, student_name, school_id) VALUES({no}, '{name}', {school_id})" - cur.execute(sqlcmd) - cur.connection.commit() - print('Kayıt başarılı biçimde eklendi...') - except sqlite3.Error as e: - print(f'Kayıt eklenemedi: {e}') - except ValueError as e: - print(f'Geçersiz Giriş: {e}') - except Exception as e: - print(f'Geçersiz giriş: {e}') - print() + print(e) + +def disp_menu(items_list): + while True: + for menu_no, (menu_item, _) in enumerate(items_list, 1): + print(f'{menu_no}) {menu_item}') + print() + try: + option = int(input('Seçiminiz:')) + if option >= 1 and option <= 9: + break + except: + pass + print('\nGeçersiz seçenek!..\n') + + return option def add_school(cur): try: - name = input('Okul adı:') - school_type = input('Okul türü:') - sqlcmd = f"INSERT INTO school(school_name, school_type) VALUES('{name}', '{school_type}')" - cur.execute(sqlcmd) + school_name = input('Okul ismi:').strip() + if school_name == '': + raise ValueError('Okulş ismi boş girilemez') + school_city = input('Okulun bulunduğu şehir:').strip() + if school_city == '': + raise ValueError('Şehir boş girilemez') + sql_cmd = f"INSERT INTO school(school_name, school_city) VALUES('{school_name}', '{school_city}')" + cur.execute(sql_cmd) cur.connection.commit() - print('Kayıt başarılı biçimde eklendi...') + print('\nOkul başarılı bir biçimde eklendi...\n') except sqlite3.Error as e: - print(f'Kayıt eklenemedi: {e}') + print(f'Eklemede sorun oluştu: {e}\n') except Exception as e: - print(f'Geçersiz giriş: {e}') - print() - -def delete_student(cur): + print(f'Hatalı giriş: {e}\n') + + return True + +def add_student(cur): try: - no = int(input('Öğrenci Numarası')) - sqlcmd = f"DELETE FROM student WHERE student_no = {no}" - cur.execute(sqlcmd) + student_name = input('Öğrencinin adı:').strip() + if student_name == '': + raise ValueError('Öğrenci boş girildi') + student_no = int(input('Öğrencinin numarası:')) + school_id = int(input("Öğrencinin okul Id'si:")) + sql_cmd = f"INSERT INTO student(student_name, student_no, school_id) \ + VALUES('{student_name}', {student_no}, {school_id})" + cur.execute(sql_cmd) cur.connection.commit() - print('Kayıt başarılı biçimde silindi...') + print('\nÖğrenci başarılı bir biçimde eklendi...\n') + except sqlite3.Error as e: - print(f'Kayıt silinemedi: {e}') + print(f'Eklemede sorun oluştu: {e}\n') except Exception as e: - print(f'Geçersiz giriş: {e}') - print() - -def delete_school(cur): + print(f'Hatalı giriş: {e}\n') + + return True + +def list_student(cur): try: - id = int(input("Dikkat! Bir okul silerken okula kayıtlı tüm öğrenciler de silinir\nOkul id'si:")) - sqlcmd = f"DELETE FROM school WHERE school_id = {id}" - cur.execute(sqlcmd) - sqlcmd = f"DELETE FROM student WHERE school_id = {id}" - cur.execute(sqlcmd) - cur.connection.commit() - print('Kayıt başarılı biçimde silindi...') - except sqlite3.Error as e: - cur.rollback() - print(f'Kayıt silinemedi: {e}') - except Exception as e: - print(f'Geçersiz giriş: {e}') - print() - -def list_students(cur): - try: - condition = input('Koşul:').strip() - - sqlcmd = "SELECT student_no, student_name, student.school_id, school_name FROM student, school WHERE student.school_id = school.school_id" + condition = input('Öğrenci için koşul:').strip() + sql_cmd = "SELECT student_id, student_name, student_no, school_name, school_city \ + FROM student, school WHERE student.school_id = school.school_id" + if condition != '': - sqlcmd += f' AND {condition}' - cur.execute(sqlcmd) - - print('\n-----------------------') - for student_no, student_name, school_id, school_name in cur.fetchall(): - print(f'{student_no} {student_name} {school_id} ({school_name})') - print('-----------------------') - + sql_cmd += f" AND {condition}" + cur.execute(sql_cmd) + + print() + print(f"{'İd':5s}{'Adı Soyadı':20s}{'No':<5s}{'Okul İsmi':<30s}{'Şehir'}") + print('-' * 80) + + for student_id, student_name, student_no, school_name, school_city in cur.fetchall(): + print(f'{student_id:<5d}{student_name:20}{student_no:<5d}{school_name:<30s}{school_city}') + + print('-' * 80) + print() + except sqlite3.Error as e: - print(e) + print(f'Aramada sorun oluştu: {e}\n') except Exception as e: - print(f'Geçersiz giriş: {e}') - print() - + print(f'Hatalı giriş: {e}\n') + + return True + +def erase_student(cur): + try: + student_id = int(input("Silinecek öğre3ncinin id'si:")) + sql_cmd = f"""SELECT student_id, student_name, student_no, school_name, school_city FROM student, school + WHERE student_id = {student_id} AND student.school_id = school.school_id""" + cur.execute(sql_cmd) + t = cur.fetchone() + if t is None: + print("\nBu id'ye ilişkin bir öğrenci yok!\n") + return + student_id, student_name, student_no, school_name, school_city = t + print(f'\n{student_id:<5d}{student_name:20}{student_no:<5d}{school_name:<30s}{school_city}\n') + confirm = input('Yukarıdaki öğrenciyi silmek istediğine emin misiniz (E)/(H):').lower() + if confirm == 'e': + sql_cmd = f"DELETE FROM student WHERE student_id = {student_id}" + cur.execute(sql_cmd) + cur.connection.commit() + print('\n1 kayır silindi...\n') + else: + print() + except sqlite3.Error as e: + print(f'Aramada sorun oluştu: {e}\n') + except Exception as e: + print(f'Hatalı giriş: {e}\n') + + return True + def list_school(cur): try: - condition = input('Koşul:').strip() - - sqlcmd = "SELECT school_id, school_name, school_type FROM school" + condition = input('Okul için koşul:').strip() + sql_cmd = "SELECT school_id, school_name, school_city FROM school"; + if condition != '': - sqlcmd += f' WHERE {condition}' - cur.execute(sqlcmd) - - print('\n-----------------------') - for school_id, school_name, school_type in cur.fetchall(): - print(f'{school_id}, {school_name}, {school_type}') - print('-----------------------') - + sql_cmd += f" WHERE {condition}" + cur.execute(sql_cmd) + + print() + print(f"{'id':<5s}{'Okul İsmi':<40s}{'Şehir'}") + print('-' * 80) + + for school_id, school_name, school_city in cur.fetchall(): + print(f'{school_id:<5d}{school_name:<40s}{school_city}') + + print('-' * 80) + print() + except sqlite3.Error as e: - print(e) + print(f'\nListelemede sorun oluştu: {e}\n') except Exception as e: - print(f'Geçersiz giriş: {e}') - print() + print(f'\nHatalı giriş: {e}\n') + return True + +def erase_school(cur): + try: + school_id = int(input("Silinecek okulun id'si:")) + sql_cmd = f"SELECT school_id, school_name, school_city FROM school WHERE school_id = {school_id}" + cur.execute(sql_cmd) + t = cur.fetchone() + if t is None: + print("\nBu id'ye ilişkin bir okul yok!\n") + return + school_id, school_name, school_city = t + print(f'\n{school_id:<5d}{school_name:<40s}{school_city}\n') + + confirm = input('Bir okulu sildiğiniz zaman o okuldaki tüm öğrencileri de silersiniz' + \ + 'Yukarıdaki okulu silmek istediğine emin misiniz (E)/(H):').lower() + if confirm == 'e': + try: + sql_cmd = f""" + BEGIN TRANSACTION; + DELETE FROM student WHERE school_id = {school_id}; + DELETE FROM school WHERE school_id = {school_id}; + COMMIT; + """ + cur.executescript(sql_cmd) + except sqlite3.Error as e: + cur.connection.rollback() + print(f'Silme işleminde hata oluştu: {e}\n') + print('\n1 kayıt silindi...\n') + else: + print() + + except sqlite3.Error as e: + print(f'Aramada sorun oluştu: {e}\n') + except Exception as e: + print(f'Hatalı giriş: {e}\n') + + return True -try: - main() -except: - pass +def exit_prog(cur): + return False + +def main(): + items_list = [ + ('Okul ekle', add_school), + ('Öğrenci ekle', add_student), + ('Öğrenci listele', list_student), + ('Okul listele', list_school), + ('Öğrenci sil', erase_student), + ('Okul sil', erase_school), + ('Çıkış', exit_prog), + ] + + try: + with sqlite3.connect('school.sqlite') as conn: + cur = conn.cursor() + create_tables(cur) + while True: + option = disp_menu(items_list) + _, f = items_list[option - 1] + if not f(cur): + break + + except sqlite3.Error as e: + print(f'DB Error: {e}') + except Exception as e: + print(e) + +main() + +#------------------------------------------------------------------------------------------------------------------------------------ + 12. Ders 13/04/2025 - Pazar +#------------------------------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------------------------------ Pek çok VTYS kütüphanesi SQL komutlarında "yer tutucu" ya da başka bir deyişle "parametre" kullanımına izin vermektedir. Python'da - yer tutucular iki biçimde bulundurulmaktadır: "?" biçiminde ya da ":isim" biçiminde. "?" yer tutucusu isimsizdir. Ancak ":isim" yer tutucusu - isimlidir. Bu yer tutucular komut içerisinde değermiş gibi kullanılabilirler. Örneğin: + yer tutucular iki biçimde kullanılmaktadır: "?" biçiminde ya da ":isim" biçiminde. "?" yer tutucusu isimsizdir. Ancak ":isim" yer + tutucusu isimlidir. Bu yer tutucular komut içerisinde bir öğe gibi kullanılabilirler. Örneğin: sqlcmd = "INSERT INTO student(student_no, student_name) VALUES(?, ?)" - Burada ilk "?" student_no için yerleştirilecek değeri, ikinci "?" ise student_name için yerleştirilecek değeri belirtmektedir. Aynı komut - şöyle de oluşturulabilirdir: + Burada ilk "?" student_no için yerleştirilecek değeri, ikinci "?" ise student_name için yerleştirilecek değeri belirtmektedir. Aynı + komut şöyle de oluşturulabilirdi: sqlcmd = "INSERT INTO student(student_no, student_name) VALUES(:no, :name)" - Burada :no yer tutucusu student_no ile :name yer tutucusu ise student_name ile eşleştirilmektedir. Pekiyi bu yer tutuculara değerleri nasıl yerleştirilmektedir? - İşte aslında execute isimli metot işletilecek SQL cümlesinin yanı sıra ikinci parametresi ile yer tutucuların değerlerini dolaşılabilir bir nesne - biçiminde almaktadır. Örneğin: + Burada :no yer tutucusu student_no için, :name yer tutucusu ise student_name için yerleştirilecek değeri belirtmektedir. Pekiyi bu + yer tutuculara değerleri nasıl yerleştirilmektedir? İşte aslında Cursor sınıfının execute metodu işletilecek SQL cümlesinin yanı + sıra ikinci parametresi ile yer tutuculara yerleştirilecek değerleri de bizden istemektedir. Eğer yer tutucular "?" işareti ile + belirtilmişse bu durumda execute metodunun ikinci parametresi bir demet ya da liste olmalıdır. Demet ya da liste içerisindeki + elemanlar sırasıyla SQL komutundaki "?" yer tutucularının yerine yerleştirilmektedir. Örneğin: - sqlcmd = "INSERT INTO student(student_no, student_name) VALUES(?, ?)"; - cur.execute(sqlcmd, (4523, "Rasim Özcan")) + sqlcmd = "INSERT INTO student(student_no, student_name, school_id) VALUES(?, ?, ?)"; + cur.execute(sqlcmd, (523, 'Rasim Özcan', 3)) conn.commit() - Eğer yer tutucular isimliyse bu duurmda execute metodunun ikinci parametre bir sözlük nesnesi olamk zorundadır. Sözlüğün anahtarları - yer tutucuların simlerinden değerleri ise ter tutuculara yerleştirilecek değerlerden oluşur. Tabii artık yer tutucuların girilme sırasının bir önemi - kalmamaktadır. Örneğin: + Burada 525 değeri ilk "?" yerine, "Rasim Özcan" değeri ikinci "?" yerine ve 3 değeri ise üçüncü "?" yerine yerleştirilir. execute + metodu bu yerleştirmeyi yaptıktan sonra komutu VTYS'ye göndermektedir. Yerleştirme yapıldıktan sonra SQL komutu şu hale gelecektir: - sqlcmd = "INSERT INTO student(student_no, student_name) VALUES(:no, :name)"; - cur.execute(sqlcmd, {'name': 'Sacit Özyıllmaz', 'no': 7372}) + "INSERT INTO student(student_no, student_name, school_id) VALUES(523, 'Rasim Özcan', 3)" + + Yazsısal değerlerin SQL komutunda tek tırnak içerisine alınmasını execute metodu zaten sağlamaktadır. + + Eğer yer tutucular isimliyse bu durumda execute metodunun ikinci parametresi bir sözlük nesnesi olmak zorundadır. Sözlüğün anahtarları + yer tutucuların isimlerinden değerleri ise ter tutuculara yerleştirilecek değerlerden oluşur. Tabii artık yer tutucuların girilme + sırasının bir önemi kalmamaktadır. Örneğin: + + sqlcmd = "INSERT INTO student(student_no, student_name, school_id) VALUES(:no, :name, :sid)"; + cur.execute(sqlcmd, {'no': 523, 'name': 'Rasim Özcan', 'sid': 3}) conn.commit() - Yer tutucu kullanmanın ne avantajı vardır? İşte her defasında yeniden bir komut yazısı oluşturmak yerine yer tutucularla bir tane komut yazısı - oluşturup hep onu kullanmak çok daha pratik ve etkindir. Yani programcı işin başında programında gerekli SQL komutlarını yer tutucularla oluşturur - sonra da onların değerlerini execute metodunda verir. Örneklerden de gördüğünüz gibi yer tutucu eğer bir string ise onu tek tırnak içerisine programcı - almamaktadır. Yer tutucuyu yerleştiren execute metodu bunu yapmaktadır. + Buradaki isimlerde ':' karakterinin kullanılmadığına dikkat ediniz. + + Pekiyi yer tutucu kullanmanın ne avantajı vardır? İşte her defasında yeniden bir komut yazısı oluşturmak yerine yer tutucularla + bir tane komut yazısı oluşturup hep onu kullanmak çok daha pratik ve etkindir. Yani programcı işin başında programında gerekli + SQL komutlarını yer tutucularla oluşturur sonra da onlar için değerleri execute metodunda belirtir. Bir kez daha anımsatmak istiyoruz: + Örneklerden de gördüğünüz gibi yer tutucu eğer bir string ise onu tek tırnak içerisine programcı almamaktadır. Yer tutucuyu yerleştiren + execute metodu bunu yapmaktadır. + + Yer tutucuların işlevlerinin Python'a son versiyonlarla eklenen f'li string'lerle (string enterpolasyonuyla) sağlanabileceğini + düşünebilirsiniz. Ancak f'li string'ler programın akışı o noktaya geldiğinde bir kez oluşturulmaktadır. Örneğin: + + student_no = 123 + sql_cmd = f"SELECT * FROM student WHERE student_no = {student_no}" + + print(sql_cmd) # SELECT * FROM student WHERE student_no = 123 + student_no = 321 + print(sql_cmd) # SELECT * FROM student WHERE student_no = 123 #------------------------------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------------------------------ - execute ve executescript metotlarının dışında Cursor sınıfının bir de executemany isimli metodu vardır. Bu metodun kullanılabilmesi için - SQL komut yazısının yer tutucuyla oluşturulması gerekir. executemany metodunun ikinci parametresi bir demet listesi ya da bir sözlük listesi - olabilir. (Burada liste ya da demet yerine herhangi bir dolaşılabilir nesne de kullanılabilir.) Metot çağrıldığında dolaşılabilir nesnedeki - elemanlar tekl tek yer tutuculara yerleştirilip komut birden fazla kez uygulanmaktadır. Örneğin: + execute ve executescript metotlarının dışında Cursor sınıfının bir de executemany isimli metodu vardır. Bu metodun kullanılabilmesi + için SQL komut yazısının yer tutucuyla oluşturulması gerekir. executemany metodunun ikinci parametresi demetlerden ya da sözlüklerden + oluşan dolaşılabilir bir nesne olabilir. Metot çağrıldığında dolaşılabilir nesnedeki elemanlar tek tek yer tutuculara yerleştirilip + komut birden fazla kez uygulanmaktadır. Örneğin: - sqlcmd = "INSERT INTO student(student_no, student_name) VALUES(?, ?)"; - cur.executemany(sqlcmd, [(8984, 'Kazım Tanış'), (6345, 'Fatma Aslan'), (8491, 'Hasan Kartal')]) + sql_cmd = "INSERT INTO student(student_name, student_no, school_id) VALUES(?, ?, ?)" + cur.executemany(sql_cmd, [('Tayyar Altınkulaç', 456, 3), ('Salim Dündar', 632, 2)]) conn.commit() - Yer tutucvular isimliyse executemany metodunda bir sözlük listesi verilebilir. Örneğin: + Yukarıdaki executemany birden fazla execute ile aynı işleve sahiptir: - sqlcmd = "INSERT INTO student(student_no, student_name) VALUES(:no, :name)"; - cur.executemany(sqlcmd, [{'no': 8984, 'name': 'Kazım Tanış'}, {'no': 6345, 'name': 'Fatma Aslan'}, {'no': 8491, 'name': 'Hasan Kartal'}]) + sql_cmd = "INSERT INTO student(student_name, student_no, school_id) VALUES(?, ?, ?)" + cur.execute(sql_cmd, ('Tayyar Altınkulaç', 456, 3)) + cur.execute(sql_cmd, ('Salim Dündar', 632, 2)) conn.commit() - executemany sayesinde bazı pratik işlemler yapılabilmektedir. Örneğin bir CSV dosyasından okuma yapan csv.reader fonksiyonu bize dolaşılabilir bir nesne - verir. Sonra her dolaşımda CSV dosyasındaki bir satır elde edilir. Biz doğrudan bu reader nesnesini executemany metodunun ikinci parametresine geçirebiliriz. Örneğin: + Yer tutucular isimliyse executemany metodunda bir sözlük listesi ya da sözlüklerden oluşan bir demet (aslında genel olarak sözlüklerden + oluşan dolaşılabilir bir nesne) verilebilir. Örneğin: + + sql_cmd = "INSERT INTO student(student_name, student_no, school_id) VALUES(:name, :no, :sid)" + cur.executemany(sql_cmd, [{'name': 'Gökhan Abur', 'no': 387, 'sid': 5}, {'name': 'Timur Selçuk', 'no': 743, 'sid': 2}]) + conn.commit() + + executemany sayesinde bazı işlemler pratik biçimde yapılabilmektedir. Örneğin bir CSV dosyasından okuma yapan standart csv modülündeki + reader fonksiyonu bize dolaşılabilir bir nesne verir. Sonra her dolaşımda CSV dosyasındaki bir satır elde edilir. Biz doğrudan bu reader + fonksiyonunun verdiği nesneyi executemany metodunun ikinci parametresine geçirebiliriz. Örneğin: import sqlite3 import csv try: - with sqlite3.connect('school.sqlite') as conn: + with sqlite3.connect('school.sqlite') as conn, open('student.csv') as f: cur = conn.cursor() - sqlcmd = "INSERT INTO student(student_no, student_name) VALUES(?, ?)"; - with open('student.csv') as f: - cur.executemany(sqlcmd, csv.reader(f)) - conn.commit() + sql_cmd = "INSERT INTO student(student_name, student_no, school_id) VALUES(?, ?, ?)" + cur.executemany(sql_cmd, csv.reader(f)) + conn.commit() except sqlite3.Error as e: print(e) + except Exception as e: + print(e) +#------------------------------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------------------------------ Tabii yer tutucular yalnızca INSERT INTO komutunda değil diğer komutlarda da kullanılabilmektedir. Örneğin: @@ -3081,75 +3169,114 @@ except: cur.executemany(sqlcmd, [(9981, ), (8984, )]) conn.commit() except sqlite3.Error as e: - print(e) - -#------------------------------------------------------------------------------------------------------------------------------------ - -#------------------------------------------------------------------------------------------------------------------------------------ - 11. Ders 16/01/2023 - Pazartesi + print(e) #------------------------------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------------------------------ Daha önceden de belirttiğimiz gibi VTYS'lerin pek çok built-in fonksiyonları vardır. Bu fonksiyonları sorgulamalarda kullanabiliriz. - Aşağıdai örnekte "student" tablosundaki öğrencilerin isimlerinin uzunlukları elde edilmiştir. + Aşağıda built-in length fonksiyonunun kullanımına ilişkin bir örnek görüyorsunuz: + + sql_cmd = "SELECT * FROM student WHERE length(student_name) = ?" + cur.execute(sql_cmd, (10, )) + students = cur.fetchall() + for student in students: + print(student) + + Burada adı soyadı 10 karakter olan öğrencilerin listesi elde edilmektedir. #------------------------------------------------------------------------------------------------------------------------------------ import sqlite3 + try: with sqlite3.connect('school.sqlite') as conn: - cur = conn.cursor() - sqlcmd = "SELECT length(student_name) FROM student" - for n, in cur.execute(sqlcmd): - print(n) + cur = conn.cursor() + sql_cmd = "SELECT * FROM student WHERE length(student_name) = ?" + cur.execute(sql_cmd, (10, )) + students = cur.fetchall() + for student in students: + print(student) except sqlite3.Error as e: print(e) +except Exception as e: + print(e) #------------------------------------------------------------------------------------------------------------------------------------ - Aşağıdaki örnekte de ad ve soyadları 10 karakter olan öğrenciler elde edilmiştir. + Tabii biz SELECT cümlesinde veirtabanındaki sütun isimlerini bu fonksiyonlara sokarak sütun isimleri yerine bunların çıktılarını + da elde edebiliriz. Örneğin "school.sqlite" veritabaınındaki öğrencilerin ad ve soyadlarının uzublukları aşağıdaki gibi elde + edilebilir: + + sql_cmd = "SELECT length(student_name) FROM student" + cur.execute(sql_cmd) + students = cur.fetchall() + for student in students: + print(student) #------------------------------------------------------------------------------------------------------------------------------------ import sqlite3 + try: with sqlite3.connect('school.sqlite') as conn: - cur = conn.cursor() - sqlcmd = "SELECT student_name FROM student WHERE length(student_name)=10" - for n, in cur.execute(sqlcmd): - print(n) + cur = conn.cursor() + sql_cmd = "SELECT length(student_name) FROM student" + cur.execute(sql_cmd) + students = cur.fetchall() + for student in students: + print(student) except sqlite3.Error as e: print(e) +except Exception as e: + print(e) #------------------------------------------------------------------------------------------------------------------------------------ - Kendimizn yazdığı bir Python fonksiyonunu SQL komutunda da kullanabiliriz. Bunun için kullanılacak olan fonksiyonun Connection nesnesinin create_function - isimli metoduyla yaratılması gerekir. create_function metodunun parametrik yapısı şöyledir: + Bazı built-in fonksiyonlar pek çok VTYS'de aynı biçimde bulunmaktadır. Ancak pek çok fonksiyon da VTYS'ye özgüdür. Bu nedenle hangi + VTYS'de çalışıyorsanız o VTYS'ye özgü fonksiyonları o VTYS'nin kendi dokümanlarından elde edebilirsiniz. + + Kendimizin yazdığı bir Python fonksiyonunu SQL komutunda da kullanabiliriz. Bunun için kullanılacak olan fonksiyonun Connection + nesnesinin create_function isimli metoduyla yaratılması gerekir. create_function metodunun parametrik yapısı şöyledir: create_function(name, narg, func, *, deterministic=False) - Metodun birinci parametresi fonksiyonun SQL içerisinden kullanılacak ismini belirtmektedir. Bu ismin fonksiyonun gerçek ismiyle aynı olması - gerekmez. İkinci parametre fonksiyonun parametre sayısını belirtmektedir. Üçüncü parametre de fonksiyon Python'daki ismini belirtir. + Metodun birinci parametresi fonksiyonun SQL içerisinden kullanılacak ismini belirtmektedir. Bu ismin fonksiyonun gerçek ismiyle + aynı olması gerekmez. İkinci parametre fonksiyonun parametre sayısını, üçüncü parametre ise Python fonksiyon nesnesini belirtmektedir. + Biz bu üçüncü parametreye çağrılmasını istediğimiz fonksiyonun ismini girebiliriz. create_function fonksiyonunu çağırdıktan sonra + artık biz belirlediğimiz bu fonksiyon ismini SQL komutunda kullanabiliriz. Fonksiyon SQL komutunda kullanıldığında komutta belirtilen + sütun bilgileri belirlenen fonksiyona parametre olarak aktarılacaktır. Örneğin biz komutta bu fonksiyona student_name ve student_no + sütunlarını argüman olarak verirsek student_name sütunu fonksiyona str olarak, student_no sütunu ise int olarak aktarılacacaktır. + Bu biçimde belirlediğimiz fonksiyon SQL komutu uygulandığında fonksiyonun geri döndürdüğü değer komutta kullanılmaktadır. SQL büyük + harf küçük harf duyarlılığı olan (case sensitive) bir dil değildir. Yani örneğin biz create_function metoduna fonksiyon ismini küçük + harfle versek bile onu komut içerisimde büyük harfle kullanabiliriz. + Örneğin: - Fonksiyona SQL komutunda geçirilen sütun parametreleri fonksiyonun içerisinden doğrudan kullanılabilmektedir. Parametrenin türü sütunun - türüyle ilgili olmaktadır. Örneğin student_name sütunu fonksiyona str parametresi olarak geçirilmektedir. + sql_cmd = "SELECT myfunc(student_name), student_no FROM student" - Aşağıdaki örnekte myfunc isimli fonksiyon SQL içerisinde reverse ismiyle kullanılmıştır. + Bu SQL cümlesi çalıştırıldığında student_name sütunundaki her isim önce myfunc fonksiyonuna parametre olarak geçirilecek, sonra + bu fonksiyonun geri dönüş değeri elde edilip SELECT tarafından işlenecektir. + + Aşağıdaki örnekte foo isimli fonksiyon SQL içerisinde "myfunc" ismiyle kullanılmaktadır. Bu örnekte öürencinin ismi ve numarası + birleştirilerek tek bir sütunmuş gibi elde edilmektedir. #------------------------------------------------------------------------------------------------------------------------------------ import sqlite3 -def myfunc(name, no): - return name[.-1] + ' ' + str(no)[.-1] +def foo(name, no): + return name + ', ' + str(no) try: with sqlite3.connect('school.sqlite') as conn: - conn.create_function('reverse', 2, myfunc) cur = conn.cursor() - - sqlcmd = "SELECT reverse(student_name, student_no) FROM student" - for n, in cur.execute(sqlcmd): - print(n) + sql_cmd = "SELECT myfunc(student_name, student_no) FROM student" + conn.create_function('myfunc', 2, foo) + + cur.execute(sql_cmd) + students = cur.fetchall() + for name, in students: + print(name) except sqlite3.Error as e: print(e) +except Exception as e: + print(e) - + #------------------------------------------------------------------------------------------------------------------------------------ Aşağıdaki örnekte zaten var olan length built-in fonksiyonunun mylength ismiyle başka bir versiyonu yazılmıştır. #------------------------------------------------------------------------------------------------------------------------------------ @@ -3171,9 +3298,9 @@ except sqlite3.Error as e: print(e) #------------------------------------------------------------------------------------------------------------------------------------ - Tabii VTYS'de zaten var olan built-in fonksiyonları gereksiz bir biçimde yeniden yazmayınız. Çalıştığınız VTYS'deki - built-in fonksiyonların listesini dokümanlardan elde edip incelemelisiniz. Örneğin substr isimli SqLite fonksiyonu - belli bir indeksten itibaren (ilk indeks 1'dir) n tane karakteri elde etmektedir. + Tabii VTYS'de zaten var olan built-in fonksiyonları gereksiz bir biçimde yeniden yazmayınız. Çalıştığınız VTYS'deki built-in + fonksiyonların listesini dokümanlardan elde edip incelemelisiniz. Örneğin substr isimli SqLite fonksiyonu belli bir indeksten itibaren + (ilk indeks 1'dir) n tane karakteri elde etmektedir. #------------------------------------------------------------------------------------------------------------------------------------ import sqlite3 @@ -3214,7 +3341,8 @@ except Exception as e: print(e) #------------------------------------------------------------------------------------------------------------------------------------ - text_factory örnek özniteliği default durumda str fonksiyonunu almaktadır. Yani SELECT edilen yazısal sütunlar str fonksiyonuna sokulmaktadır. + text_factory örnek özniteliği default durumda str fonksiyonunu almaktadır. Yani SELECT edilen yazısal sütunlar str fonksiyonuna + sokulmaktadır. #------------------------------------------------------------------------------------------------------------------------------------ import sqlite3