Skip to content

SQL API Reference ​

v1.1.19+

The SQL API lets you execute custom SQL queries configured on the Lovrabet platform.

ℹ️ Version requirement This feature requires SDK v1.1.19 or later.

💡 New to custom SQL? If this is your first time using custom SQL, start with the Custom SQL tutorial — this document is a pure API reference.

When to Use the SQL API ​

ScenarioRecommended API
Simple CRUD operationsDataset API
Cross-table joinsSQL API ✅
Complex aggregate statisticsSQL API ✅
Custom reportsSQL API ✅

API Methods ​

Use the client.sql namespace to execute SQL queries.

Method Signature ​

TypeScript
client.sql.execute<T>({ sqlCode, params }: SqlExecuteParams): Promise<SqlExecuteResult<T>>
client.sql.execute<T>(sqlCode: string | number, params?: Record<string, any>): Promise<SqlExecuteResult<T>>

Parameters ​

ParameterTypeRequiredDescription
sqlCodestring | number✅SQL code, in the format "xxxxx-xxxxx" or a numeric ID
paramsRecord<string, any>❌SQL parameter object for parameterized queries

Return Value ​

TypeScript
interface SqlExecuteResult<T> {
  execSuccess: boolean; // SQL 执行是否成功
  execResult?: T[]; // 查询结果数组(仅成功时存在)
}

⚠️ Important The SDK returns an object containing execSuccess and execResult — not a plain array.

Your application must check execSuccess before using execResult.

executeSql() - legacy style ​

Uses the client.api namespace (kept for backward compatibility; not recommended).

TypeScript
client.api.executeSql<T>(sqlCode: string | number, params?: Record<string, any>): Promise<SqlExecuteResult<T>>

Quick Start ​

TypeScript
import { createClient, sqlSafe } from "@lovrabet/sdk";

// 1. 创建客户端
const client = createClient({
  accessKey process.env.LOVRABET_ACCESS_KEY,
  appCode: "your-app-code",
});

// 2. 执行 SQL - 使用 sqlSafe 语法糖(推荐)
const { data, error } = await sqlSafe(() =>
  client.sql.execute({ sqlCode: "xxxxx-xxxxx" })
);

// 3. 处理结果(一次检查)
if (error) {
  console.error("查询失败:", error.message);
  return;
}

// data 直接是查询结果数组
console.log(`查询成功,返回 ${data.length} 条数据`);
data.forEach((row) => console.log(row));
TypeScript
// 不使用 sqlSafe:需要手动检查 execSuccess
const result = await client.sql.execute({ sqlCode: "xxxxx-xxxxx" });

if (result.execSuccess && result.execResult) {
  console.log(`查询成功,返回 ${result.execResult.length} 条数据`);
  result.execResult.forEach((row) => console.log(row));
} else {
  console.error("SQL 执行失败");
}

Parameterized Queries ​

TypeScript
// SQL 中使用 #{paramName} 定义参数
// 例如:SELECT * FROM users WHERE id = #{userId} AND status = #{status}

// 推荐方式:对象参数
const result = await client.sql.execute({
  sqlCode: "xxxxx-xxxxx",
  params: {
    userId: 123,
    status: "active",
  }
});

// 或直接传参
const result = await client.sql.execute("xxxxx-xxxxx", {
  userId: 123,
  status: "active",
});

if (result.execSuccess && result.execResult) {
  console.log("查询结果:", result.execResult);
}

TypeScript Support ​

TypeScript
// 定义结果类型
interface UserStat {
  id: number;
  name: string;
  login_count: number;
}

// 使用 sqlSafe + 泛型
const { data, error } = await sqlSafe<UserStat>(() =>
  client.sql.execute({ sqlCode: "xxxxx-xxxxx" })
);

if (error) {
  console.error("查询失败:", error.message);
  return;
}

// data 是 UserStat[],类型安全
data.forEach((user) => {
  console.log(`${user.name}: ${user.login_count} 次登录`);
});

Error Handling ​

TypeScript
import { sqlSafe } from "@lovrabet/sdk";

// 一次检查处理所有错误
const { data, error } = await sqlSafe(() =>
  client.sql.execute({ sqlCode: "xxxxx-xxxxx" })
);

if (error) {
  // 区分错误类型
  if (error.code === 'SQL_ERROR') {
    // 业务逻辑失败(execSuccess = false)
    console.error('SQL 执行失败:', error.cause);
  } else {
    // HTTP 错误(404、500 等)
    console.error('请求失败:', error.message, error.status);
  }
  return;
}

// data 直接是查询结果数组
console.log(`查询到 ${data.length} 条记录`);

Distinguishing Error Types ​

TypeScript
const { data, error } = await sqlSafe(() =>
  client.sql.execute({ sqlCode: 'user-stats' })
);

if (error) {
  // 业务错误:execSuccess = false
  if (error.code === 'SQL_ERROR') {
    const originalResult = error.cause;  // 原始 SqlExecuteResult
    console.error('业务失败:', originalResult);
  }
  // HTTP 错误:404、500 等
  else if (error.status) {
    console.error('HTTP 错误:', error.status, error.message);
  }
  // 其他错误
  else {
    console.error('未知错误:', error.message);
  }
  return;
}

// 使用数据
data.forEach(row => console.log(row));

Common Error Codes ​

CodeDescriptionFix
401Authentication failedCheck your AccessKey or log in again
404SQL not foundCheck that the SQL code is correct
500Server errorRetry later or contact support

FAQ ​

Why is execSuccess false? ​

execSuccess: false means the SQL failed to execute on the platform. Common causes:

  • SQL syntax errors
  • A referenced table or column doesn't exist
  • Wrong SQL parameters or mismatched types
  • Database connection issues

Fix: Test the SQL on the platform's custom SQL management page first to confirm it runs.

How do I debug SQL queries? ​

Enable SDK debug mode:

TypeScript
const client = createClient({
  appCode: "your-app",
  accessKey: process.env.ACCESS_KEY,
  options: {
    debug: true, // 启用调试日志
  },
});

How do I handle large datasets? ​

  1. Use LIMIT in the SQL
  2. Use pagination parameters
  3. Use background jobs: for heavy data processing, prefer a scheduled task over a real-time query

Which SQL operations are supported? ​

  • ✅ SELECT queries: fully supported
  • ⚠️ UPDATE/DELETE: partially supported (requires admin permission configuration)
  • ❌ INSERT: not recommended (use the Dataset API)
  • ❌ DDL operations: not supported (CREATE/DROP TABLE, etc.)

Differences in Backend Functions ​

If you run SQL inside a Backend Function (BFF) on the Lovrabet platform, the return structure differs from the frontend SDK:

Return Value Comparison ​

EnvironmentCallReturn valueHow to get the data
Frontend SDKclient.sql.execute(){ execSuccess, execResult }Check execSuccess, read from execResult
Backend Functioncontext.client.sql.execute()A plain array [{ col: val }, ...]Use the result directly; no execResult field

Backend Function Example ​

JavaScript
// BFF 环境中
export default async function myEndpoint(params, context) {
  // 直接返回数组,无需检查 execSuccess
  const rows = await context.client.sql.execute({
    sqlCode: "user-stats",
    params: { userId: params.userId }
  });

  // rows 就是查询结果数组
  return { data: rows };
}

⚠️ Mind the difference There is no execResult field in BFF — the following pattern is wrong:

Error Handling ​

Frontend SDK: check execSuccess or use sqlSafe

TypeScript
const result = await client.sql.execute({ sqlCode: 'xxx' });
if (!result.execSuccess) {
  throw new Error('查询失败');
}

Backend Function: failures throw directly — catch them with try-catch

JavaScript
try {
  const rows = await context.client.sql.execute({ sqlCode: 'xxx' });
  return { data: rows };
} catch (error) {
  throw new Error(`查询失败: ${error.message}`);
}
  • Custom SQL tutorial - a complete step-by-step tutorial
  • Quick start - SDK installation and configuration
  • Authentication - the three auth modes in depth
  • API guide - Dataset API reference
  • Troubleshooting - fixes for common issues

Last updated: 2025-11-12

基于飞书知识库同步生成,内容以飞书源文档为准