存储过程 #
一、存储过程概述 #
1.1 什么是存储过程 #
存储过程是存储在数据库中的可执行代码:
text
存储过程特点:
├── 封装业务逻辑
├── 提高代码复用
├── 减少网络传输
├── 增强安全性
└── 支持多种语言
1.2 OrientDB函数类型 #
| 类型 | 说明 |
|---|---|
| SQL函数 | 使用SQL语法 |
| JavaScript函数 | 使用JavaScript语法 |
| Java函数 | 使用Java编写 |
二、创建函数 #
2.1 使用Studio创建 #
- 访问 http://localhost:2480
- 选择数据库
- 点击 “Functions” 标签
- 点击 “New Function”
- 输入函数名和代码
2.2 使用SQL创建 #
sql
CREATE FUNCTION greet "SELECT 'Hello, ' + name + '!' AS message"
2.3 创建带参数的函数 #
sql
CREATE FUNCTION greetPerson(name) "SELECT 'Hello, ' + name + '!' AS message"
三、JavaScript函数 #
3.1 基本JavaScript函数 #
javascript
// 函数名: calculateAge
var birthYear = birthYear;
var currentYear = new Date().getFullYear();
return currentYear - birthYear;
3.2 数据库操作 #
javascript
// 函数名: getActiveUsers
var db = orient.getDatabase();
var result = db.query("SELECT FROM User WHERE status = 'active'");
return result;
3.3 事务操作 #
javascript
// 函数名: transferMoney
var db = orient.getDatabase();
db.begin();
try {
db.command("UPDATE Account SET balance = balance - ? WHERE id = ?", [amount, fromId]);
db.command("UPDATE Account SET balance = balance + ? WHERE id = ?", [amount, toId]);
db.commit();
return {success: true};
} catch (e) {
db.rollback();
return {success: false, error: e.message};
}
3.4 复杂业务逻辑 #
javascript
// 函数名: processOrder
var db = orient.getDatabase();
var orderId = orderId;
db.begin();
try {
var order = db.query("SELECT FROM Order WHERE id = ?", [orderId])[0];
if (order.status != 'pending') {
return {success: false, error: 'Order already processed'};
}
var items = db.query("SELECT FROM OrderItem WHERE orderId = ?", [order.rid]);
var totalAmount = 0;
for (var i = 0; i < items.length; i++) {
var item = items[i];
var product = db.query("SELECT FROM Product WHERE @rid = ?", [item.productId])[0];
if (product.stock < item.quantity) {
db.rollback();
return {success: false, error: 'Insufficient stock for ' + product.name};
}
db.command("UPDATE Product SET stock = stock - ? WHERE @rid = ?",
[item.quantity, product.rid]);
totalAmount += item.quantity * item.price;
}
db.command("UPDATE Order SET status = 'processed', totalAmount = ? WHERE @rid = ?",
[totalAmount, order.rid]);
db.commit();
return {success: true, totalAmount: totalAmount};
} catch (e) {
db.rollback();
return {success: false, error: e.message};
}
四、SQL函数 #
4.1 基本SQL函数 #
sql
CREATE FUNCTION getPersonCount "SELECT COUNT(*) FROM Person"
4.2 带参数的SQL函数 #
sql
CREATE FUNCTION getPersonByName(name) "SELECT FROM Person WHERE name = :name"
4.3 复杂SQL函数 #
sql
CREATE FUNCTION getTopCustomers(limit) "
SELECT
customer.name AS customerName,
COUNT(*) AS orderCount,
SUM(totalAmount) AS totalSpent
FROM Order
GROUP BY customer
ORDER BY totalSpent DESC
LIMIT :limit
"
五、调用函数 #
5.1 SQL调用 #
sql
SELECT greetPerson('Tom')
SELECT calculateAge(1990)
SELECT getActiveUsers()
5.2 在查询中使用 #
sql
SELECT name, calculateAge(birthYear) AS age FROM Person
SELECT name, getPersonCount() AS totalPersons FROM Person LIMIT 1
5.3 Java调用 #
java
ODatabaseSession db = orientDB.open("mydb", "admin", "admin");
OResultSet result = db.query("SELECT greetPerson(?)", "Tom");
while (result.hasNext()) {
OResult row = result.next();
System.out.println(row.getProperty("message"));
}
5.4 REST API调用 #
text
POST /function/{database}/{functionName}
Content-Type: application/json
{
"parameters": ["Tom", 30]
}
六、函数管理 #
6.1 查看所有函数 #
sql
SELECT FROM OFunction
SELECT name, language FROM OFunction
6.2 查看函数定义 #
sql
SELECT name, code FROM OFunction WHERE name = 'greetPerson'
6.3 更新函数 #
sql
UPDATE OFunction SET code = "SELECT 'Hello, ' + name + '!!!' AS message"
WHERE name = 'greetPerson'
6.4 删除函数 #
sql
DELETE FROM OFunction WHERE name = 'greetPerson'
DROP FUNCTION greetPerson
七、函数参数 #
7.1 位置参数 #
javascript
// 函数名: add
var a = arguments[0];
var b = arguments[1];
return a + b;
7.2 命名参数 #
javascript
// 函数名: greet
var name = name || 'Guest';
return 'Hello, ' + name + '!';
7.3 默认参数 #
javascript
// 函数名: calculateDiscount
var price = price;
var discount = discount || 0.1;
return price * (1 - discount);
7.4 可变参数 #
javascript
// 函数名: sum
var total = 0;
for (var i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
八、返回值 #
8.1 返回单值 #
javascript
// 函数名: square
return n * n;
8.2 返回对象 #
javascript
// 函数名: getPersonInfo
var db = orient.getDatabase();
var person = db.query("SELECT FROM Person WHERE @rid = ?", [rid])[0];
return {
name: person.name,
age: person.age,
email: person.email
};
8.3 返回集合 #
javascript
// 函数名: getPersonList
var db = orient.getDatabase();
return db.query("SELECT FROM Person WHERE status = 'active'");
九、错误处理 #
9.1 异常捕获 #
javascript
// 函数名: safeOperation
try {
var db = orient.getDatabase();
db.command("INSERT INTO Person SET name = ?", [name]);
return {success: true};
} catch (e) {
return {success: false, error: e.message};
}
9.2 参数验证 #
javascript
// 函数名: validateAndCreate
if (!name || name.trim() === '') {
throw new Error('Name is required');
}
if (!email || !email.includes('@')) {
throw new Error('Valid email is required');
}
var db = orient.getDatabase();
return db.command("INSERT INTO Person SET name = ?, email = ?", [name, email]);
十、实际应用示例 #
10.1 用户注册函数 #
javascript
// 函数名: registerUser
var db = orient.getDatabase();
var username = username;
var email = email;
var password = password;
var existing = db.query("SELECT FROM User WHERE email = ?", [email]);
if (existing.length > 0) {
return {success: false, error: 'Email already exists'};
}
db.begin();
try {
var user = db.command(
"INSERT INTO User SET username = ?, email = ?, password = ?, status = 'active', createdAt = sysdate()",
[username, email, password]
);
db.command(
"INSERT INTO UserProfile SET userId = ?, avatar = 'default.png'",
[user[0].rid]
);
db.commit();
return {success: true, userId: user[0].rid.toString()};
} catch (e) {
db.rollback();
return {success: false, error: e.message};
}
10.2 订单处理函数 #
javascript
// 函数名: createOrder
var db = orient.getDatabase();
var customerId = customerId;
var items = items;
db.begin();
try {
var order = db.command(
"INSERT INTO Order SET customer = ?, status = 'pending', createdAt = sysdate()",
[customerId]
);
var totalAmount = 0;
for (var i = 0; i < items.length; i++) {
var item = items[i];
db.command(
"INSERT INTO OrderItem SET orderId = ?, productId = ?, quantity = ?, price = ?",
[order[0].rid, item.productId, item.quantity, item.price]
);
totalAmount += item.quantity * item.price;
}
db.command(
"UPDATE Order SET totalAmount = ? WHERE @rid = ?",
[totalAmount, order[0].rid]
);
db.commit();
return {success: true, orderId: order[0].rid.toString(), totalAmount: totalAmount};
} catch (e) {
db.rollback();
return {success: false, error: e.message};
}
10.3 报表生成函数 #
javascript
// 函数名: generateSalesReport
var db = orient.getDatabase();
var startDate = startDate;
var endDate = endDate;
var orders = db.query(
"SELECT FROM Order WHERE createdAt BETWEEN ? AND ?",
[startDate, endDate]
);
var totalRevenue = 0;
var orderCount = orders.length;
var productSales = {};
for (var i = 0; i < orders.length; i++) {
var order = orders[i];
totalRevenue += order.totalAmount;
var items = db.query("SELECT FROM OrderItem WHERE orderId = ?", [order.rid]);
for (var j = 0; j < items.length; j++) {
var item = items[j];
var productId = item.productId.toString();
if (!productSales[productId]) {
productSales[productId] = {quantity: 0, revenue: 0};
}
productSales[productId].quantity += item.quantity;
productSales[productId].revenue += item.quantity * item.price;
}
}
return {
period: {start: startDate, end: endDate},
totalRevenue: totalRevenue,
orderCount: orderCount,
productSales: productSales
};
十一、性能优化 #
11.1 减少数据库调用 #
javascript
// 不推荐
for (var i = 0; i < ids.length; i++) {
db.query("SELECT FROM Person WHERE @rid = ?", [ids[i]]);
}
// 推荐
db.query("SELECT FROM Person WHERE @rid IN ?", [ids]);
11.2 使用批量操作 #
javascript
// 推荐
db.begin();
for (var i = 0; i < records.length; i++) {
db.command("INSERT INTO Person SET name = ?", [records[i].name]);
}
db.commit();
11.3 缓存结果 #
javascript
// 函数名: getCachedConfig
var db = orient.getDatabase();
var cacheKey = "config_" + configKey;
var cached = db.query("SELECT FROM Cache WHERE key = ?", [cacheKey]);
if (cached.length > 0) {
return cached[0].value;
}
var config = db.query("SELECT FROM Config WHERE key = ?", [configKey])[0];
db.command("INSERT INTO Cache SET key = ?, value = ?, expiresAt = sysdate() + 3600000",
[cacheKey, config.value]);
return config.value;
十二、总结 #
存储过程要点:
| 操作 | 语法 | 说明 |
|---|---|---|
| 创建 | CREATE FUNCTION | 创建函数 |
| 调用 | SELECT functionName() | 调用函数 |
| 查看 | SELECT FROM OFunction | 查看函数 |
| 删除 | DROP FUNCTION | 删除函数 |
下一步,让我们学习触发器!
最后更新:2026-03-27