Semakin besar proyek analisis, semakin rapuh kebiasaan menyimpan data di banyak berkas CSV: data ganda, format berubah-ubah, dan pembaruan tidak konsisten. Database relasional menyelesaikan masalah tersebut dengan satu wadah terstruktur dan bahasa query standar — SQL. MATLAB dapat berbicara langsung dengan database tersebut: interface sqlite sudah ada di MATLAB inti sejak R2015a, sedangkan Database Toolbox membuka akses ke database server seperti PostgreSQL dan MySQL. Chapter ini membahas konsep database, koneksi, pengambilan data, penulisan data, dan keamanan query. Cakupan materinya:

  • konsep database relasional dan lima perintah SQL inti
  • sqlite di MATLAB inti vs Database Toolbox
  • koneksi, fetch, sqlread, dan sqlwrite
  • modifikasi data dengan execute serta transaksi commit/close
  • bahaya SQL injection dan query berparameter

Konsep Database Relasional #

Aturannya: data hidup di tabel — baris merepresentasikan satu entitas, kolom merepresentasikan atribut, dan tipe kolom dijaga konsisten oleh mesin database. Mekanismenya: SQL (Structured Query Language) adalah bahasa deklaratif — kita menyatakan data apa yang ingin didapat, mesin database yang memutuskan cara memindai dan menyaring. Lima perintah inti yang dipakai hampir setiap hari:

Perintah SQLTugasPaduan di chapter ini
SELECTambil kolom tertentuquerySederhana + tampilkan
WHEREsaring baris dengan predikatquerySederhana, queryRentang
INSERTtambah baris barumutasi pegawai(end+1)
UPDATEubah nilai kolomloop ubah gaji
DELETEbuang barishapusBaris

Ditulis dalam SQL, kelima operasi tabel pegawai tampak seperti ini:

sql
SELECT nama, gaji FROM pegawai WHERE kota = 'Jakarta';
INSERT INTO pegawai VALUES ('Fajar', 'Jakarta', 7200);
UPDATE pegawai SET gaji = gaji + 500 WHERE nama = 'Andi';
DELETE FROM pegawai WHERE nama = 'Rina';

Kalimat WHERE kota = 'Jakarta' dievaluasi per baris oleh query engine — persis pola yang akan kita tiru dengan MATLAB murni di bagian akhir chapter.

sqlite di Core MATLAB vs Database Toolbox #

Aturannya: pilih jalur koneksi berdasar tempat data berada. Mekanismenya: sqlite membuka berkas database tunggal tanpa server — seluruh tabel, indeks, dan transaksi hidup dalam satu berkas di disk. Database Toolbox berperan berbeda: membuat koneksi jaringan ke database server lewat JDBC atau ODBC. Perbandingannya:

Aspeksqlite (MATLAB inti)Database Toolbox
SejakR2015aproduk terpisah (berlangganan)
Wadah datasatu berkas .db di diskserver: PostgreSQL, MySQL, Oracle, dsb.
Cocok untukproyek lokal, analisis, data menengahdata perusahaan, akses bersama
Fungsi kuncisqlite, fetch, execute, sqlread, sqlwritedatabase, fetch, execute, sqlwrite

Untuk proyek pribadi dan tim kecil, sqlite hampir selalu cukup: tidak ada instalasi server, berkas mudah disalin sebagai bagian proyek reproducible.

Koneksi dan Pengambilan Data #

Aturannya: setiap sesi database dimulai dari objek koneksi dan ditutup dengan close — koneksi yang terlupakan mengunci berkas SQLite dari proses lain. Mekanismenya: objek conn menyimpan pegangan ke berkas database; fetch mengirim teks SQL, menjalankan query di mesin SQLite, lalu mengemas hasilnya sebagai table MATLAB:

matlab
conn = sqlite('penjualan.db');                   % buka berkas database
data = fetch(conn, 'SELECT * FROM pegawai');     % hasil dikembalikan sebagai table
close(conn);                                     % tutup sambungan

Fungsi fetch(conn, sqlquery) menjalankan query lalu mengembalikan tabel table — kolom database menjadi variabel, baris database menjadi baris tabel. Fungsi sqlread mengambil satu tabel utuh tanpa menulis SQL: sqlread(conn, 'pegawai') mengembalikan seluruh isi tabel pegawai. Untuk arah sebaliknya, sqlwrite mengekspor table MATLAB menjadi baris baru di database: sqlwrite(conn, 'pegawai', tabelBaru) menyisipkan setiap baris tabelBaru ke tabel pegawai. Ketiga fungsi tersebut hanya berjalan di MATLAB — runner Octave tidak memiliki sqlite, sehingga blok di atas diverifikasi terhadap dokumentasi resmi tanpa dijalankan runner.

Modifikasi Data dan Transaksi #

Aturannya: perubahan skema dan isi database dilakukan lewat execute, bukan fetch. Mekanismenya: execute(conn, sqlquery) menjalankan pernyataan SQL yang tidak mengembalikan data — CREATE TABLE, INSERT, UPDATE, DELETE — langsung pada berkas database:

matlab
conn = sqlite('penjualan.db');
execute(conn, 'CREATE TABLE pegawai (nama TEXT, kota TEXT, gaji REAL)');
execute(conn, 'INSERT INTO pegawai VALUES (''Fajar'', ''Jakarta'', 7200)');
commit(conn);
close(conn);

Transaksi menjaga kelompok perubahan tetap utuh: bila sesi berakhir sebelum commit, perubahan yang belum dikomit tidak dijadikan permanen, dan rollback membatalkannya secara eksplisit. Pola amannya: buka koneksi → execute serangkaian perubahan yang saling bergantung → commit → close. Untuk menyisipkan data bertumpuk, sqlwrite dengan table lebih ringkas daripada merangkai INSERT satu per satu.

Keamanan: SQL Injection #

Aturannya: nilai yang berasal dari pengguna tidak boleh dirangkai langsung ke dalam teks SQL. Mekanismenya: teks SQL adalah kode — bila input pengguna menyusup ke teks tersebut, pengguna bisa menyuntikkan klausa tambahan dan membaca atau merusak seluruh tabel:

matlab
% BERBAHAYA: input pengguna digabung ke teks SQL
q = ['SELECT * FROM pegawai WHERE nama = ''' inputNama ''''];
data = fetch(conn, q);

Varian yang aman memisahkan kode SQL dari nilai. Untuk sqlite, rute paling bersih adalah sqlwrite: nilai berada di dalam table dan tidak pernah menyentuh teks SQL:

matlab
sqlwrite(conn, 'pegawai', dataBaru);   % nilai lewat table, bukan string SQL

Pada Database Toolbox, query berparameter memakai placeholder ? — data dikirim terpisah dari teks SQL lewat bentuk execute ber-data:

matlab
sql = "INSERT INTO pegawai VALUES (?, ?, ?)";
execute(conn, sql, dataBaru);       % dataBaru: table berisi nilai

Koneksi JDBC dapat melangkah lebih jauh dengan objek SQLPreparedStatement: nilai di-bind ke parameter sekali, lalu pernyataan yang sama dijalankan berulang dengan nilai berbeda — pola standar aplikasi produksi. Objek prepared statement hanya tersedia untuk koneksi JDBC, bukan untuk sqlite.

Mini Query Engine di MATLAB Murni #

Karena sqlite hanya ada di MATLAB, contoh.m menguji konsep SQL di atas data di memori: tabel menjadi struct array, dan tiap operasi SQL menjadi fungsi murni. Fungsi querySederhana meniru SELECT ... WHERE kolom = nilai:

matlab
function hasil = querySederhana(data, kolom, nilai)
% QUERYSEDERHANA SELECT ... WHERE kolom = nilai (teks).
%   Pembandingan dilakukan per baris, meniru evaluasi
%   predikat WHERE oleh mesin database.
    hasil = data(strcmp({data.(kolom)}, nilai));
end

Predikat numerik WHERE gaji >= batas dan pengurutan ORDER BY gaji mengikuti pola yang sama:

matlab
function hasil = queryRentang(data, kolom, batas)
% QUERYRENTANG SELECT ... WHERE kolom >= batas (numerik).
    hasil = data([data.(kolom)] >= batas);
end

function hasil = urutkan(data, kolom)
% URUTKAN ORDER BY kolom ASC (indeks hasil sort).
    [~, idx] = sort([data.(kolom)]);
    hasil = data(idx);
end

Alur ujinya mengikuti siklus hidup query sungguhan:

Operasi mutasi INSERT/UPDATE/DELETE diuji dalam satu blok pada data yang sama:

matlab
    pegawai(end+1) = struct('nama', 'Fajar', 'kota', 'Jakarta', 'gaji', 7200);
    assert(numel(pegawai) == 6, 'INSERT gagal');
    fprintf('INSERT Fajar    : 5 -> %d baris\n', numel(pegawai));

    for k = 1:numel(pegawai)
        if strcmp(pegawai(k).nama, 'Andi')
            pegawai(k).gaji = pegawai(k).gaji + 500;   % UPDATE SET gaji = gaji + 500
        end
    end
    gajiAndi = pegawai(strcmp({pegawai.nama}, 'Andi')).gaji;
    assert(isequal(gajiAndi, 8600), 'UPDATE gagal');
    fprintf('UPDATE Andi +500: gaji 8100 -> %d\n', gajiAndi);

    pegawai = hapusBaris(pegawai, 'nama', 'Rina');
    assert(numel(pegawai) == 5, 'DELETE gagal');
    fprintf('DELETE Rina     : 6 -> %d baris\n', numel(pegawai));

Output yang Dihasilkan (keseluruhan contoh.m):

text
== Bagian 1: SELECT * FROM pegawai ==
nama     kota         gaji
Budi     Jakarta      7500
Siti     Bandung      6200
Andi     Jakarta      8100
Rina     Surabaya     5400
Dewi     Bandung      6900
jumlah baris: 5
== Bagian 2: WHERE kota = 'Jakarta' ==
nama     kota         gaji
Budi     Jakarta      7500
Andi     Jakarta      8100
jumlah baris: 2
== Bagian 3: WHERE gaji >= 6000 ORDER BY gaji ==
nama     kota         gaji
Siti     Bandung      6200
Dewi     Bandung      6900
Budi     Jakarta      7500
Andi     Jakarta      8100
== Bagian 4: INSERT, UPDATE, DELETE ==
INSERT Fajar    : 5 -> 6 baris
UPDATE Andi +500: gaji 8100 -> 8600
DELETE Rina     : 6 -> 5 baris
mini query engine: SELECT/WHERE/ORDER/INSERT/UPDATE/DELETE PASS

Filter kota = 'Jakarta' menyisakan dua dari lima baris, filter rentang gaji >= 6000 menyisakan empat baris yang terurut naik, lalu tiga mutasi menggerakkan jumlah baris 5 → 6 → 5 dengan gaji Andi naik menjadi 8600 — angka-angka tersebut dijaga oleh assert sehingga regresi logika langsung gagal.

Ringkasan #

Kerja database di MATLAB berdiri di atas empat gerbang: objek koneksi (sqlite('file.db') di MATLAB inti sejak R2015a, atau database di Database Toolbox untuk server SQL), pembacaan (fetch mengembalikan table, sqlread mengambil tabel utuh), penulisan (execute untuk SQL tanpa hasil, sqlwrite untuk ekspor table), dan housekeeping transaksi (commit lalu close). Nilai dari pengguna selalu lewat placeholder ?, sqlwrite, atau prepared statement JDBC — jangan pernah merangkai string SQL. Skrip contoh.m menutup konsep dengan mini query engine teruji: SELECT/WHERE/ORDER BY/INSERT/UPDATE/DELETE semuanya lulus di atas struct array lima baris.