Veritabanı Veri Güncelleme Mantığı

Veritabanında bir veri güncellemek istediğimizde temel olarak "UPDATE tablo_adi SET sütun_adi = yeni_deger WHERE id = 2" yazıyoruz. Lakin merak ettiğim husus şu:

Programlarda bir veri değiştirdiğimizde (Mesela Kullanıcı adı) bizim satırı komple yeniden mi işliyor, yoksa sadece kullanıcı adını mı işliyor?

tek tek işliyorsa Kullanıcı adı dışında birkaç veri daha değiştirdik bu sefer bunları nasıl işliyor?

Bunlar için ayrı ayrı fonksiyonlar yapmıyorlardır heralde.

Kim?

Ikisini de yapmak icin gecerli sebepler var, ikisi de olabilir.

Tek tek. Degistirdikce isleyebilir.

Fonksiyon bu seviyede bir dusunce icin yanlis soyutlama katmani sanki. Kredi faiz oranlari konusurken “paralari tek tek saymiyorlardir herhalde” demek gibi.

Nasil bir mimariye karar verdik ki fonksiyon sayisi fazla geldi?

3 Beğeni

Eyvallah hocam youtube’dan konu hakkında birkaç video seyrettim, onları birbiri ile harmanladım biraz şimdi olayı daha iyi anladım. (Normalde video seyretme alışkanlığım yoktur) Videoları bulamadım. Newipe kullanıyor ve geçmiş tutmuyorum. Videolarda hem İngilizce, hem de baaşlıkları konudan bağımsızdı tam hatırlamıyorum. Bu sebeple videoları paylaşamıyorum.

Lakin kafama şimdi de FOREIGN KEY takıldı. Ne yaptıysam olması gerektiği gibi çalıştıramadım. Hangi denediğimi örnek atsam bilemiyorum ama şu daha uygun gibi:

SQL sorgu da (DB Browser) da SQL kodunu yürütünce hata veriyorda, aynısını pythonda yapınca olmayan staff_id’i ekliyor. Yani hata vermiyor. (Hop ne ediysun sen yok Staff listesinde böyle bir id demiyor.) Aradım taradım olan çoğu kaynağı denedim hiç biri SQL kodunu yazdığımdaki gibi hata vermiyor, yani olmayan id’i yazınca bile ekliyor.

    db.execute("CREATE TABLE IF NOT EXISTS User (\
        id INTEGER PRIMARY KEY AUTOINCREMENT,\
        username varchar,\
        email varchar,\
        password text,\
        staff_id INTEGER,\
        statu_id INTEGER,\
        FOREIGN KEY(staff_id) REFERENCES Staff(id),\
        FOREIGN KEY(statu_id) REFERENCES Statu(id))"
    )

    db.execute("CREATE TABLE IF NOT EXISTS Staff (\
    id INTEGER PRIMARY KEY AUTOINCREMENT,\
     name varchar,\
      surname varchar,\
       phone INTEGER)"
    )

Python kodu

    def add_user(self, username, email, password, staff_id, statu_id):
        database.db.execute("INSERT INTO user VALUES (NULL, ?, ?, ?, ?, ?)",
                            (username, email, password, staff_id, statu_id))
        database.db.commit()
   Dene().add_user("dene1", "dene2@yandex.com", "dene3", 1, 7)

> 7 diye bir id adresi yok normal şartta hata vermesi gerekmez mi?


SQL KODU

INSERT INTO user VALUES (NULL, "iue", "iuea", "uieauea", 8, 9)

SQL ÇIKTISI

Yürütme hatalarla tamamlandı.
Sonuç: FOREIGN KEY constraint failed
1. satırda:
INSERT INTO user VALUES (NULL, "iue", "iuea", "uieauea", 8, 9)

Burada id tanımlıyorsun, NULL geçemezsin. Boş bırak kendi artan bir id o.

1 Beğeni

Boş bırakınca da şu hataları veriyor:

    database.db.execute("INSERT INTO user VALUES (, ?, ?, ?, ?, ?)",
sqlite3.OperationalError: near ",": syntax error
    database.db.execute("INSERT INTO user VALUES (?, ?, ?, ?, ?)",
sqlite3.OperationalError: table user has 6 columns but 5 values were supplied
    database.db.execute("INSERT INTO user VALUES ( ?, ?, ?, ?, ?, ?)",
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 6, and there are 5 supplied.

kısmında user dan sonra girmek istediğin tablo alanlarını ekle , user(isim, password, vs) gibi

  1. Hangi server? Foreign key destegi var mi?
  2. Foreign key constraint’leri ne zaman enforce ediliyor? Cogu duzgun implementasyonda transaction icinde violate edebilirsin. Oteki turlu birbirini refere eden iki rowu yaratmak veya silmek mumkun olmaz.
  3. Constraint’e ters row’u yaratabilmek onemli degil, baskalarinin gormesi onemli. Disaridan gorunur olmasi, “tabloya girmesi”.
  4. Kolon bos birakmak icin kolon isimlerinin de yazildigi INSERT sentaksini kullanmak lazim.

https://www.sqlite.com/foreignkeys.html

Bu tarz kaynaklardan bakarak yapmaya çalışıyorum hocam, dediğiniz şeylerin çoğunu bilmiyorum doğrusu, kaynak aradım ama çok değişik şeyler çıktı. Uyguladıklarımda oldu ama nedense o hataları alamadım.

SQL de kod çalıştırdım user de kullanılan statu’yu sildim. Yani bunu da çalıştıramadım. Ama eklmede olmayan statu’yu eklemiyor o ne gariptir ki çalıştı.

    db.execute("CREATE TABLE IF NOT EXISTS User(\
        id INTEGER PRIMARY KEY AUTOINCREMENT,\
        username varchar,\
        email varchar,\
        password text,\
        staff_id INTEGER,\
        statu_id INTEGER,\
        CONSTRAINT fk_StaffUser FOREIGN KEY(staff_id) REFERENCES Staff(id) ON DELETE CASCADE,\
        CONSTRAINT fk_StatuUser FOREIGN KEY(statu_id) REFERENCES Statu(id) ON DELETE CASCADE)"
    )

En son bunu denedim. Bu da hata vermedi.

SQL kodu: PRAGMA foreign_keys;
Çıktı: 1

Bu da olmadı. Python’da eksik yaptığım birşey var bence veritabanında eklemiyor ama Python kodu ekliyor.

Hocam DB Browserdan SQL kodu girince herşey yolunda ama Pythonda yapınca mübarek kuralları çiğniyor. Birşey anlamadım ben bu işten, onun ondan ne farkı var ki…

:+1: bu en dogrusu

DB Browser PRAGMA foreign_keys = ON; ile FK’lari aciyor mu? Acmiyorsa FK violation almaz…

Takip etmekte zorlaniyorum, kodun tamamini atar misin? Gerekiyorsa database’le beraber. (Database’i onu yaratan SQL script’ine (CREATE TABLEx + INSERTy) donusturmek mumkun, olmadi dosya olarak upload etmek gerekebilir)

Hocam DB Browser SQL kodlarının tümünü sorunsuz çalıştırıyor, veri de getiriyor bunda hiçbir problem yok.
Python da bunların hepsini yapıyor işleme, getirme gibi durumlarda sorun yok. Benim anlamadığım ve takıldığım tek nokta ‘1 admin’, ‘2 Standart’ statüleri var. bunların id numaralarını kullanıcı eklerken girerken eğer oldu da kodda hata veya açık oldu id yerine statuda olmayan ‘3’ girildi işte bu koşulda hata vermesi.

SQL kodda olmayan bir id girilince eklemiyor ama Python da aynı şeyi girince ekliyor. Yani hata vermiyor.
Basitçe sorunum bu aslında sorgu ile yaparım bunu ama takıldım işte veritabanı böyle bir şeyi destekler ve uyarken, kod neden buna uymuyor diye.

Kodun ise atılacak bir tarafı yok aslında basitçe veritabanı oluşturduk, deneyerek de veri giriyorum.

db = sqlite3.connect("database.db")

db.execute("CREATE TABLE IF NOT EXISTS User (\
        id INTEGER PRIMARY KEY AUTOINCREMENT,\
        username varchar,\
        email varchar,\
        password text,\
        staff_id INTEGER,\
        statu_id INTEGER,\
        FOREIGN KEY(staff_id) REFERENCES Staff(id),\
        FOREIGN KEY(statu_id) REFERENCES Statu(id))"
    )

    db.execute("CREATE TABLE IF NOT EXISTS Staff (\
    id INTEGER PRIMARY KEY AUTOINCREMENT,\
     name varchar,\
      surname varchar,\
       phone INTEGER)"
    )
    db.commit()
    def add_user(self, username, email, password):
        database.db.execute("INSERT INTO user(username, email, password) VALUES (?, ?, ?)",
                            (username, email, password))
        database.db.commit()

    def add_statu(self, name):
        database.db.execute("INSERT INTO statu VALUES (NULL,?)", (name, ))
        database.db.commit()
database.db.execute("INSERT INTO user VALUES ("d1", "d2", "d3", "5", "8") ")

Dosya diğer bilgisayarda kaldı. parça parça etraftan toplayarak birleştirmeye çalıştım. Kod böyle birşeydi.
Son kodu yeni yazdm böyle böyle deniyorum. İkinci kodu kullanmıyorum henüz. Birinci kod ise Telegramdan arkadaşlara atmıştım parça parça topladım.

Olabilir, kodu gormek lazim.

:person_shrugging: kodu gormeden bir sey soyleyemeyiz.

Yukarida DB semasi (yaratan kod) var, guzel, ama onun disinda islem yapan bir sey yok.

import sqlite3

database = sqlite3.connect("/home/kaninym/Masaüstü/drnm.db")

database.execute("CREATE TABLE IF NOT EXISTS User(\
    id INTEGER PRIMARY KEY AUTOINCREMENT,\
    username varchar,\
    email varchar,\
    password text,\
    statu_id INTEGER,\
    FOREIGN KEY(statu_id) REFERENCES Statu(id))"
)

database.execute("CREATE TABLE IF NOT EXISTS Statu (\
    id INTEGER PRIMARY KEY AUTOINCREMENT,\
     name varchar)"
)

#database.execute('INSERT INTO Statu(name) VALUES ("Deneme")')
#database.execute('INSERT INTO user(username, email, password, statu_id) VALUES ("d1", "d2", "d3", "1")')
#
#database.commit()

database.execute('DELETE FROM Statu WHERE id = "1"')

database.commit()

Haaah super. Soyle:

import sqlite3

database = sqlite3.connect("/tmp/hede.sqlite3")
database.execute("PRAGMA foreign_keys = 1") # Sadece bu satiri ekledim

database.execute("CREATE TABLE IF NOT EXISTS User(\
    id INTEGER PRIMARY KEY AUTOINCREMENT,\
    username varchar,\
    email varchar,\
    password text,\
    statu_id INTEGER,\
    FOREIGN KEY(statu_id) REFERENCES Statu(id))"
)

database.execute("CREATE TABLE IF NOT EXISTS Statu (\
    id INTEGER PRIMARY KEY AUTOINCREMENT,\
     name varchar)"
)

database.execute('INSERT INTO Statu(name) VALUES ("Deneme")')
database.execute('INSERT INTO user(username, email, password, statu_id) VALUES ("d1", "d2", "d3", "1")')

database.commit()

database.execute('DELETE FROM Statu WHERE id = "1"')

database.commit()
Traceback (most recent call last):
  File "a.py", line 25, in <module>
    database.execute('DELETE FROM Statu WHERE id = "1"')
sqlite3.IntegrityError: FOREIGN KEY constraint failed
1 Beğeni

Hocam çok teşekkür ederim. Allah’a şükür :slight_smile:

PRAGMA’yı bilmiyordum bunu da öğrenmiş oldum. Allah sizden razı olsun.

Hocam boş string için var mı böyle birşey. Boş bırakıldığında NULL olarak düşmediğini farkettim de.

E

?

Bos ile NULL farkli seyler.

CHECK constraint kullanabilirsin. CHECK strlen(kolon) > 0 diye. 1) SQLite’ta var mi bilmiyorum. 2) String uzunluk fonksiyonunun adini da bilmiyorum, attim.

1 Beğeni

Hocam hiç o şekilde kullanıldığını bilmiyordum. Veritabanı ayarlarını görmemize yarayan birşey sanıyordum onu. Bu arada programda o ayar zaten 1 görünüyordu harbiden. Pythonda da tanımlamak gerekiyormuş demek ki.

CHECK(name <> '')