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 | numberSQL 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 execResultnot 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

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