Kueri Berparameter dan Transaksi
Teruskan parameter dengan aman dan kelola transaksi database multi-langkah dalam R.
Kueri Berparameter dan Transaksi adalah pelajaran R Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar R Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus R Academy mencakup 4 pelajaran total.
Mengapa Menggunakan Kueri Berparameter?
Ketika input pengguna ditempelkan langsung ke string SQL, penyerang dapat menyisipkan kode SQL berbahaya. Kueri berparameter memisahkan struktur SQL dari nilai data, sehingga serangan injeksi menjadi mustahil sekaligus membuat kode Anda lebih rapi dan mudah dibaca.
library(DBI)
# DANGEROUS: string concatenation (SQL injection risk!)
user_input <- "'; DROP TABLE users; --"
# bad_sql <- paste0("SELECT * FROM users WHERE name = '", user_input, "'")
# dbGetQuery(con, bad_sql) <- NEVER do this
# SAFE: parameterized query
# dbGetQuery(con, 'SELECT * FROM users WHERE name = $1',
# params = list(user_input))
cat('Parameterized queries prevent SQL injection')dbGetQuery() dengan Parameter
dbGetQuery() menjalankan pernyataan SELECT dan mengembalikan hasilnya sebagai bingkai data. Teruskan daftar params untuk mengikat nilai ke placeholder. Sintaks placeholder berbeda-beda menurut pengandar: $1 untuk PostgreSQL, ? untuk SQLite/MySQL.
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ':memory:')
dbWriteTable(con, 'employees', data.frame(
name = c('Alice', 'Bob', 'Carol'),
department = c('Engineering', 'Marketing', 'Engineering'),
salary = c(90000, 75000, 95000)
))
# Parameterized SELECT — SQLite uses ?
result <- dbGetQuery(
con,
'SELECT name, salary FROM employees WHERE department = ?',
params = list('Engineering')
)
print(result)
dbDisconnect(con)dbExecute() — INSERT, UPDATE, DELETE
dbExecute() menjalankan pernyataan SQL yang mengubah data (INSERT, UPDATE, DELETE) dan mengembalikan jumlah baris yang terdampak. Gunakan params untuk pengikatan nilai yang aman. Inilah fungsi yang tepat untuk operasi penulisan.
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ':memory:')
dbWriteTable(con, 'users', data.frame(
id = 1:3,
name = c('Alice', 'Bob', 'Carol'),
active = c(TRUE, FALSE, TRUE)
))
# Safe UPDATE with parameters
rows_affected <- dbExecute(
con,
'UPDATE users SET active = ? WHERE id = ?',
params = list(TRUE, 2)
)
cat('Rows updated:', rows_affected, '\n')
# Verify
result <- dbGetQuery(con, 'SELECT * FROM users WHERE id = 2')
cat('Bob active:', result$active)
dbDisconnect(con)Beberapa Parameter dalam Satu Kueri
Anda dapat mengikat beberapa parameter dengan menyediakan semuanya dalam daftar params. Parameter tersebut diikat secara berurutan ke placeholder (? atau $1, $2, ...) dalam string SQL. Selalu samakan jumlah elemen daftar dengan jumlah placeholder.
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ':memory:')
dbWriteTable(con, 'products', data.frame(
id = 1:4,
name = c('Apple', 'Banana', 'Cherry', 'Date'),
price = c(1.5, 0.8, 3.0, 5.0),
stock = c(100, 200, 50, 30)
))
# Filter by two parameters
result <- dbGetQuery(
con,
'SELECT name, price FROM products WHERE price > ? AND stock > ?',
params = list(1.0, 40)
)
print(result)
dbDisconnect(con)INSERT Berparameter
Pernyataan INSERT berparameter menambahkan rekaman baru dengan aman. Ikat setiap nilai kolom sebagai parameter. Untuk INSERT massal, gunakan dbAppendTable() dengan bingkai data — cara ini lebih cepat dan DBI menangani pengikatan secara otomatis.
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ':memory:')
dbExecute(con, 'CREATE TABLE logs (level TEXT, message TEXT, ts TEXT)')
# Parameterized INSERT
dbExecute(
con,
'INSERT INTO logs (level, message, ts) VALUES (?, ?, ?)',
params = list('INFO', 'User logged in', as.character(Sys.time()))
)
result <- dbGetQuery(con, 'SELECT * FROM logs')
print(result)
dbDisconnect(con)dbBegin() dan dbCommit() — Transaksi
Transaksi mengelompokkan beberapa pernyataan SQL menjadi satu unit atomik: semuanya berhasil, atau tidak ada yang berhasil. Gunakan dbBegin() untuk memulai, lalu dbCommit() untuk menerapkan semua perubahan sekaligus.
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ':memory:')
dbExecute(con, 'CREATE TABLE accounts (id INTEGER, balance REAL)')
dbExecute(con, "INSERT INTO accounts VALUES (1, 1000), (2, 500)")
# Transfer 200 from account 1 to account 2
dbBegin(con)
dbExecute(con, 'UPDATE accounts SET balance = balance - ? WHERE id = ?',
params = list(200, 1))
dbExecute(con, 'UPDATE accounts SET balance = balance + ? WHERE id = ?',
params = list(200, 2))
dbCommit(con)
result <- dbGetQuery(con, 'SELECT * FROM accounts')
print(result)
dbDisconnect(con)dbRollback() — Membatalkan Transaksi
Jika ada pernyataan dalam transaksi yang gagal, panggil dbRollback() untuk membatalkan semua perubahan yang dibuat sejak dbBegin(). Dengan demikian, basis data tetap berada dalam keadaan konsisten. Selalu pasangkan dbBegin() dengan dbCommit() atau dbRollback().
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ':memory:')
dbExecute(con, 'CREATE TABLE orders (id INTEGER, amount REAL)')
dbExecute(con, 'INSERT INTO orders VALUES (1, 500)')
# Simulate a failed transaction
dbBegin(con)
tryCatch({
dbExecute(con, 'UPDATE orders SET amount = ? WHERE id = ?',
params = list(600, 1))
stop('Simulated error during processing') # something goes wrong
dbCommit(con)
}, error = function(e) {
dbRollback(con)
cat('Transaction rolled back:', e$message, '\n')
})
# Amount is still 500 (rollback worked)
result <- dbGetQuery(con, 'SELECT * FROM orders')
cat('Amount after rollback:', result$amount)
dbDisconnect(con)dbWithTransaction() — Pola yang Lebih Aman
dbWithTransaction() secara otomatis membungkus blok kode Anda dalam transaksi. Fungsi ini melakukan commit jika blok berhasil dan rollback jika terjadi kesalahan apa pun. Cara ini lebih rapi dan mengurangi kemungkinan kesalahan dibandingkan memanggil dbBegin() / dbCommit() / dbRollback() secara manual.
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ':memory:')
dbExecute(con, 'CREATE TABLE ledger (account TEXT, amount REAL)')
dbExecute(con, "INSERT INTO ledger VALUES ('Alice', 1000), ('Bob', 500)")
# Automatic transaction management:
dbWithTransaction(con, {
dbExecute(con, "UPDATE ledger SET amount = amount - 100 WHERE account = 'Alice'",
params = list())
dbExecute(con, "UPDATE ledger SET amount = amount + 100 WHERE account = 'Bob'",
params = list())
})
# Committed automatically on success
print(dbGetQuery(con, 'SELECT * FROM ledger'))
dbDisconnect(con)Penanganan Kesalahan di Dalam Transaksi
Menggabungkan tryCatch() dengan dbWithTransaction() menghasilkan pelaporan kesalahan yang rapi. Ketika blok bagian dalam menimbulkan kesalahan, dbWithTransaction() secara otomatis melakukan rollback, dan penangan kesalahan Anda dapat mencatat atau meneruskan kembali masalah tersebut.
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ':memory:')
dbExecute(con, 'CREATE TABLE inventory (item TEXT, qty INTEGER)')
dbExecute(con, "INSERT INTO inventory VALUES ('Widget', 100)")
safe_update <- function(con, item, qty_change) {
tryCatch(
dbWithTransaction(con, {
dbExecute(con,
'UPDATE inventory SET qty = qty + ? WHERE item = ?',
params = list(qty_change, item))
cat('Updated', item, 'by', qty_change, '\n')
}),
error = function(e) cat('Failed (rolled back):', e$message, '\n')
)
}
safe_update(con, 'Widget', -30)
print(dbGetQuery(con, 'SELECT * FROM inventory'))
dbDisconnect(con)INSERT Berkelompok untuk Performa
Memasukkan banyak baris satu per satu dalam loop berlangsung lambat. Ada dua pendekatan yang lebih baik: gunakan dbAppendTable() untuk memasukkan seluruh bingkai data sekaligus, atau bungkus INSERT individual dalam satu transaksi — basis data melakukan commit penulisan ke disk sekali di akhir, sehingga INSERT massal dalam transaksi jauh lebih cepat daripada INSERT dengan auto-commit.
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ':memory:')
dbExecute(con, 'CREATE TABLE events (user_id INTEGER, action TEXT)')
# Fast: insert a whole data frame at once
new_events <- data.frame(
user_id = c(101, 102, 103, 104),
action = c('login', 'view', 'purchase', 'logout')
)
dbAppendTable(con, 'events', new_events)
result <- dbGetQuery(con, 'SELECT COUNT(*) AS n FROM events')
cat('Rows inserted:', result$n)
dbDisconnect(con)dbDisconnect() — Selalu Tutup Koneksi
Koneksi basis data menggunakan sumber daya di server. Selalu panggil dbDisconnect(con) setelah selesai. Penggunaan on.exit(dbDisconnect(con)) di bagian atas fungsi memastikan koneksi ditutup bahkan jika terjadi kesalahan.
library(DBI)
# Pattern: use on.exit to guarantee disconnection
run_query <- function(sql) {
con <- dbConnect(RSQLite::SQLite(), ':memory:')
on.exit(dbDisconnect(con), add = TRUE) # always runs
dbExecute(con, 'CREATE TABLE t (x INTEGER)')
dbExecute(con, 'INSERT INTO t VALUES (1), (2), (3)')
result <- dbGetQuery(con, sql)
result # con is closed automatically after return
}
df <- run_query('SELECT * FROM t WHERE x > 1')
cat('Rows:', nrow(df))
# on.exit fires after return — connection cleanly closedPemeriksaan Singkat
Anda perlu mengelompokkan dua pernyataan UPDATE yang saling terkait sehingga keduanya berhasil atau tidak satu pun mengubah basis data. Pendekatan mana yang terbaik?
Kueri Berparameter dan Transaksi — Hal-Hal Penting
Operasi basis data yang aman dan andal dalam R dengan DBI:
- Jangan pernah menggabungkan input pengguna ke dalam string SQL — selalu gunakan
params dbGetQuery(con, sql, params = list(...))— SELECT yang amandbExecute(con, sql, params = list(...))— INSERT/UPDATE/DELETE yang aman- Placeholder:
?untuk SQLite/MySQL,$1/$2untuk PostgreSQL dbBegin()+dbCommit()+dbRollback()— pengendalian transaksi manualdbWithTransaction(con, { ... })— commit/rollback otomatis (disarankan)dbAppendTable(con, 'tbl', df)— INSERT massal yang cepaton.exit(dbDisconnect(con))— selalu tutup koneksi
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ':memory:')
on.exit(dbDisconnect(con), add = TRUE)
dbExecute(con, 'CREATE TABLE transfers (from_id INT, to_id INT, amount REAL)')
# Safe parameterized insert inside a transaction:
dbWithTransaction(con, {
dbExecute(con,
'INSERT INTO transfers (from_id, to_id, amount) VALUES (?, ?, ?)',
params = list(1, 2, 250.00)
)
})
result <- dbGetQuery(con, 'SELECT * FROM transfers')
cat('Transfer recorded:', result$amount)Belajar R dengan tutor AI — gratis
Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.
- Kursus
- 43
- Pelajaran
- 159
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Kueri Berparameter dan Transaksi” gratis?
Ya — teks lengkap “Kueri Berparameter dan Transaksi” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus R Academy, upgrade ke CoddyKit PRO. Kursus R Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Kueri Berparameter dan Transaksi”?
Teruskan parameter dengan aman dan kelola transaksi database multi-langkah dalam R. Kamu berlatih R Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai R Academy?
Tidak diperlukan pengalaman sebelumnya. R Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.
Berapa lama pelajaran “Kueri Berparameter dan Transaksi” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran R Academy ini?
Ya. Setiap pelajaran R Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Dasar-Dasar DBI dan RSQLite
- Menghubungkan ke PostgreSQL dan MySQL
- dbplyr: SQL melalui Sintaks dplyr
- Kueri Berparameter dan Transaksi