Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Tools & Tips

Database Relasional untuk Dummies

by
Difficulty:BeginnerLength:LongLanguages:

Indonesian (Bahasa Indonesia) translation by ⚡ Rova Rindrata (you can also view the original English article)

Aplikasi web dapat dipisah menjadi dua komponen utama: sebuah front-end yang menampilkan dan mengumpulkan informasi, dan back-end untuk menyimpan informasi. Dalam artikel ini, saya akan menunjukkan apa itu database relasional, dan bagaimana cara merancang database dengan benar untuk menyimpan informasi aplikasi Anda.

Sebuah database menyimpan data dalam cara yang terorganisir sehingga dapat dicari dan diambil kemudian. Ini seharusnnya berisi satu tabel atau lebih. Sebuah tabel seperti spreadsheet, yang terdiri dari baris dan kolom. Semua baris yang memiliki kolom yang sama, dan masing-masing kolom berisi data-data itu sendiri. Jika itu membantu, berpikirlah seperti tabel Anda dengan cara yang sama pada sebuah tabel dalam Excel.

Gambar 1

Data dapat dimasukkan, diperoleh, diperbarui, dan dihapus dari tabel. Kata, created, umumnya digunakan sebagai pengganti inserted, sehingga, secara kolektif, empat fungsi ini disingkat dengan baik sebagai CRUD.

Sebuah database relasional adalah jenis database yang mengatur data ke dalam tabel, dan menghubungkan mereka, berdasarkan hubungan yang sudah didefinisikan. Hubungan ini mengijinkan Anda untuk mengambil dan menggabungkan data dari satu tabel atau lebih dengan query tunggal.

Tapi itu hanyalah sekelompok kata-kata. Untuk benar-benar memahami database relasional, Anda perlu membuatnya satu sendiri. Mari kita mulai dengan mendapatkan beberapa data nyata di mana kita bisa bekerja.


Langkah 1: Mendapatkan Beberapa Data

Dalam semangat artikel kloning Twitter dari Nettuts+ (PHPRuby on RailsDjango), mari kita mendapatkan beberapa data Twitter. Saya mencari Twitter untuk "#database" dan mengambil contoh sepuluh tweet berikut:

Tabel 1

full_name username text created_at following_username
"Boris Hadjur" "_DreamLead" "What do you think about #emailing #campaigns #traffic in #USA? Is it a good market nowadays? do you have #databases?" "Tue, 12 Feb 2013 08:43:09 +0000" "Scootmedia", "MetiersInternet"
"Gunnar Svalander" "GunnarSvalander" "Bill Gates Talks Databases, Free Software on Reddit http://t.co/ShX4hZlA #billgates #databases" "Tue, 12 Feb 2013 07:31:06 +0000" "klout", "zillow"
"GE Software" "GEsoftware" "RT @KirkDBorne: Readings in #Databases: excellent reading list, many categories: http://t.co/S6RBUNxq via @rxin Fascinating." "Tue, 12 Feb 2013 07:30:24 +0000" "DayJobDoc", "byosko"
"Adrian Burch" "adrianburch" "RT @tisakovich: @NimbusData at the @Barclays Big Data conference in San Francisco today, talking #virtualization, #databases, and #flash memory." "Tue, 12 Feb 2013 06:58:22 +0000" "CindyCrawford", "Arjantim"
"Andy Ryder" "AndyRyder5" "http://t.co/D3KOJIvF article about Madden 2013 using AI to prodict the super bowl #databases #bus311" "Tue, 12 Feb 2013 05:29:41 +0000" "MichaelDell", "Yahoo"
"Andy Ryder" "AndyRyder5" "http://t.co/rBhBXjma an article about privacy settings and facebook #databases #bus311" "Tue, 12 Feb 2013 05:24:17 +0000" "MichaelDell", "Yahoo"
"Brett Englebert" "Brett_Englebert" "#BUS311 University of Minnesota's NCFPD is creating #databases to prevent "food fraud." http://t.co/0LsAbKqJ" "Tue, 12 Feb 2013 01:49:19 +0000" "RealSkipBayless", "stephenasmith"
Brett Englebert "Brett_Englebert" "#BUS311 companies might be protecting their production #databases, but what about their backup files? http://t.co/okJjV3Bm" "Tue, 12 Feb 2013 01:31:52 +0000" "RealSkipBayless", "stephenasmith"
"Nimbus Data Systems" "NimbusData" "@NimbusData CEO @tisakovich @BarclaysOnline Big Data conference in San Francisco today, talking #virtualization, #databases,& #flash memory" "Mon, 11 Feb 2013 23:15:05 +0000" "dellock6", "rohitkilam"
"SSWUG.ORG" "SSWUGorg" "Don't forget to sign up for our FREE expo this Friday: #Databases, #BI, and #Sharepoint: What You Need to Know! http://t.co/Ijrqrz29" "Mon, 11 Feb 2013 22:15:37 +0000" "drsql", "steam_games"

Berikut adalah arti dari nama setiap kolom:

MySQL digunakan di hampir setiap perusahaan Internet yang telah Anda dengar.

  • full_name: Nama lengkap pengguna
  • username: Nama Twitter
  • text: Tweet itu sendiri
  • created_at: Timestamp dari tweet
  • following_username: daftar orang-orang yang diikuti pengguna ini, dipisahkan oleh koma. Untuk keringkasan, saya membatasi panjang daftar menjadi dua

Ini adalah semua data yang nyata; Anda dapat mencari Twitter dan menemukan tweet ini.

Ini bagus. Data semua dalam satu tempat, sehingga mudah untuk menemukannya, kan? Tidak seperti itu. Ada beberapa masalah dengan tabel ini. Pertama, ada data yang berulang-ulang di kolom. Kolom "username" dan "following_username" adalah berulang-ulang, karena keduanya mengandung jenis data yang sama — akun Twitter. Ada bentuk pengulangan lain dalam kolom "following_username". Kolom hanya mengandung satu nilai, tetapi masing-masing dari field "following_username" berisi dua.

Kedua, ada data yang berulang-ulang di seluruh baris.

@AndyRyder5 dan @Brett_Englebert masing-masing men-tweet dua kali, sehingga sisa dari informasi mereka telah diduplikasi.

Duplikat adalah bermasalah karena itu membuat operasi CRUD yang lebih menantang. Sebagai contoh, itu akan memakan waktu lebih lama untuk mengambil data karena waktu akan terbuang melalui baris yang terduplikat. Juga, memperbarui data akan menjadi masalah; jika pengguna mengubah nama Twitter mereka, kita akan perlu menemukan setiap duplikat dan memperbaruinya.

Data yang berulang-ulang adalah masalah. Kita dapat memperbaiki masalah ini dengan membelah Tabel 1 ke dalam tabel-tabel terpisah. Mari kita lanjutkan dengan pertama kali menyelesaikan pengulangan di seluruh masalah kolom.


Langkah 2: Menghapus Data yang berulang-ulang di Seluruh Kolom

Seperti yang disebutkan di atas, kolom "username" dan "following_username" dalam Tabel 1 adalah berulang-ulang. Pengulangan ini terjadi karena saya mencoba untuk mengekspresikan hubungan mengikuti antara pengguna. Mari kita memperbaiki desain Tabel 1 dengan membaginya menjadi dua tabel: satu hanya untuk hubungan mengikuti dan satu untuk seluruh informasi.

Gambar 2

Karena @Brett_Englebert mengikuti @RealSkipBayless, tabel following akan mengungkapkan hubungan tersebut dengan menyimpan @Brett_Englebert sebagai "from_user" dan @RealSkipBayless sebagai "to_user." Mari langsung membagi Tabel 1 menjadi dua tabel ini:

Tabel 2: Tabel following

from_user to_user
_DreamLead Scootmedia
_DreamLead MetiersInternet
GunnarSvalander klout
GunnarSvalander zillow
GEsoftware DayJobDoc
GEsoftware byosko
adrianburch CindyCrawford
adrianburch Arjantim
AndyRyder MichaelDell
AndyRyder Yahoo
Brett_Englebert RealSkipBayless
Brett_Englebert stephenasmith
NimbusData dellock6
NimbusData rohitkilam
SSWUGorg drsql
SSWUGorg steam_games

Tabel 3: Tabel users

full_name username text created_at
"Boris Hadjur" "_DreamLead" "What do you think about #emailing #campaigns #traffic in #USA? Is it a good market nowadays? do you have #databases?" "Tue, 12 Feb 2013 08:43:09 +0000"
"Gunnar Svalander" "GunnarSvalander" "Bill Gates Talks Databases, Free Software on Reddit http://t.co/ShX4hZlA #billgates #databases" "Tue, 12 Feb 2013 07:31:06 +0000"
"GE Software" "GEsoftware" "RT @KirkDBorne: Readings in #Databases: excellent reading list, many categories: http://t.co/S6RBUNxq via @rxin Fascinating." "Tue, 12 Feb 2013 07:30:24 +0000"
"Adrian Burch" "adrianburch" "RT @tisakovich: @NimbusData at the @Barclays Big Data conference in San Francisco today, talking #virtualization, #databases, and #flash memory." "Tue, 12 Feb 2013 06:58:22 +0000"
"Andy Ryder" "AndyRyder5" "http://t.co/D3KOJIvF article about Madden 2013 using AI to prodict the super bowl #databases #bus311" "Tue, 12 Feb 2013 05:29:41 +0000"
"Andy Ryder" "AndyRyder5" "http://t.co/rBhBXjma an article about privacy settings and facebook #databases #bus311" "Tue, 12 Feb 2013 05:24:17 +0000"
"Brett Englebert" "Brett_Englebert" "#BUS311 University of Minnesota's NCFPD is creating #databases to prevent "food fraud." http://t.co/0LsAbKqJ" "Tue, 12 Feb 2013 01:49:19 +0000"
Brett Englebert "Brett_Englebert" "#BUS311 companies might be protecting their production #databases, but what about their backup files? http://t.co/okJjV3Bm" "Tue, 12 Feb 2013 01:31:52 +0000"
"Nimbus Data Systems" "NimbusData" "@NimbusData CEO @tisakovich @BarclaysOnline Big Data conference in San Francisco today, talking #virtualization, #databases,& #flash memory" "Mon, 11 Feb 2013 23:15:05 +0000"
"SSWUG.ORG" "SSWUGorg" "Don't forget to sign up for our FREE expo this Friday: #Databases, #BI, and #Sharepoint: What You Need to Know! http://t.co/Ijrqrz29" "Mon, 11 Feb 2013 22:15:37 +0000"

Ini tampak lebih baik. Sekarang di tabel users (Tabel 3), hanya ada satu kolom dengan akun Twitter. Dalam tabel following (Tabel 2), hanya satu akun Twitter pada setiap fiaeld dalam kolom "to_user".

Edgar F. Codd, ilmuwan komputer yang meletakkan dasar teoritis dari database relasional, memanggil langkah ini untuk menghapus data berulang-ulang di seluruh kolom sebagai first normal form (1NF).


Langkah 3: Menghapus Data Berulang-ulang di Seluruh Baris

Sekarang kita sudah memperbaiki pengulangan seluruh kolom, kita perlu untuk memperbaiki pengulangan seluruh baris. Karena pengguna @AndyRyder5 dan @Brett_Englebert masing-masing men-tweet dua kali, informasi mereka diduplikasi di tabel users (Tabel 3). Ini menunjukkan bahwa kita perlu mengeluarkan tweets dan menempatkan mereka di tabel mereka sendiri.

Gambar 3

Seperti sebelumnya, "text" menyimpan tweet itu sendiri. Sejak kolom "created_at" menyimpan timestamp dari tweet, masuk akal untuk menariknya ke tabel ini juga. Saya juga memasukkan referensi untuk kolom "username" sehingga kita tahu siapa yang menerbitkan tweet. Berikut ini adalah hasil dari menempatkan tweet di tabel mereka sendiri:

Tabel 4: Tabel tweets

text created_at username
"What do you think about #emailing #campaigns #traffic in #USA? Is it a good market nowadays? do you have #databases?" "Tue, 12 Feb 2013 08:43:09 +0000" "_DreamLead"
"Bill Gates Talks Databases, Free Software on Reddit http://t.co/ShX4hZlA #billgates #databases" "Tue, 12 Feb 2013 07:31:06 +0000" "GunnarSvalander"
"RT @KirkDBorne: Readings in #Databases: excellent reading list, many categories: http://t.co/S6RBUNxq via @rxin Fascinating." "Tue, 12 Feb 2013 07:30:24 +0000" "GEsoftware"
"RT @tisakovich: @NimbusData at the @Barclays Big Data conference in San Francisco today, talking #virtualization, #databases, and #flash memory." "Tue, 12 Feb 2013 06:58:22 +0000" "adrianburch"
"http://t.co/D3KOJIvF article about Madden 2013 using AI to prodict the super bowl #databases #bus311" "Tue, 12 Feb 2013 05:29:41 +0000" "AndyRyder5"
"http://t.co/rBhBXjma an article about privacy settings and facebook #databases #bus311" "Tue, 12 Feb 2013 05:24:17 +0000" "AndyRyder5"
"#BUS311 University of Minnesota's NCFPD is creating #databases to prevent "food fraud." http://t.co/0LsAbKqJ" "Tue, 12 Feb 2013 01:49:19 +0000" "Brett_Englebert"
"#BUS311 companies might be protecting their production #databases, but what about their backup files? http://t.co/okJjV3Bm" "Tue, 12 Feb 2013 01:31:52 +0000" "Brett_Englebert"
"@NimbusData CEO @tisakovich @BarclaysOnline Big Data conference in San Francisco today, talking #virtualization, #databases,& #flash memory" "Mon, 11 Feb 2013 23:15:05 +0000" "NimbusData"
"Don't forget to sign up for our FREE expo this Friday: #Databases, #BI, and #Sharepoint: What You Need to Know! http://t.co/Ijrqrz29" "Mon, 11 Feb 2013 22:15:37 +0000" "SSWUGorg"

Tabel 5: Tabel users

full_name username
"Boris Hadjur" "_DreamLead"
"Gunnar Svalander" "GunnarSvalander"
"GE Software" "GEsoftware"
"Adrian Burch" "adrianburch"
"Andy Ryder" "AndyRyder5"
"Brett Englebert" "Brett_Englebert"
"Nimbus Data Systems" "NimbusData"
"SSWUG.ORG" "SSWUGorg"

Setelah pembagian, tabel users (Tabel 5) memiliki baris unik untuk pengguna dan akun Twitter mereka.

Edgar F. Codd, memanggil langkah ini untuk menghapus data berulang-ulang di seluruh baris sebagai second normal form (2NF).


Langkah 4: Menghubungkan Tabel dengan Keys

Data dapat dimasukkan, diperoleh, diperbarui, dan dihapus dari tabel.

Sejauh ini, Tabel 1 telah dibagi menjadi tiga tabel baru: following (Tabel 2), tweets (Tabel 4), dan users (Tabel 5). Tapi bagaimana ini berguna? Data berulang-ulang telah dihapus, tapi sekarang data-data tersebar di tiga tabel independen. Untuk mengambil data, kita perlu untuk menarik link yang bermakna antara tabel. Dengan cara ini kita dapat mengungkapkan pertanyaan seperti, "apa yang telah di-tweet pengguna dan siapa yang diikuti pengguna".

Cara menarik link antara tabel adalah pertama-tama memberikan setiap baris dalam tabel sebuah pengenal unik, disebut primary key, dan kemudian mereferensi primary key itu dalam tabel lain yang Anda ingin untuk menghubungkan.

Sebenarnya kita sudah melakukan ini di users (Tabel 5) dan tweets (Tabel 4). Di users, primary key adalah kolom "username" karena tidak ada dua pengguna yang akan memiliki akun Twitter yang sama. Di tweets, kami mereferensikan key ini di kolom "username" jadi kita mengtahui siapa men-tweet apa. Karena itu adalah sebuah referensi, kolom "username" dalam tweets disebut foreign key. Dengan cara ini, key "username" terhubung ke tabel users dan tweets bersama-sama.

Apakah kolom "username" adalah ide yang terbaik sebagai primary key untuk tabel users?

Di satu sisi, ini adalah natural key — masuk akal untuk mencari menggunakan akun Twitter daripada menetapkan setiap user beberapa ID numerik dan mencari berdasarkan itu. Di sisi lain, bagaimana jika pengguna ingin mengubah akun Twitter-nya? Yang bisa menyebabkan kesalahan jika primary key dan semua referensi foreign key tidak diperbarui secara akurat, kesalahan bisa dihindari jika konstanta numerik ID digunakan. Akhirnya pilihan tergantung pada sistem Anda. Jika Anda ingin memberikan pengguna kemampuan untuk mengubah nama pengguna mereka, itu lebih baik untuk menambahkan kolom numerik "id" auto-increment ke users dan menggunakannya sebagai primary key. Sebaliknya, "username" akan baik-baik saja. Saya akan terus menggunakan "username" sebagai primary key untuk users

Mari kita beralih ke tweets (Tabel 4). Primary key harus mengidentifikasi setiap baris dengan unik, jadi apakah primary key harus di sini? Field "created_at" tidak akan bekerja karena jika dua pengguna men-tweet pada waktu yang sama persis, tweet mereka akan memiliki timestamp identik. "text" memiliki masalah yang sama jika dua pengguna men-tweet "Hello World," kita tidak bisa membedakan antara baris tersebut. Kolom "username" adalah foreign key yang mendefinisikan link dengan users jadi mari kita tidak bermain-main dengannya. Karena kolom lain bukanlah kandidat yang baik, masuk akal di sini untuk menambahkan kolom numerik "id" auto-increment dan menggunakannya sebagai primary key.

Tabel 6: Tabel tweets dengan sebuah kolom "id"

id text created_at username
1 "What do you think about #emailing #campaigns #traffic in #USA? Is it a good market nowadays? do you have #databases?" "Tue, 12 Feb 2013 08:43:09 +0000" "_DreamLead"
2 "Bill Gates Talks Databases, Free Software on Reddit http://t.co/ShX4hZlA #billgates #databases" "Tue, 12 Feb 2013 07:31:06 +0000" "GunnarSvalander"
3 "RT @KirkDBorne: Readings in #Databases: excellent reading list, many categories: http://t.co/S6RBUNxq via @rxin Fascinating." "Tue, 12 Feb 2013 07:30:24 +0000" "GEsoftware"
4 "RT @tisakovich: @NimbusData at the @Barclays Big Data conference in San Francisco today, talking #virtualization, #databases, and #flash memory." "Tue, 12 Feb 2013 06:58:22 +0000" "adrianburch"
5 "http://t.co/D3KOJIvF article about Madden 2013 using AI to prodict the super bowl #databases #bus311" "Tue, 12 Feb 2013 05:29:41 +0000" "AndyRyder5"
6 "http://t.co/rBhBXjma an article about privacy settings and facebook #databases #bus311" "Tue, 12 Feb 2013 05:24:17 +0000" "AndyRyder5"
7 "#BUS311 University of Minnesota's NCFPD is creating #databases to prevent "food fraud." http://t.co/0LsAbKqJ" "Tue, 12 Feb 2013 01:49:19 +0000" "Brett_Englebert"
8 "#BUS311 companies might be protecting their production #databases, but what about their backup files? http://t.co/okJjV3Bm" "Tue, 12 Feb 2013 01:31:52 +0000" "Brett_Englebert"
9 "@NimbusData CEO @tisakovich @BarclaysOnline Big Data conference in San Francisco today, talking #virtualization, #databases,& #flash memory" "Mon, 11 Feb 2013 23:15:05 +0000" "NimbusData"
10 "Don't forget to sign up for our FREE expo this Friday: #Databases, #BI, and #Sharepoint: What You Need to Know! http://t.co/Ijrqrz29" "Mon, 11 Feb 2013 22:15:37 +0000" "SSWUGorg"

Akhirnya, mari kita tambahkan primary key ke tabel following. Dalam tabel ini, baik kolom "from_user" atau "to_user" secara unik mengidentifikasi setiap baris dengan sendirinya. Namun "from_user" dan "to_user" bersama-sama melakukannya, karena mereka mewakili hubungan tunggal. Primary key dapat didefinisikan pada lebih dari satu kolom, jadi kita akan menggunakan kedua kolom ini sebagai primary key untuk tabel following.

Adapun foreign key, "from_user" dan "to_user" masing-masing adalah foreign key karena mereka dapat digunakan untuk mendefinisikan sebuah link dengan tabel users. Jika kita query untuk akun Twitter pada kolom "from_user", kita akan mendapatkan semua pengguna yang ia ikuti. Sejalan dengan itu, jika kita query untuk akun Twitter pada kolom "to_user", kita akan mendapatkan semua pengguna yang mengikutinya.

Kita telah mencapai banyak hal sejauh ini. Kita telah menghapus pengulangan di seluruh kolom dan baris dengan memisahkan data ke dalam tiga tabel yang berbeda, dan kemudian kita memilih primary key yang bermakna untuk menghubungkan tabel bersama-sama. Seluruh proses ini disebut normalisasi dan outputnya adalah data yang diatur dengan bersih menurut model relasional. Konsekuensi dari organisasi ini adalah bahwa baris akan muncul di database hanya sekali bergerak maju, yang pada gilirannya membuat operasi CRUD lebih mudah.

Gambar 4 diagram skema database yang diselesaikan. Tiga tabel yang dihubungkan bersama-sama dan primary key yang disorot.

Gambar 4


Sistem Manajemen Database Relasional

Ada variasi kecil dalam SQL antara masing-masing vendor RDBMS, disebut SQL dialects.

Sekarang kita tahu bagaimana merancang sebuah database relasional, bagaimana kita benar-benar menerapkannya? Sistem manajemen database relasional (RDBMS) adalah perangkat lunak yang memungkinkan Anda membuat dan menggunakan database relasional. Ada beberapa vendor komersial dan open source untuk dipilih. Pada sisi komersial, Oracle DatabaseIBM DB2, dan Microsoft SQL Server adalah tiga solusi yang terkenal. Pada sisi gratis dan open source, MySQLSQLite, dan PostgreSQL adalah tiga solusi yang banyak digunakan.

MySQL digunakan di hampir setiap perusahaan Internet yang telah Anda dengar. Dalam konteks artikel ini, Twitter menggunakan MySQL untuk menyimpan tweet pengguna mereka.

SQLite adalah umum di embedded System. iOS dan Android mengijinkan pengembang menggunakan SQLite untuk mengelola aplikasi database pribadi mereka. Google Chrome menggunakan SQLite untuk menyimpan riwayat browsing, cookies, dan thumbnail Anda pada halaman "yang paling sering dikunjungi".

PostgreSQL juga RDBMS yang banyak digunakan. Ekstensi PostGIS melengkapi PostgreSQL dengan fungsi geospasial yang membuatnya berguna untuk aplikasi pemetaan. Pengguna PostgreSQL yang penting adalah OpenStreetMap.


Structured Query Language (SQL)

Setelah Anda men-download dan mengatur sebuah RDBMS pada sistem Anda, langkah selanjutnya adalah membuat database dan tabel di dalamnya dalam rangka untuk memasukkan dan mengelola data relasional Anda. Cara Anda melakukan ini adalah dengan Structured Query Language (SQL), yang merupakan bahasa standar untuk bekerja dengan RDBMS.

Berikut adalah gambaran singkat dari pernyataan SQL umum yang relevan dengan contoh data Twitter di atas. Saya sarankan Anda memeriksa SQL Cookbook untuk daftar aplikasi berbasis daftar yang lebih lengkap dari SQL query.

  • Membuat database, bernama "development"
  • Membuat tabel bernama "users"

    RDBMS mengharuskan setiap kolom dalam sebuah tabel diberi tipe data. Di sini saya menetapkan kolom "full_name" dan "username" dengan tipe data VARCHAR yang merupakan string yang dapat bervariasi lebarnya. Saya sudah secara acak mengatur panjang maksimumnya 100. Daftar lengkap tipe data dapat ditemukan di sini.

  • Memasukkan data (operasi Create di CRUD)
  • Mengambil semua tweet milik @_DreamLead (operasi Retrieve di CRUD)
  • Memperbarui nama pengguna (operasi Update di CRUD)
  • Menghapus pengguna (operasi Delete di CRUD)

SQL adalah cukup mirip dengan kalimat bahasa inggris biasa. Ada variasi kecil dalam SQL antara masing-masing vendor RDBMS, disebut SQL dialects, tetapi perbedaannya tidak cukup dramatis bahwa Anda tidak dapat dengan mudah mentransfer pengetahuan SQL dari satu ke yang lain.


Kesimpulan

Dalam artikel ini, kita belajar bagaimana merancang sebuah database relasional. Kita mengambil kumpulan data dan mengorganisir ke dalam tabel yang terkait. Kami juga sempat melihat solusi RDBMS dan SQL. Jadi kita mulai dengan men-download RDBMS dan menormalisasi beberapa data Anda ke database relasional hari ini.

Pratinjau Gambar Sumber: FindIcons.com/Barry Mieny

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.