Foto oleh panumas nikhomkhai via Pexels

Setiap query yang pernah ditulis di SQL Server pada akhirnya berjalan di atas dua konsep paling fundamental: database dan table. Memahami bagaimana keduanya tersusun secara hierarkis — dan bagaimana SQL Server menyimpan metadata tentang struktur tersebut — adalah fondasi yang akan terus dipakai di hampir setiap materi berikutnya, mulai dari query sederhana hingga stored procedure yang kompleks.

Artikel ini membahas hierarki penyimpanan data di SQL Server dari level instance hingga baris data, sekaligus praktik langsung membuat database dan table pertama beserta cara memeriksa strukturnya.

Hierarki Penyimpanan Data di SQL Server

Satu instance SQL Server bisa menampung banyak database. Setiap database terdiri dari banyak table, dan setiap table tersusun dari kolom (column) yang mendefinisikan jenis data, serta baris (row) yang berisi data sesungguhnya. Hierarki ini penting dipahami karena operasi seperti backup, security, dan connection string semuanya beroperasi pada level database, bukan pada level instance secara keseluruhan.

Membuat dan berpindah ke database baru

CREATE DATABASE TokoOnlineDb; GO USE TokoOnlineDb; GO -- Expected: database baru muncul di Object Explorer SSMS -- setelah refresh node 'Databases'

Membuat Table Pertama

IDENTITY mengisi CustomerId otomatis tanpa perlu diisi manual

CREATE TABLE Customers ( CustomerId INT PRIMARY KEY IDENTITY(1,1), FullName NVARCHAR(100) NOT NULL, Email NVARCHAR(150) NOT NULL, CreatedAt DATETIME DEFAULT GETDATE() ); INSERT INTO Customers (FullName, Email) VALUES ('Budi Santoso', 'budi@mail.com'); SELECT * FROM Customers; -- Expected output: -- CustomerId | FullName | Email | CreatedAt -- 1 | Budi Santoso | budi@mail.com | 2026-... (tanggal saat ini)

IDENTITY(1,1) membuat SQL Server otomatis mengisi nilai CustomerId berurutan dimulai dari 1, bertambah 1 setiap baris baru — sehingga tidak perlu menentukan nilainya secara manual saat insert, sekaligus mencegah duplikasi nilai primary key secara tidak sengaja.

Skema sebagai Pengelompok Table

Selain database, SQL Server juga mengenal konsep schema sebagai lapisan pengelompokan di dalam satu database, mirip seperti namespace pada bahasa pemrograman. Secara default, table yang dibuat tanpa menyebut schema akan masuk ke schema dbo (database owner).

Schema memisahkan table berdasarkan modul atau domain bisnis

CREATE SCHEMA Penjualan; GO CREATE TABLE Penjualan.Transaksi ( TransaksiId INT PRIMARY KEY IDENTITY(1,1), Jumlah DECIMAL(18,2) ); -- Diakses dengan menyebut schema secara eksplisit SELECT * FROM Penjualan.Transaksi;

Penggunaan schema sangat membantu pada database besar dengan ratusan table, karena memudahkan pengelompokan berdasarkan modul bisnis seperti Penjualan, Inventori, atau Keuangan, sekaligus memungkinkan pengaturan hak akses yang lebih granular per schema.

Melihat Struktur Table yang Sudah Dibuat

Memeriksa struktur kolom table lewat system view

SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Customers'; -- Expected output: -- CustomerId | int | NO -- FullName | nvarchar | NO -- Email | nvarchar | NO -- CreatedAt | datetime | YES

INFORMATION_SCHEMA adalah kumpulan view standar ANSI SQL yang tersedia di hampir semua RDBMS, termasuk SQL Server, sehingga query semacam ini juga portable jika suatu saat perlu dijalankan di database lain seperti PostgreSQL dengan sedikit penyesuaian.

Struktur Fisik Database: Data File dan Log File

Melihat data file (.mdf) dan log file (.ldf) sebuah database

-- Melihat file fisik yang membentuk sebuah database SELECT name, physical_name, type_desc, size * 8 / 1024 AS SizeMB FROM sys.master_files WHERE database_id = DB_ID('TokoOnlineDB'); -- Hasil, contoh: -- TokoOnlineDB ...\TokoOnlineDB.mdf ROWS 512 -- TokoOnlineDB_log ...\TokoOnlineDB_log.ldf LOG 64

Setiap database di SQL Server minimal terdiri dari dua jenis file fisik: data file berekstensi .mdf yang menyimpan seluruh table, index, dan objek data lainnya, serta log file berekstensi .ldf yang mencatat setiap perubahan transaksi sebelum benar-benar diterapkan ke data file. Mekanisme pencatatan ini disebut write-ahead logging, dan menjadi dasar kemampuan SQL Server melakukan rollback transaksi serta memulihkan database setelah terjadi crash.

Database besar juga bisa memiliki data file tambahan berekstensi .ndf yang dikelompokkan ke dalam filegroup, memungkinkan satu database tersebar ke beberapa disk fisik untuk meningkatkan kecepatan baca-tulis atau memisahkan table berukuran besar dari table lainnya. Log file sebaiknya ditempatkan di disk fisik yang berbeda dari data file pada server production, karena pola akses keduanya berbeda: log file ditulis secara sekuensial sedangkan data file diakses secara acak.

Ukuran log file yang terus membengkak biasanya menandakan recovery model database diset ke Full namun transaction log backup tidak pernah dijalankan secara rutin, sehingga log lama tidak pernah dibebaskan; memahami hubungan antara recovery model dan pertumbuhan log file ini penting sebelum database dipakai untuk menyimpan data dalam skala produksi.

Schema sebagai Namespace Logis dalam Database

Membuat dan menggunakan schema sebagai pemisah namespace

-- Membuat schema terpisah untuk modul Penjualan dan Keuangan CREATE SCHEMA Penjualan; GO CREATE SCHEMA Keuangan; GO CREATE TABLE Penjualan.Transaksi ( TransaksiID INT IDENTITY PRIMARY KEY, Jumlah DECIMAL(18,2) ); CREATE TABLE Keuangan.Transaksi ( TransaksiID INT IDENTITY PRIMARY KEY, Jumlah DECIMAL(18,2) ); -- Mengakses table dengan nama schema eksplisit, tidak bentrok meski nama table sama SELECT * FROM Penjualan.Transaksi; SELECT * FROM Keuangan.Transaksi;

Schema pada SQL Server berfungsi sebagai namespace logis yang mengelompokkan objek seperti table, view, dan stored procedure ke dalam unit yang lebih terorganisir di dalam satu database. Berbeda dengan database itu sendiri, schema tidak memisahkan penyimpanan fisik data, melainkan hanya memisahkan ruang nama, sehingga dua table dengan nama sama seperti Transaksi dapat hidup berdampingan selama berada di schema yang berbeda, misalnya Penjualan.Transaksi dan Keuangan.Transaksi.

Setiap table yang dibuat tanpa schema eksplisit otomatis masuk ke schema dbo (database owner), yang menjadi default bawaan SQL Server. Pada aplikasi kecil hal ini jarang menjadi masalah, tetapi pada sistem besar dengan banyak modul, mengandalkan dbo untuk semua object membuat database sulit dipetakan dan menyulitkan penerapan hak akses granular, karena permission pada SQL Server dapat diberikan per schema, bukan hanya per table satu per satu.

Penggunaan schema yang terstruktur, misalnya memisahkan schema Sales, Finance, dan Audit, memudahkan tim DBA memberi akses baca pada schema Audit kepada tim kepatuhan tanpa membuka akses ke schema Finance yang sensitif. Konvensi penamaan dua bagian (schema.nama_object) juga wajib dicantumkan secara eksplisit dalam setiap query produksi, karena bergantung pada resolusi default schema pengguna dapat menimbulkan ambiguitas ketika satu login memiliki default schema yang berbeda dari dbo, dan ambiguitas semacam ini sering baru terdeteksi setelah aplikasi berjalan di lingkungan produksi.

Menambah Kolom dan Default Constraint pada Table yang Sudah Ada

ALTER TABLE menambah kolom dengan default

-- Menambah kolom baru dengan nilai default untuk baris yang sudah ada ALTER TABLE dbo.Pelanggan ADD StatusAktif BIT NOT NULL CONSTRAINT DF_Pelanggan_StatusAktif DEFAULT (1); -- Memverifikasi constraint yang baru terpasang SELECT name, definition FROM sys.default_constraints WHERE parent_object_id = OBJECT_ID('dbo.Pelanggan'); -- Hasil: DF_Pelanggan_StatusAktif ((1))

Menambahkan kolom NOT NULL ke table yang sudah berisi banyak baris mengharuskan penyertaan default constraint, karena SQL Server perlu nilai pengganti untuk seluruh baris lama yang tidak memiliki nilai pada kolom baru tersebut. Tanpa DEFAULT, perintah ALTER TABLE akan ditolak dengan pesan error karena kolom NOT NULL tidak boleh kosong pada baris yang sudah ada sebelumnya.

Memberi nama eksplisit pada constraint seperti DF_Pelanggan_StatusAktif, bukan membiarkan SQL Server membuat nama otomatis yang acak, memudahkan proses penghapusan atau perubahan constraint tersebut di kemudian hari, karena nama otomatis seperti DF__Pelanggan__Statu__3C69FB99 sulit diingat dan harus dicari lebih dulu lewat query ke sys.default_constraints sebelum bisa dihapus dengan aman.

Kesalahan Umum yang Sering Terjadi

Lupa menjalankan USE DatabaseName sebelum membuat table

Tanpa berpindah context database dengan USE, table yang dibuat bisa tanpa sengaja masuk ke database yang salah, biasanya database default seperti master, yang bisa membingungkan saat mencarinya kembali.

Tidak mendefinisikan NOT NULL pada kolom yang seharusnya wajib diisi

Kolom tanpa NOT NULL secara default mengizinkan nilai kosong, yang bisa menyebabkan data tidak konsisten jika aplikasi lupa melakukan validasi di sisi kode sebelum insert data ke database.

Mengabaikan schema dan menumpuk semua table di dbo

Pada database kecil ini tidak masalah, namun begitu jumlah table bertambah menjadi ratusan, tidak adanya pengelompokan schema membuat navigasi dan pengaturan hak akses jadi jauh lebih sulit dikelola.

Kapan Pendekatan Ini Tidak Cocok Dipakai

Mendesain terlalu banyak table terpisah untuk data yang sangat jarang berubah dan selalu diakses bersamaan (misalnya data konfigurasi sistem) kadang membuat query jadi lebih kompleks karena butuh JOIN yang sebenarnya tidak perlu. Normalisasi tetap penting sebagai prinsip dasar desain database, tapi tidak harus dipaksakan ke setiap jenis data tanpa mempertimbangkan pola akses yang sesungguhnya terjadi di aplikasi.

Ringkasan

Memahami hubungan antara database, schema, dan table, serta cara memeriksa strukturnya lewat system view, adalah fondasi sebelum masuk ke topik tipe data dan query yang lebih kompleks pada materi selanjutnya.