R: اتصالات قاعدة البيانات R
آخر تحديث: 2026-08-26
في الدروس الثلاثة السابقة، تعرفنا على البيانات المخزنة في ملفات (CSV، Excel، JSON). ومع ذلك، يتم تخزين 90% من البيانات على مستوى المؤسسات في قواعد البيانات — مثل MySQL وPostgreSQL وSQL Server وOracle. في هذا الدرس، سنتعلم كيفية ربط لغة R بقاعدة بيانات، والاستعلام عن البيانات باستخدام لغة SQL، وكتابة إطارات البيانات في قاعدة البيانات.
بعد الانتهاء من هذا الدرس، ستتمكن من إجراء استعلام على جدول قاعدة بيانات يحتوي على ملايين الصفوف باستخدام لغة R، وإعادة كتابة نتائج التحليل إلى قاعدة البيانات.
1. ما ستتعلمه
- أساسيات قواعد البيانات (قواعد البيانات العلائقية، لغة SQL)
- مواصفات واجهة DBI وبرامج تشغيل ODBC
- قاعدة بيانات محلية من نوع RSQLite (لا تتطلب خادمًا) الاتصال بـ MySQL/PostgreSQL/SQL Server
- dbGetQuery / dbExecute / dbReadTable
- dbWriteTable: الكتابة إلى إطار بيانات
- يقوم dplyr بترجمة لغة SQL تلقائيًا
- ممارسات الإنتاج: تجمع الاتصالات، وقطع الاتصالات
2. قصة محلل بيانات
(1) المشكلة: يتم تخزين البيانات في قاعدة البيانات
بوب محلل يحتاج إلى استرجاع بيانات من قاعدة بيانات MySQL الخاصة بالشركة:
SELECT customer_id, SUM(amount) AS total
FROM orders
WHERE order_date >= '2024-01-01'
GROUP BY customer_id
ORDER BY total DESC
LIMIT 100;
يقوم بتشغيل SQL في Navicat → ثم يقوم بتصدير ملف CSV → ثم يقرأ ملف CSV في R. ويستغرق ذلك منه 5 دقائق في كل مرة. لو قام بربط R مباشرةً بقاعدة البيانات—
(2) الحل باستخدام لغة R
library(DBI)
library(RMySQL)
# 1. Connect to the Database
con <- dbConnect(RMySQL::MySQL(),
dbname = "shop",
host = "localhost",
user = "root",
password = "secret")
# 2. Run straight ahead SQL
result <- dbGetQuery(con, "
SELECT customer_id, SUM(amount) AS total
FROM orders
WHERE order_date >= '2024-01-01'
GROUP BY customer_id
ORDER BY total DESC
LIMIT 100
")
# 3. or use dplyr Translation SQL
library(dplyr)
result2 <- tbl(con, "orders") |>
filter(order_date >= "2024-01-01") |>
group_by(customer_id) |>
summarise(total = sum(amount)) |>
arrange(desc(total)) |>
collect() # Forget it R Memory
# 4. Disconnect
dbDisconnect(con)
سطر واحد للاتصال + سطر واحد من SQL. هذه هي قوة اتصالات قواعد البيانات في لغة R.
3. منظومة قواعد بيانات R
(1) 4 حزم أساسية
| الحزمة | الوظيفة | التبعيات |
|---|---|---|
| DBI | مواصفات واجهة قاعدة البيانات (واجهة برمجة تطبيقات موحدة) | لغة R الخالصة |
| RSQLite | برنامج تشغيل SQLite (قاعدة بيانات محلية) | لغة R الخالصة (لا يتطلب خادمًا) |
| RMySQL / RMariaDB | برنامج تشغيل MySQL/MariaDB | يتطلب مكتبة عميل MySQL |
| RPostgreSQL | برنامج تشغيل PostgreSQL | يتطلب مكتبة عميل PostgreSQL |
| odbc | واجهة ODBC العالمية | يتطلب تثبيت برنامج تشغيل ODBC |
| dbplyr | ترجمة dplyr إلى لغة SQL | DBI |
(2) التثبيت
# 1. Core Interfaces(Required)
install.packages("DBI")
# 2. Local Database(No server required,Recommended for beginners)
install.packages("RSQLite")
# 3. Production Database(On Demand)
install.packages("RMySQL") # MySQL
install.packages("RMariaDB") # MariaDB(Recommended Alternatives RMySQL)
install.packages("RPostgreSQL") # PostgreSQL
install.packages("odbc") # General ODBC
4. RSQLite: قاعدة بيانات محلية (موصى بها للمبتدئين)
(1) ما هو SQLite؟
graph LR
A["SQLite"] --> B["Serverless"]
A --> C["Single-File Storage"]
A --> D["Embedded"]
A --> E["Zero Configuration"]
A --> F["Python/R/Excel Can be read"]
style A fill:#d4edda
style B fill:#cce5ff
style C fill:#f8d7da
style D fill:#e1d4ff
SQLite = قاعدة بيانات قائمة على الملفات (كل ملف يمثل قاعدة بيانات)، ولا تتطلب أي خادم ولا تحتاج إلى أي إعدادات. تأتي SQLite مدمجة في الهواتف الذكية وأجهزة iPhone وأجهزة Android ولغة Python ولغة R.
(2) إنشاء قاعدة بيانات أو الاتصال بها
library(DBI)
library(RSQLite)
# 1. Create/Connect(If the file does not exist, it will be created automatically.)
con <- dbConnect(SQLite(), "my_database.db")
# 2. Disconnect(Important!Disconnect after use)
dbDisconnect(con)
# 3. Temporary Database(In memory,Restart Failed)
con <- dbConnect(SQLite(), ":memory:")
(3) الكتابة إلى DataFrame
# Prepare the data
sales <- data.frame(
id = 1:5,
product = c("A", "B", "A", "C", "B"),
amount = c(100, 200, 150, 300, 250)
)
con <- dbConnect(SQLite(), "shop.db")
# Write to Table(Coverage:overwrite / Add:append)
dbWriteTable(con, "sales", sales, overwrite = TRUE)
# Verification
dbListTables(con)
# [1] "sales"
(4) قراءة البيانات
# Method 1:Read the entire table
df <- dbReadTable(con, "sales")
print(df)
# Method 2:Execute SQL
result <- dbGetQuery(con, "SELECT * FROM sales WHERE amount > 150")
print(result)
# Method 3:dplyr(Lazy Query,Finally collect)
library(dplyr)
result2 <- tbl(con, "sales") |>
filter(amount > 150) |>
collect()
(5) عمليات أخرى
# 1. List all tables
dbListTables(con)
# [1] "sales" "products" "customers"
# 2. Does the table exist?
dbExistsTable(con, "sales")
# [1] TRUE
# 3. Delete Table
dbRemoveTable(con, "sales")
# 4. View Table Fields
dbListFields(con, "sales")
# [1] "id" "product" "amount"
# 5. Commit Transaction
dbCommit(con)
dbRollback(con)
5. الاتصال بقاعدة بيانات الإنتاج
MySQL/MariaDB
# MySQL
library(RMySQL)
con <- dbConnect(MySQL(),
dbname = "shop",
host = "localhost",
port = 3306,
user = "root",
password = "your_password")
# MariaDB(Recommendations,Open Source)
library(RMariaDB)
con <- dbConnect(MariaDB(),
dbname = "shop",
host = "localhost",
port = 3306,
user = "root",
password = "your_password")
PostgreSQL
library(RPostgreSQL)
con <- dbConnect(PostgreSQL(),
dbname = "shop",
host = "localhost",
port = 5432,
user = "postgres",
password = "your_password")
(3) ODBC (الاتصال بـ SQL Server/Oracle)
library(odbc)
con <- dbConnect(odbc(),
Driver = "SQL Server",
Server = "localhost",
Database = "shop",
UID = "sa",
PWD = "your_password")
libmysqlclient-dev لـ MySQL).
6. dbplyr: الترجمة التلقائية لـ SQL في dplyr
(1) المفهوم الأساسي
graph LR
A["dplyr Chain Operation"] --> B["dbplyr Translate to SQL"]
B --> C["Database Execution"]
C --> D["collect Pull back R Memory"]
style A fill:#cce5ff
style B fill:#d4edda
style C fill:#f8d7da
style D fill:#fff3cd
(2) التطبيق العملي
library(dplyr)
library(dbplyr) # Load Translator
# 1. Create a "lazy" table(Doesn't actually query the database)
orders <- tbl(con, "orders")
# 2. Write dplyr Code(Will not be executed immediately)
query <- orders |>
filter(order_date >= "2024-01-01", amount > 100) |>
group_by(customer_id) |>
summarise(
total = sum(amount),
n_orders = n()
) |>
arrange(desc(total)) |>
head(100)
# 3. View the translation SQL
query |> show_query()
# SELECT `customer_id`, SUM(`amount`) AS `total`, COUNT(*) AS `n_orders`
# FROM `orders`
# WHERE (`order_date` >= '2024-01-01') AND (`amount` > 100.0)
# GROUP BY `customer_id`
# ORDER BY `total` DESC
# LIMIT 100
# 4. Forget it R Memory
result <- query |> collect()
tbl() + dplyr + collect() هي التركيبة المثالية لتحليل قواعد البيانات — لا داعي لكتابة لغة SQL يدويًّا؛ حيث يتم ترجمة كود R تلقائيًّا إلى لغة SQL وتنفيذه في قاعدة البيانات.
(3) مزايا الأداء
تنفيذ قاعدة البيانات مقابل التحميل في ذاكرة R:
| حجم البيانات | التحميل إلى R | التنفيذ في قاعدة البيانات |
|---|---|---|
| @,000 صف | 0.1 ثانية | 0.1 ثانية (لا فرق) |
| @,000 صف | 10 ثوانٍ | 0.5 ثانية (تحتوي قاعدة البيانات على فهارس) |
| 100 مليون سطر | تجميد | 5 ثوانٍ (قدرة معالجة قاعدة البيانات) |
tbl() + collect() لتحليل الجداول الكبيرة — فهذا يعرض النتائج فقط في R، وليس الجدول بأكمله.
7. كتابة DataFrame إلى قاعدة بيانات
(1) dbWriteTable
# 1. Create/Overview Table
dbWriteTable(con, "sales_summary", summary_df, overwrite = TRUE)
# 2. Append to the existing table
dbWriteTable(con, "sales_log", new_data, append = TRUE)
# 3. Temporary Table(Automatically delete at the end of the session)
dbWriteTable(con, "temp_data", df, temporary = TRUE)
# 4. Line Name Processing
dbWriteTable(con, "df", df, row.names = FALSE) # Do not include the line number
(2) التطبيق العملي
# Read R Data → Cleaning → Write back to the database
library(dplyr)
library(readr)
# 1. Read CSV
sales <- read_csv("sales.csv")
# 2. Cleaning
clean_sales <- sales |>
filter(!is.na(amount)) |>
mutate(date = as.Date(date)) |>
group_by(region, product) |>
summarise(total = sum(amount))
# 3. Write back to the database
con <- dbConnect(SQLite(), "shop.db")
dbWriteTable(con, "sales_by_region_product", clean_sales, overwrite = TRUE)
# 4. Verification
result <- dbGetQuery(con, "SELECT * FROM sales_by_region_product LIMIT 5")
print(result)
8. الممارسات الإنتاجية
(1) أفضل الممارسات لتكوين الاتصال
# 1. Use .Renviron Save Password(Don't put it in the code)
# Add to ~/.Renviron:
# DB_PASSWORD=your_password
password <- Sys.getenv("DB_PASSWORD")
# 2. Connection Configuration Encapsulation
db_connect <- function() {
dbConnect(RMariaDB::MariaDB(),
dbname = "shop",
host = Sys.getenv("DB_HOST", "localhost"),
port = as.integer(Sys.getenv("DB_PORT", 3306)),
user = Sys.getenv("DB_USER", "root"),
password = Sys.getenv("DB_PASSWORD"))
}
# 3. Use withConnection Pattern
con <- db_connect()
on.exit(dbDisconnect(con)) # Automatically disconnect when the function ends
(2) معالجة الأخطاء
# 1. Simple tryCatch
result <- tryCatch(
{
con <- dbConnect(SQLite(), "shop.db")
dbGetQuery(con, "SELECT * FROM sales LIMIT 10")
},
error = function(e) {
message("Database Error:", e$message)
NULL
},
finally = {
if (exists("con") && !is.null(con)) dbDisconnect(con)
}
)
# 2. Check the connection
if (dbIsValid(con)) {
cat("Connection is normal\n")
} else {
cat("Connection Lost\n")
}
(3) العمليات المجمعة
# 1. Bulk Insert(Transactions)
dbBegin(con)
for (chunk in split(data, ceiling(seq_len(nrow(data)) / 1000))) {
dbWriteTable(con, "big_table", chunk, append = TRUE)
}
dbCommit(con)
# 2. Progress Bar
library(progress)
pb <- progress_bar$new(total = nrow(data))
for (i in seq_len(nrow(data))) {
dbExecute(con, "INSERT INTO log VALUES (?, ?)", params = list(data$id[i], data$msg[i]))
pb$tick()
}
9. مثال كامل: تحليل قاعدة بيانات المبيعات في SQLite
فيما يلي مثال على مسار عمل كامل يربط بين جميع المفاهيم التي تم تناولها في هذا الدرس.
▶ مثال: تحليل شامل لقاعدة بيانات المبيعات المحلية
# ============================================
# Comprehensive Analysis of the Local Sales Database
# Features:Use RSQLite Database Creation,Look up data,Analysis
# ============================================
library(DBI)
library(RSQLite)
library(dplyr)
# 1. Create a Database + Write Initial Data
con <- dbConnect(SQLite(), "shop_demo.db")
dbWriteTable(con, "customers", data.frame(
id = 1:5,
name = c("Alice", "Bob", "Charlie", "Diana", "Eve"),
city = c("Beijing", "Shanghai", "Guangzhou", "Beijing", "Shenzhen"),
register_date = as.Date("2023-01-01") + c(0, 30, 60, 90, 120)
), overwrite = TRUE)
dbWriteTable(con, "orders", data.frame(
id = 1:20,
customer_id = sample(1:5, 20, replace = TRUE),
order_date = as.Date("2024-01-01") + sample(0:90, 20),
amount = sample(100:2000, 20)
), overwrite = TRUE)
cat("=== Table Structure ===\n")
print(dbListTables(con))
# 2. SQL Search:Total Order Amount for Each Customer
cat("\n=== SQL Search(Total Customer Orders)===\n")
result_sql <- dbGetQuery(con, "
SELECT c.name, c.city, COUNT(o.id) AS n_orders, SUM(o.amount) AS total
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
GROUP BY c.id
ORDER BY total DESC
")
print(result_sql)
# 3. The same query using dplyr(dbplyr Translation SQL)
cat("\n=== dplyr Search(Automatic Translation SQL)===\n")
customers_tbl <- tbl(con, "customers")
orders_tbl <- tbl(con, "orders")
result_dplyr <- customers_tbl |>
left_join(orders_tbl, by = c("id" = "customer_id")) |>
group_by(id, name, city) |>
summarise(
n_orders = n(),
total = sum(amount)
) |>
arrange(desc(total)) |>
collect()
print(result_dplyr)
# 4. Complex Analysis:Monthly Sales Trends
cat("\n=== Monthly Sales Trends ===\n")
monthly_sales <- orders_tbl |>
mutate(month = format(order_date, "%Y-%m")) |>
group_by(month) |>
summarise(
orders = n(),
revenue = sum(amount),
avg_amount = round(mean(amount), 2)
) |>
collect()
print(monthly_sales)
# 5. Identify High-Value Customers
cat("\n=== High-value customers(Order Value > 2000)===\n")
vip_customers <- customers_tbl |>
left_join(orders_tbl, by = c("id" = "customer_id")) |>
group_by(id, name, city) |>
summarise(total = sum(amount, na.rm = TRUE)) |>
filter(total > 2000) |>
arrange(desc(total)) |>
collect()
print(vip_customers)
# 6. Write the analysis results back to the database
dbWriteTable(con, "vip_customers", vip_customers, overwrite = TRUE)
dbWriteTable(con, "monthly_sales", monthly_sales, overwrite = TRUE)
cat("\n=== The report has been saved to the database. ===\n")
print(dbListTables(con))
# 7. Verify the table to which data is written back
cat("\n=== Verification vip_customers ===\n")
vip_reloaded <- dbReadTable(con, "vip_customers")
print(vip_reloaded)
# 8. Disconnect
dbDisconnect(con)
cat("\n=== The database connection has been lost ===\n")
# 9. Clean Up Files
file.remove("shop_demo.db")
النتائج المتوقعة (مقتطف):
=== SQL Search(Total Customer Orders)===
name city n_orders total
1 Eve Shenzhen 5 5180
2 Diana Beijing 5 4643
3 Charlie Guangzhou 4 4156
4 Bob Shanghai 3 3461
5 Alice Beijing 3 3033
=== Monthly Sales Trends ===
month orders revenue avg_amount
1 2024-01 4 5239 1309.75
2 2024-02 5 6491 1298.20
...
❓ أسئلة شائعة
dbConnect(RMariaDB::MariaDB(), dbname, host, user, password). استخدم متغير البيئة Sys.getenv("DB_PASSWORD") لكلمة المرور لتجنب كتابتها بشكل ثابت في الكود.dbWriteTable أم SQL للكتابة في قاعدة البيانات؟dbWriteTable(con, "table", df, overwrite = TRUE) بسيط وسهل الاستخدام؛ أما بالنسبة لعمليات الكتابة المعقدة، فاستخدم dbExecute(con, "INSERT...") أو SQL المعلم.on.exit(dbDisconnect(con)) لإغلاق الاتصالات تلقائيًا؛ أو استخدم مجموعة الاتصالات الموجودة في حزمة pool (موصى به في بيئة الإنتاج).📖 ملخص
- DBI هي مواصفات واجهة لقواعد بيانات R؛ وتقوم برامج تشغيل محددة (RSQLite، RMariaDB، RPostgreSQL) بتنفيذ هذه المواصفات.
- RSQLite: مقدمة موصى بها — لا تتطلب خادمًا، مكتوبة بلغة R الخالصة، قاعدة بيانات قائمة على الملفات (ملف .db واحد)
- 5 وظائف أساسية:
dbConnectالاتصال /dbDisconnectقطع الاتصال /dbGetQueryاستعلام SQL /dbWriteTableالكتابة /dbReadTableقراءة الجدول بأكمله - dbplyr يُعد نقطة تحول جذرية:
tbl(con, "table") + dplyr + collect()يُترجم كود لغة R تلقائيًا إلى لغة SQL - الكتابة: الكتابة فوق البيانات باستخدام
dbWriteTable(con, "name", df, overwrite = TRUE)/ الإضافة إلى البيانات باستخدامappend = TRUE - ممارسة عملية: استخدم كلمة المرور
Sys.getenv()والمعاملاتdbBegin/dbCommit/dbRollbackوon.exitلإنهاء الاتصال. - عند تحليل الجداول الكبيرة، استخدم دائمًا
tbl() + collect()— قم بالحساب داخل قاعدة البيانات فقط؛ ولا تقم بتحميل البيانات إلى ذاكرة R
📝 تمارين
-
تمرين أساسي: استخدم RSQLite لإنشاء قاعدة بيانات محلية
test.db، وأدخل إطار بيانات واحدًا (5 صفوف، 3 أعمدة)، ثم استخدمdbReadTableلقراءته مرة أخرى للتحقق من اكتمال البيانات. -
أسئلة أساسية: قم بتنفيذ الاستعلامات الثلاثة التالية بلغة SQL على قاعدة البيانات المذكورة في السؤال السابق: ①
SELECT * FROM table②SELECT COUNT(*) FROM table③SELECT col, COUNT(*) FROM table GROUP BY col. -
تمرين أساسي: استخدم
dbExecuteلإنشاء جدول جديد (يحتوي على الحقول id و name و age)، واستخدمdbWriteTableلإدراج 5 صفوف من البيانات، ثم استخدمdbRemoveTableلحذفها. تحقق من صحة كل عملية. -
تمرين متقدم: باستخدام قاعدة بيانات المبيعات النموذجية (جدولان:
customersوorders)، استخدم الجدولtbl() + dplyr + collect()للقيام بما يلي: ① تحديد العملاء الذين لديهم أكثر من 3 طلبات؛ ② حساب إجمالي المبيعات الشهرية؛ ③ تحديد العملاء الثلاثة الأكثر إنفاقًا. التقط لقطة شاشة واحفظها. -
التحدي: استخدم
dbplyrلترجمة عملية معقدة في dplyr إلى لغة SQL: ① عوامل تصفية متعددة ② group_by + summarise ③ arrange + head ④ ربط داخلي بين جدولين. استخدمshow_query()لعرض سلسلة SQL والتحقق من مطابقتها لـ SQL المكتوب يدويًّا.