BAB 3: Pilihan yang Dijaga: Domain Nilai dan Aturan Isian
#Studi kasus: "Satu kondisi, empat ejaan"
Kepala Seksi minta rekap jumlah pohon sehat. Anda mengelompokkan data survei berdasarkan kolom Kondisi, dan muncul tujuh baris, bukan tiga. Ada Sehat, sehat, dan Sehat (dengan spasi di ujung). Ada Terserang Hama dan Terserang hama. Dua baris lagi kosong.
Komputer menganggap semua ejaan itu berbeda. Rekap yang seharusnya selesai lima menit menjadi dua jam pembersihan. Bab ini mencegahnya sejak data dimasukkan.
#Konsep: domain dalam tiga kalimat
Domain adalah daftar nilai yang sah untuk satu kolom, seperti kotak pilihan di formulir kertas: surveyor tinggal mencentang, tidak mengetik bebas. Ada tiga bentuk umum: daftar (misalnya tiga kondisi pohon), rentang (tinggi pohon 0 sampai 60 m), dan pola teks. Domain mencegah salah ketik, tetapi tidak selalu menjadi gembok, dan di bab ini Anda akan melihat bedanya.
Istilah baru bagian ini:
- Domain: daftar atau rentang nilai sah untuk satu kolom.
- Value Map: pilihan tetap yang dibuat langsung di QGIS.
- Value Relation: pilihan yang diambil dari sebuah tabel acuan.
- Aturan isian (constraint): syarat sebuah isian, misalnya tidak boleh kosong.
- Nilai bawaan: isian yang terisi otomatis, misalnya tanggal hari ini.

#Tiga lapis penjagaan
Banyak orang mengira satu pengaturan sudah cukup. Hasil uji saya menunjukkan ada tiga lapis, dengan kekuatan berbeda. [terbukti: diuji di QGIS 4.0.2 dan GDAL 3.12]
| Lapis | Di mana tersimpan | Apa yang terjadi bila nilai salah |
|---|---|---|
| Domain di GeoPackage | Di dalam berkas .gpkg | QGIS membaca domain itu dan membuat kotak pilihan di formulir. Penulisan lewat program (GDAL atau skrip QGIS) tidak ditolak. |
| Pengaturan formulir QGIS (Value Map, Value Relation, Range, aturan isian) | Di proyek, atau di dalam GeoPackage bila disimpan sebagai gaya | Formulir mencegah isian yang salah dan memberi peringatan. Penulisan lewat program tidak melewati formulir. |
| Pagar di berkas (trigger SQL) | Di dalam berkas .gpkg | Menolak nilai salah, siapa pun yang menulis, termasuk skrip. |
Jadi untuk survei lapangan yang melibatkan banyak orang, pakai lapis pertama dan kedua agar formulir ramah. Bila datanya penting sekali, tambahkan lapis ketiga.
#Memilih jenis pilihan

- Pakai Value Map untuk daftar pendek yang jarang berubah, seperti
Kondisi. - Pakai Value Relation bila daftarnya bisa bertambah, seperti jenis pohon. Anda cukup menambah baris di tabel
Ref_Jenis, tanpa mengutak-atik formulir. - Pakai Range untuk angka, seperti tinggi pohon 0 sampai 60 m.
#Aturan isian dan nilai bawaan
Aturan isian punya dua kekuatan. Yang tegas menolak penyimpanan. Yang lunak hanya memberi peringatan. Dalam skrip I3.4, saya memakai tegas untuk hal yang pasti salah, dan lunak untuk hal yang masih mungkin terjadi.
| Kolom | Aturan | Kekuatan |
|---|---|---|
ID_Survei | Tidak boleh kosong dan harus unik | Tegas |
Kondisi | Tidak boleh kosong | Tegas |
Tinggi_Phn | Antara 0 dan 60 | Tegas |
Akurasi_m | Maksimal 5 m | Lunak (peringatan) |
Nilai bawaan menghemat waktu dan mengurangi salah ketik:
| Kolom | Ekspresi nilai bawaan | Hasil |
|---|---|---|
Tgl_Survei | to_date(now()) | Tanggal hari ini |
Surveyor | @user_account_name | Nama akun yang sedang masuk |
ID_Survei | Ekspresi di Bagian A | SV-001, lalu SV-002, dan seterusnya |
Angka 5 m pada Akurasi_m adalah contoh. Tetapkan batas Anda sendiri dari uji titik referensi di Bab 1.
#Bagian A: QGIS
#Bagian A: Domain dan formulir di QGIS
Siapkan Survei_KPH.gpkg dari Bab 2 (atau jalankan skrip I3.2).
Lapis 1: domain di dalam GeoPackage
- Buka panel Browser. Klik kanan
Survei_KPH.gpkg, lalu pilih New Field Domain ► New Coded Values Domain. Dokumentasi QGIS menyebut menu ini ada untuk GeoPackage dan file geodatabase. [CEK: isi kotak dialognya] - Beri nama
Kondisi_Pohon, tipe field Text, lalu isi tiga nilai:Sehat,Terserang Hama,Tebangan Liar. - Buat satu lagi lewat New Field Domain ► New Range Domain: nama
Tinggi_Pohon, tipe Decimal, nilai terkecil 0 dan terbesar 60. [CEK] - Perluas
Titik_Surveidi Browser sampai terlihat daftar field. Klik kananKondisi, pilih Set Field Domain, lalu pilihKondisi_Pohon. Ulangi untukTinggi_PhndenganTinggi_Pohon. [CEK]
Cara cepat dan terbukti: jalankan skrip I3.3. Hasil uji skrip (QGIS 4.0.2):
Domain di berkas: ['Kondisi_Pohon', 'Tinggi_Pohon']
Widget Kondisi : ValueMap
Widget Tinggi_Phn : Range
Nilai 'ngawur' dan tinggi 250 m: tertulis tanpa ditolakDua baris pertama membuktikan domain tersimpan dan QGIS membacanya. Baris terakhir membuktikan domain bukan gembok.
Lapis 2: formulir dan aturan isian
- Klik kanan
Titik_Survei► Properties ► tab Attributes Form. Pilih fieldKondisi. Ubah Widget Type menjadi Value Map, lalu isi tiga pilihan tadi. - Pilih
Jenis. Ubah Widget Type menjadi Value Relation. Atur Layer keRef_Jenis, Key dan Value keJenis. - Pilih
Tinggi_Phn. Ubah Widget Type menjadi Range, lalu isi Minimum 0 dan Maximum 60. - Pada
Kondisi, centang Not null di bagian Constraints. PadaID_Survei, centang Not null dan Unique. PadaTinggi_Phn, isi Expression dengan"Tinggi_Phn" BETWEEN 0 AND 60, dengan pesan galat singkat. Centang Enforce expression constraint untuk aturan tegas. - Pada bagian Defaults, isi Default value
to_date(now())untukTgl_Survei, dan@user_account_nameuntukSurveyor. - Simpan agar pengaturan ikut ke dalam GeoPackage. Di bawah jendela Properties, buka menu Style, lalu pilih penyimpanan gaya ke basis data (GeoPackage). [CEK: nama persis menu]
Semua ini juga bisa dikerjakan dengan skrip I3.4. Inti skrip:
# Inti skrip I3.4 (berkas lengkap: skrip/i3_04_formulir_widget.py)
widget("Kondisi", "ValueMap", {"map": [{p: p} for p in pilihan]})
widget("Jenis", "ValueRelation", {"Layer": ref_jenis.id(), "LayerName": "Ref_Jenis", "LayerSource": ref_jenis.source(),
"LayerProviderName": "ogr", "Key": "Jenis", "Value": "Jenis", "AllowNull": False})
widget("Tinggi_Phn", "Range", {"Min": 0.0, "Max": 60.0, "Step": 0.1, "Style": "SpinBox", "Precision": 1, "AllowNull": False})
lyr.setConstraintExpression(idx("Tinggi_Phn"), '"Tinggi_Phn" BETWEEN 0 AND 60', "Tinggi pohon harus 0 sampai 60 m")
lyr.setFieldConstraint(idx("Tinggi_Phn"), QgsFieldConstraints.ConstraintExpression, QgsFieldConstraints.ConstraintStrengthHard)
lyr.setDefaultValueDefinition(idx("Tgl_Survei"), QgsDefaultValue("to_date(now())"))
lyr.saveStyleToDatabaseV2("Formulir_Survei", "Formulir survei pohon", True, "")Ekspresi nilai bawaan untuk ID_Survei (menambah nomor terakhir dengan satu):
'SV-' || lpad(to_string(coalesce(maximum(to_int(substr("ID_Survei", 4))), 0) + 1), 3, '0')Hasil uji skrip (QGIS 4.0.2):
Simpan gaya ke GeoPackage: SaveStyleResult.Success
Gaya bawaan terbaca: True
Fitur salah : ['Kondisi: value is NULL', 'Tinggi_Phn: Tinggi pohon harus 0 sampai 60 m check failed',
'Akurasi_m: Akurasi lebih dari 5 m: ulangi pengukuran bila bisa check failed']
Fitur benar : []
Tabel acuan ditemukan: Ref_Jenis
Nilai bawaan -> ID_Survei: SV-001 | Tgl_Survei: tanggal hari uji | Surveyor: nama akunFitur yang salah (kondisi kosong, tinggi 250 m, akurasi 8,4 m) ditandai tiga pelanggaran. Fitur yang benar lolos.
Lapis 3: pagar di berkas (opsional)
- Untuk data yang sangat penting, tambahkan trigger SQL. Skrip I3.5 memasang trigger pada salinan berkas dan menguji dua nilai:
CREATE TRIGGER cek_kondisi_tambah BEFORE INSERT ON Titik_Survei
WHEN NEW.Kondisi IS NULL OR NEW.Kondisi NOT IN ('Sehat','Terserang Hama','Tebangan Liar')
BEGIN SELECT RAISE(ABORT, 'Kondisi harus salah satu dari tiga pilihan baku'); END;Kondisi 'sehat' -> DITOLAK: Kondisi harus salah satu dari tiga pilihan baku
Kondisi 'Sehat' -> DITERIMA#Bagian B: ArcGIS Pro
#Bagian B: ArcGIS Pro
Di geodatabase, domain adalah objek yang berdiri sendiri, lalu dipasang ke kolom. Alurnya tiga langkah. [kemungkinan: dokumentasi Esri]
- Create Domain (Data Management): pilih tipe Coded value atau Range.
- Add Coded Value To Domain atau Set Value For Range Domain: isi nilainya.
- Assign Domain To Field: pasang domain ke kolom.
Cara lewat antarmuka: pilih layer di panel Contents, tab Feature Layer ► Data ► Domains, klik New Domain, lalu simpan. Pasang domain di Fields view pada kolom Domain. Kolom Default di Fields view dipakai untuk nilai bawaan. [CEK]
# [CEK] Cocokkan dengan versi Anda. Nama alat dari dokumentasi ArcGIS Pro.
import arcpy
gdb = r"D:/KPH_Contoh/Survei.gdb"
arcpy.management.CreateDomain(gdb, "Kondisi_Pohon", "Kondisi pohon", "TEXT", "CODED")
for nilai in ["Sehat", "Terserang Hama", "Tebangan Liar"]:
arcpy.management.AddCodedValueToDomain(gdb, "Kondisi_Pohon", nilai, nilai)
arcpy.management.CreateDomain(gdb, "Tinggi_Pohon", "Tinggi 0 sampai 60 m", "DOUBLE", "RANGE")
arcpy.management.SetValueForRangeDomain(gdb, "Tinggi_Pohon", 0, 60)
arcpy.management.AssignDomainToField(gdb + "/Titik_Survei", "Kondisi", "Kondisi_Pohon")
arcpy.management.AssignDomainToField(gdb + "/Titik_Survei", "Tinggi_Phn", "Tinggi_Pohon")Padanan Value Relation: tidak ada yang persis sama di desktop. Cara umum adalah domain nilai kode yang diisi dari tabel acuan, lalu diperbarui dengan alat Table To Domain. [CEK]
Padanan aturan tegas di berkas: Attribute Rules (jenis constraint) di geodatabase, yang tidak dikenali ArcMap. [kemungkinan: dokumentasi Esri]
#Bagian C: ArcMap 10.8
#Bagian C: ArcMap 10.8
- Di jendela Catalog, klik kanan geodatabase ► Properties ► tab Domains. Buat domain, tentukan nama, tipe field, dan tipe domain (Coded Values atau Range). Isi nilainya. [kemungkinan: dokumentasi ArcMap]
- Pasang domain ke kolom lewat Feature Class Properties ► Fields, lalu pilih kolom dan atur Domain di bagian propertinya. [kemungkinan: dokumentasi ArcMap]
- Alat yang sama dengan Pro ada di ArcToolbox (Create Domain, Add Coded Value To Domain, Assign Domain To Field). Kode Python harus mengikuti Python 2.7. [CEK]
Tidak ada padanan: ArcMap tidak punya Value Relation, aturan isian ber-ekspresi, atau Attribute Rules. Pemeriksaan harus lewat skrip atau Bab 6. [kemungkinan]
#Cek paham
- Mengapa Value Relation lebih baik daripada Value Map untuk daftar jenis pohon?
- Apa beda aturan isian tegas dan lunak?
- Mengapa domain di GeoPackage belum menjamin tidak ada nilai salah?
Jawaban:
- Daftar jenis bisa bertambah. Dengan Value Relation, Anda cukup menambah baris di tabel acuan. Dengan Value Map, Anda harus mengubah pengaturan formulir.
- Tegas menolak penyimpanan. Lunak hanya memberi peringatan, sehingga data tetap bisa disimpan.
- Domain bekerja di formulir. Penulisan langsung lewat program tidak melewati formulir, sehingga nilai di luar daftar tetap bisa tertulis. Untuk jaminan kuat, perlu pagar di berkas atau pemeriksaan data berkala.
#Kesalahan umum
- Mengetik pilihan manual di banyak tempat. Tempatkan daftar di satu tabel acuan dan pakai ulang.
- Mengubah daftar setelah data terkumpul. Nilai lama yang tidak ada di daftar baru akan menjadi tidak sah. Ganti dengan hati-hati dan perbarui data lama.
- Menyimpan formulir hanya di proyek. Ponsel yang memuat GeoPackage saja tidak melihat pengaturan itu. Simpan gaya ke dalam GeoPackage, atau bawa proyeknya.
- Menganggap domain sama dengan gembok. Anggap domain sebagai penunjuk arah. Tetap periksa data (Bab 6).
#Ringkasan dan latihan
Ringkasan: domain membatasi pilihan satu kolom. Daftar tetap pakai Value Map, daftar yang bisa tumbuh pakai Value Relation, angka pakai Range. Aturan isian dan nilai bawaan melengkapinya. Penjagaan kuat butuh trigger atau pemeriksaan data.
Latihan: jalankan skrip I3.3 dan I3.4 pada Survei_KPH.gpkg. Lalu muat ulang berkas itu di proyek QGIS kosong, dan periksa apakah Kondisi tampil sebagai kotak pilihan. Tambahkan nilai keempat Lainnya ke tabel Ref_Kondisi. Mengapa nilai itu belum muncul di Value Map Kondisi?
Jawaban yang diharapkan: karena Kondisi memakai Value Map yang daftarnya tetap di pengaturan, bukan membaca tabel acuan.
#Tabel perbandingan: membatasi isian
| Tugas | QGIS | ArcGIS Pro | ArcMap 10.8 |
|---|---|---|---|
| Daftar pilihan tetap | Domain di GeoPackage, atau Value Map | Coded value domain | Coded value domain |
| Daftar dari tabel | Value Relation | Table To Domain [CEK] | Table To Domain [CEK] |
| Rentang angka | Range domain atau widget Range | Range domain | Range domain |
| Tidak boleh kosong, unik | Constraints di Attributes Form | Allow NULL di Fields view; unik lewat aturan [CEK] | Allow NULL di Fields |
| Aturan ber-ekspresi | Expression constraint | Attribute Rules | Tidak ada padanan |
| Nilai bawaan | Defaults di Attributes Form | Kolom Default di Fields view | Default value pada properti field |
| Penolakan di berkas | Trigger SQL | Attribute Rules | Tidak ada padanan |