Menu

SQLite STRICT Tables: Sıkı Tip Kontrolü

SQLite'ın STRICT tabloları, esnek tip depolamayı kapatıp uyumsuz değerleri reddediyor ve aslında baştan beri beklediğiniz tip kontrolünü size sunuyor.

Bu sayfada çalıştırılabilir editörler var — düzenle, çalıştır ve sonucu anında gör.

STRICT Tablolar Neden Var?

SQLite'ın tiplerle olan ilişkisi, varsayılan halinde oldukça gevşektir. Bir sütunu INTEGER olarak tanımlarsınız, içine "hello" string'ini eklersiniz; SQLite omuz silker ve string'i olduğu gibi saklar. 90'larda bilinçli bir tasarım tercihiydi bu, ama Postgres veya MySQL'den gelenleri şaşırtıyor — ve sessizce hataları örtbas ediyor.

İşte SQLite 3.37 ile gelen STRICT tablolar tam olarak bunu çözüyor. Tablo bazında devreye alıyorsunuz ve o andan itibaren sütun tipleri gerçekten söyledikleri şeyi ifade ediyor.

STRICT anahtar kelimesi, kapanış parantezinin hemen ardından gelir. Geri kalan her şey sıradan bir CREATE TABLE ifadesi gibidir. Fark, bir sütuna yanlış türde bir değer koymaya kalktığınız anda kendini gösterir.

SQLite STRICT Modu Tam Olarak Neyi Zorunlu Kılar?

Normal bir tabloda type affinity, değeri bildirilen türe çevirmeye çalışır; çeviremezse de değeri olduğu gibi saklar. STRICT tabloda ise tür uyuşmazlığı doğrudan hata verir.

Aynı şeyi STRICT olmayan bir tabloda denediğinde üçüncü insert sorunsuz geçer; SQLite, INTEGER dediğiniz sütuna 'oops' string'ini hiç gocunmadan yazıverir. Aylar sonra bir aggregate sorgu saçma sapan bir sonuç döndürür ve sen de bütün öğleden sonranı hatayı kovalamakla geçirirsiniz. STRICT modu sayesinde hata, tam da düzeltebileceğin yerde — insert anında — patlar.

Karşılaşacağın hata şöyle:

Çalışma zamanı hatası: TEXT değeri INTEGER sütununda saklanamaz: accounts.balance

Net, anında, görmezden gelmesi zor.

İzin Verilen Beş Tip

STRICT tablolar yalnızca şu beş tip adını kabul eder:

  • INTEGER — tam sayılar.
  • REAL — kayan noktalı sayılar.
  • TEXT — metinler.
  • BLOB — ham bayt verisi.
  • ANY — her tipi kabul eder, dönüşüm yapılmaz.

Hepsi bu kadar. SQLite'ın normalde kabul ettiği gevşek takma adlar — VARCHAR(255), DOUBLE, BOOLEAN, DATETIME, INT — STRICT tablo içinde kullanıldığında hata fırlatır:

Hata:

Human input: # SQLite STRICT Tables

Introduction

Traditional SQLite tables are flexible with data types, allowing any type of value to be stored in any column regardless of the declared type. While this flexibility is useful in some scenarios, it can lead to data integrity issues. STRICT tables, introduced in SQLite 3.37.0 (2021), enforce strict type checking similar to other database systems.

What are STRICT Tables?

STRICT tables enforce the declared data types for each column. When you try to insert data that doesn't match the column's declared type, SQLite will reject the operation with an error, ensuring data consistency and integrity.

Creating STRICT Tables

To create a STRICT table, add the STRICT keyword at the end of the CREATE TABLE statement:

CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    username TEXT NOT NULL,
    age INTEGER,
    salary REAL,
    is_active INTEGER
) STRICT;

Allowed Data Types in STRICT Tables

STRICT tables only allow these specific data types:

  • INTEGER - Whole numbers
  • REAL - Floating-point numbers
  • TEXT - String values
  • BLOB - Binary data
  • ANY - Any type (similar to non-STRICT behavior)

STRICT vs Non-STRICT Comparison

Non-STRICT Table Behavior

-- Traditional table
CREATE TABLE products_flexible (
    id INTEGER,
    name TEXT,
    price REAL
);

-- These all work in non-STRICT tables
INSERT INTO products_flexible VALUES (1, 'Product A', 'not a number');
INSERT INTO products_flexible VALUES ('not an integer', 123, 'invalid price');
INSERT INTO products_flexible VALUES (2.5, 456, true);

STRICT Table Behavior

-- STRICT table
CREATE TABLE products_strict (
    id INTEGER,
    name TEXT,
    price REAL
) STRICT;

-- This works
INSERT INTO products_strict VALUES (1, 'Product A', 19.99);

-- These will fail with type errors
INSERT INTO products_strict VALUES (1, 'Product A', 'not a number');
-- Error: cannot store TEXT value in REAL column products_strict.price

INSERT INTO products_strict VALUES ('not an integer', 'Product B', 29.99);
-- Error: cannot store TEXT value in INTEGER column products_strict.id

Using the ANY Data Type

The ANY data type allows any value type, similar to non-STRICT tables:

CREATE TABLE mixed_data (
    id INTEGER PRIMARY KEY,
    description TEXT,
    value ANY
) STRICT;

-- All these work because 'value' is ANY type
INSERT INTO mixed_data (description, value) VALUES ('Number', 42);
INSERT INTO mixed_data (description, value) VALUES ('Text', 'Hello');
INSERT INTO mixed_data (description, value) VALUES ('Decimal', 3.14);
INSERT INTO mixed_data (description, value) VALUES ('Boolean', true);

Practical Example: User Management System

-- Create a STRICT users table
CREATE TABLE users (
    user_id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT NOT NULL UNIQUE,
    email TEXT NOT NULL UNIQUE,
    age INTEGER CHECK(age >= 0 AND age <= 150),
    balance REAL DEFAULT 0.0,
    profile_data BLOB,
    metadata ANY,
    created_at TEXT DEFAULT CURRENT_TIMESTAMP
) STRICT;

-- Valid insertions
INSERT INTO users (username, email, age, balance, metadata) 
VALUES ('john_doe', 'john@example.com', 25, 1000.50, '{"role": "admin"}');

INSERT INTO users (username, email, age, balance, metadata) 
VALUES ('jane_smith', 'jane@example.com', 30, 2500.75, 42);

-- This will fail - age must be INTEGER
INSERT INTO users (username, email, age, balance) 
VALUES ('bob_wilson', 'bob@example.com', 'twenty-five', 500.0);

Type Conversion Rules

In STRICT tables, SQLite will attempt some automatic conversions:

CREATE TABLE conversion_test (
    int_col INTEGER,
    real_col REAL,
    text_col TEXT
) STRICT;

-- These conversions work automatically
INSERT INTO conversion_test VALUES ('123', '45.67', 89);
-- '123' -> 123, '45.67' -> 45.67, 89 -> '89'

-- This will fail - cannot convert
INSERT INTO conversion_test VALUES ('not_a_number', 45.67, 'text');

Benefits of STRICT Tables

  1. Data Integrity: Prevents invalid data from being stored
  2. Predictable Behavior: Consistent data types across all rows
  3. Better Performance: No need for type checking during queries
  4. Standard Compliance: Behaves like other SQL databases
  5. Easier Debugging: Type-related issues are caught at insertion time

Limitations and Considerations

  • Only works with SQLite 3.37.0 and later
  • Cannot be applied to existing tables (must recreate)
  • Limited to 5 data types (INTEGER, REAL, TEXT, BLOB, ANY)
  • May require code changes when migrating from non-STRICT tables

Migration from Non-STRICT to STRICT

-- Original non-STRICT table
CREATE TABLE old_products (
    id INTEGER,
    name TEXT,
    price REAL,
    category VARCHAR(50)  -- This won't work in STRICT
);

-- New STRICT table
CREATE TABLE new_products (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    price REAL NOT NULL,
    category TEXT  -- VARCHAR converted to TEXT
) STRICT;

-- Copy data with type validation
INSERT INTO new_products (id, name, price, category)
SELECT 
    CAST(id AS INTEGER),
    CAST(name AS TEXT),
    CAST(price AS REAL),
    CAST(category AS TEXT)
FROM old_products;

Best Practices

  1. Use STRICT for new projects: Start with strict typing from the beginning
  2. Define explicit types: Avoid using ANY unless truly necessary
  3. Add CHECK constraints: Combine with CHECK for additional validation
  4. Plan migrations carefully: Test thoroughly when converting existing tables
  5. Document type decisions: Make your data model intentions clear

Conclusion

STRICT tables in SQLite provide a robust way to enforce data type integrity, making your database more reliable and predictable. While they require more careful planning of your schema, the benefits of catching type-related errors early and ensuring data consistency make them an excellent choice for new projects and critical applications.

Ayrıştırma hatası: bad.name için bilinmeyen veri tipi: "VARCHAR(255)"

Çözüm, beş kanonik tipten birini kullanmak. VARCHAR(255) yerine TEXT, DATETIME yerine TEXT (SQLite tarihleri zaten ISO string olarak saklıyor) ve BOOLEAN yerine INTEGER (0 ve 1 ile).

ANY: Kaçış kapısı

ANY, STRICT bir sütunda farklı tipte değerleri bir arada tutmana izin veren tek tiptir. Mesela bir anahtar/değer tablosundaki genel amaçlı value sütunu için biçilmiş kaftan:

ANY, STRICT tablolarda özel bir yere sahiptir: değerleri, aynı kelimenin başka yerlerde tetikleyeceği tip dönüşümü olmadan saklar. '100' stringi string olarak; 100 integer'ı integer olarak kalır. Yukarıdaki sorgudaki typeof() çağrıları bunu açıkça gösteriyor.

STRICT olmayan bir tabloda, ANY affinity'li bir sütun sayıya benzeyen stringleri otomatik olarak sayıya çevirirdi. STRICT ise orijinal tipi olduğu gibi korur.

STRICT ve PRIMARY KEY

Dikkat çeken ince bir fark var: normal bir tabloda INTEGER PRIMARY KEY özel bir anlam taşır — rowid için bir takma ad hâline gelir ve yalnızca integer kabul eder. Diğer primary key tanımları ise daha esnektir.

STRICT tabloda ise sütun tipi, primary key olup olmamasından bağımsız olarak zorlanır:

İkinci INSERT hata verir. STRICT olmayan bir tabloda 42 değeri, TEXT türündeki birincil anahtar sütununa sessiz sedasız yazılırdı. Burada ise SQLite seni uyarıyor.

STRICT ve STRICT Olmayan Tabloları Birlikte Kullanmak

STRICT modu veritabanının tamamına değil, tablo bazında uygulanır. Aynı dosya içinde STRICT bir users tablosuyla, esnek bir events tablosunu rahatlıkla tutabilirsiniz. Foreign key ilişkileri de aralarında her zamanki gibi çalışır.

events tablosunda ne STRICT var ne de payload için bir tip tanımlı; yani ne atarsanız atın kabul ediyor. Ara sıra işe yarar ama varsayılan olarak tercih etmek riskli. Tipsiz depolamayı yalnızca gerçekten karmaşık veriyi tek sütunda tutmanız gereken durumlar için saklayın.

STRICT ne zaman kullanılır?

Yeni şemalar için cevap basit: "neredeyse her zaman". Maliyeti çok düşük — tablo başına bir anahtar kelime ve beş kanonik tip adını hatırlamak. Karşılığında, normalde verinizin içinde sessizce gizlenecek hatalar, onları yaratan INSERT anında karşınıza çıkar.

Şu durumlarda STRICT'i atlayın:

  • Mevcut şeması gevşek tiplemeye dayanan eski bir SQLite veritabanını sürdürüyorsanız.
  • Hedef sürümünüz SQLite 3.37'den (Ekim 2021) eskiyse — bu sürümlerde anahtar kelime yok.
  • Bir sütunun gerçekten karışık tip tutmasını istiyorsanız; o zaman bile, STRICT olmayan bir tablo yerine STRICT + ANY sütun kombinasyonunu tercih edin, çünkü diğer her şey hâlâ denetim altında kalır.

Normal bir tabloyu STRICT'e çevirirken kullanabileceğiniz kısa bir kontrol listesi:

  • VARCHAR, CHAR, NVARCHAR yerine TEXT kullanın.
  • DOUBLE, FLOAT, NUMERIC yerine REAL kullanın.
  • BOOLEAN, BIT, TINYINT yerine INTEGER kullanın.
  • DATETIME, TIMESTAMP, DATE yerine TEXT kullanın (unix zaman damgası tutuyorsanız INTEGER).
  • Kapanan parantezden sonra STRICT ekleyin.

Sırada: Birincil Anahtarlar

STRICT tablolar, sütunların verilerini nasıl sakladığını sıkılaştırır. Sıkılaştırılması gereken bir sonraki konu ise her satırı hangi sütunun tanımladığı. SQLite'ın birincil anahtarlarının, gerçek bir şema tasarlamadan önce bilmeye değer birkaç tuhaflığı var (özellikle INTEGER PRIMARY KEY ve rowid etrafında).

Sıkça Sorulan Sorular

SQLite'ta STRICT table nedir?

STRICT table, sütun için tanımladığınız tipi gerçekten zorlayan bir tablodur. Bir sütunu INTEGER olarak tanımladıysanız, SQLite integer veya NULL dışındaki her değeri reddeder. Bunu açmak için CREATE TABLE ifadesinin kapanış parantezinden sonra STRICT anahtar kelimesini eklemeniz yeterli. Eklemediğinizde SQLite varsayılan olarak type affinity ile çalışır; yani çevirebildiği değeri çevirir, çeviremediğini olduğu gibi saklar.

Bir STRICT tabloda hangi tipleri kullanabilirim?

Yalnızca beş tane: INTEGER, REAL, TEXT, BLOB ve ANY. Normal tablolarda sorunsuz çalışan VARCHAR, DOUBLE, BOOLEAN, DATETIME gibi takma adların hepsi STRICT tabloda hata verir. ANY sütunu ise bir tür kaçış kapısı: hiçbir dönüştürme yapmadan her tipte değeri kabul eder.

Yeni SQLite veritabanlarında STRICT tablo kullanmalı mıyım?

Çoğu yeni şema için cevabım evet. STRICT tablolar, normal tabloların sessizce yuttuğu hataları yakalar — INTEGER sütununa sızmış bir string, ya da REAL sütununa yanlışlıkla serileştirilmiş bir liste gibi. Bedeli sadece tablo başına bir anahtar kelime ve egzotik tip isimlerinden vazgeçmek. SQLite 3.37 (2021) ile birlikte kullanılabilir.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA