重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
sap-sqlscript by secondsky/sap-skills
npx skills add https://github.com/secondsky/sap-skills --skill sap-sqlscriptSQLScript 是 SAP HANA 对 SQL 的过程化扩展,支持直接在数据库层执行复杂的数据密集型逻辑。它遵循 代码到数据范式,将计算推送到数据所在的位置,而不是将数据移动到应用层。
:variableName)DUMMY 表进行单行操作| 类型 | 描述 | 执行 |
|---|---|---|
| 声明式 | 纯 SQL 序列 | 转换为数据流图,并行处理 |
| 命令式 | 控制结构 (IF, WHILE, FOR) | 顺序处理,阻止并行执行 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
一次性逻辑,不存储在数据库中。适用于测试和临时执行。
DO [(<parameter_clause>)]
BEGIN [SEQUENTIAL EXECUTION]
<body>
END;
示例:
DO
BEGIN
DECLARE lv_count INTEGER;
SELECT COUNT(*) INTO lv_count FROM "MYTABLE";
SELECT :lv_count AS record_count FROM DUMMY;
END;
具有输入/输出参数的可重用数据库对象。
CREATE [OR REPLACE] PROCEDURE <procedure_name>
(
[IN <param> <datatype>],
[OUT <param> <datatype>],
[INOUT <param> <datatype>]
)
LANGUAGE SQLSCRIPT
[SQL SECURITY {DEFINER | INVOKER}]
[DEFAULT SCHEMA <schema_name>]
[READS SQL DATA | READS SQL DATA WITH RESULT VIEW <view_name>]
AS
BEGIN
<procedure_body>
END;
标量 UDF - 返回单个值:
CREATE FUNCTION <function_name> (<input_parameters>)
RETURNS <scalar_type>
LANGUAGE SQLSCRIPT
AS
BEGIN
<function_body>
RETURN <value>;
END;
表 UDF - 返回表(只读):
CREATE FUNCTION <function_name> (<input_parameters>)
RETURNS TABLE (<column_definitions>)
LANGUAGE SQLSCRIPT
READS SQL DATA
AS
BEGIN
RETURN SELECT ... FROM ...;
END;
SQLScript 支持适用于不同用例的全面数据类型。完整文档请参见 references/data-types.md,包括:
DECLARE <variable_name> <datatype> [:= <initial_value>];
-- 示例
DECLARE lv_name NVARCHAR(100);
DECLARE lv_count INTEGER := 0;
DECLARE lv_date DATE := CURRENT_DATE;
注意: 未初始化的变量默认为 NULL。
隐式声明:
lt_result = SELECT * FROM "MYTABLE" WHERE status = 'A';
显式声明:
DECLARE lt_data TABLE (
id INTEGER,
name NVARCHAR(100),
amount DECIMAL(15,2)
);
使用 TABLE LIKE:
DECLARE lt_copy TABLE LIKE :lt_original;
DECLARE arr INTEGER ARRAY := ARRAY(1, 2, 3, 4, 5);
-- 访问:arr[1], arr[2] 等 (基于 1 的索引)
-- 注意:数组不能从过程返回
IF <condition1> THEN
<statements>
[ELSEIF <condition2> THEN
<statements>]
[ELSE
<statements>]
END IF;
比较运算符:
| 运算符 | 含义 |
|---|---|
= | 等于 |
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
!=, <> | 不等于 |
重要: IF-ELSE 不能在 SELECT 语句中使用。请改用 CASE WHEN。
WHILE <condition> DO
<statements>
END WHILE;
-- 数值范围
FOR i IN 1..10 DO
<statements>
END FOR;
-- 反向
FOR i IN REVERSE 10..1 DO
<statements>
END FOR;
-- 游标迭代
FOR row AS <cursor_name> DO
<statements using row.column_name>
END FOR;
LOOP
<statements>
IF <condition> THEN
BREAK;
END IF;
END LOOP;
定义可重用的表结构:
CREATE TYPE <type_name> AS TABLE (
<column1> <datatype>,
<column2> <datatype>,
...
);
在过程中的使用:
CREATE PROCEDURE get_employees (OUT et_result MY_TABLE_TYPE)
LANGUAGE SQLSCRIPT AS
BEGIN
et_result = SELECT * FROM "EMPLOYEES";
END;
游标逐行处理结果集。模式:声明 → 打开 → 获取 → 关闭
性能注意: 游标会绕过数据库优化器并顺序处理行。主要用于基于主键的查询。尽可能优先使用基于集合的操作。
DECLARE CURSOR <cursor_name> FOR
SELECT <columns> FROM <table> [WHERE <condition>];
OPEN <cursor_name>;
FETCH <cursor_name> INTO <variables>;
CLOSE <cursor_name>;
完整示例:
DO
BEGIN
DECLARE lv_id INTEGER;
DECLARE lv_name NVARCHAR(100);
DECLARE CURSOR cur_employees FOR
SELECT id, name FROM "EMPLOYEES" WHERE dept = 'IT';
OPEN cur_employees;
FETCH cur_employees INTO lv_id, lv_name;
WHILE NOT cur_employees::NOTFOUND DO
-- 处理行
SELECT :lv_id, :lv_name FROM DUMMY;
FETCH cur_employees INTO lv_id, lv_name;
END WHILE;
CLOSE cur_employees;
END;
FOR 循环替代方案:
FOR row AS cur_employees DO
SELECT row.id, row.name FROM DUMMY;
END FOR;
发生异常时暂停执行并执行清理操作。
DECLARE EXIT HANDLER FOR <condition_value>
<statement>;
条件值:
SQLEXCEPTION - 任何 SQL 异常SQL_ERROR_CODE <number> - 特定错误代码访问错误详情:
::SQL_ERROR_CODE - 数字错误代码::SQL_ERROR_MESSAGE - 错误消息文本示例:
CREATE PROCEDURE safe_insert (IN iv_id INTEGER, IN iv_name NVARCHAR(100))
LANGUAGE SQLSCRIPT AS
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SELECT ::SQL_ERROR_CODE AS err_code,
::SQL_ERROR_MESSAGE AS err_msg FROM DUMMY;
END;
INSERT INTO "MYTABLE" VALUES (:iv_id, :iv_name);
END;
将用户定义的名称与错误代码关联:
DECLARE <condition_name> CONDITION FOR SQL_ERROR_CODE <number>;
-- 示例
DECLARE duplicate_key CONDITION FOR SQL_ERROR_CODE 301;
DECLARE EXIT HANDLER FOR duplicate_key
SELECT 'Duplicate key error' FROM DUMMY;
抛出用户定义的异常(代码 10000-19999):
-- 抛出异常
SIGNAL <condition_name> SET MESSAGE_TEXT = '<message>';
-- 在处理器中重新抛出
RESIGNAL [<condition_name>] [SET MESSAGE_TEXT = '<message>'];
常见错误代码:
| 代码 | 描述 |
|---|---|
| 301 | 唯一约束违反 |
| 1299 | 未找到数据 |
ABAP 托管数据库过程允许在 ABAP 类中使用 SQLScript。
CLASS zcl_my_amdp DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_amdp_marker_hdb. " 必需接口
TYPES: BEGIN OF ty_result,
id TYPE i,
name TYPE string,
END OF ty_result,
tt_result TYPE STANDARD TABLE OF ty_result.
CLASS-METHODS: get_data
IMPORTING VALUE(iv_filter) TYPE string
EXPORTING VALUE(et_result) TYPE tt_result.
ENDCLASS.
CLASS zcl_my_amdp IMPLEMENTATION.
METHOD get_data BY DATABASE PROCEDURE
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING ztable.
et_result = SELECT id, name
FROM ztable
WHERE category = :iv_filter;
ENDMETHOD.
ENDCLASS.
-- 好:尽早过滤和投影
lt_filtered = SELECT col1, col2 FROM "BIGTABLE" WHERE status = 'A';
lt_result = SELECT a.col1, b.name
FROM :lt_filtered AS a
JOIN "LOOKUP" AS b ON a.id = b.id;
-- 差:先连接再过滤
lt_result = SELECT a.col1, b.name
FROM "BIGTABLE" AS a
JOIN "LOOKUP" AS b ON a.id = b.id
WHERE a.status = 'A';
-- 好:基于集合的操作
lt_result = SELECT id, amount * 1.1 AS new_amount FROM "ORDERS";
-- 差:逐行处理
FOR row AS cur_orders DO
UPDATE "ORDERS" SET amount = row.amount * 1.1 WHERE id = row.id;
END FOR;
-- 当重复项不可能或可接受时更快
SELECT * FROM table1 UNION ALL SELECT * FROM table2;
-- 较慢:移除重复项
SELECT * FROM table1 UNION SELECT * FROM table2;
-- 差:每次执行都重新优化
EXECUTE IMMEDIATE 'SELECT * FROM ' || :lv_table;
-- 好:带参数的静态 SQL
SELECT * FROM "MYTABLE" WHERE id = :lv_id;
将控制结构放在过程的末尾,以最大化声明式语句的并行处理。
| 限制 | 值 |
|---|---|
| 每个事务的表锁 | 16,383 |
| 语句中的表数 | 4,095 |
| SQL 语句长度 | 2 GB |
| 过程大小 | 受 SQL 语句长度限制 (2 GB) |
注意: 实际限制可能因 HANA 版本而异。请查阅 SAP 文档以获取特定版本的限值。
lv_result = lv_str1 || ' ' || lv_str2;
COALESCE(value, default_value)
IFNULL(value, default_value)
NULLIF(value1, value2)
ADD_DAYS(date, n)
ADD_MONTHS(date, n)
DAYS_BETWEEN(date1, date2)
CURRENT_DATE
CURRENT_TIMESTAMP
CAST(value AS datatype)
TO_VARCHAR(value)
TO_INTEGER(value)
TO_DATE(string, 'YYYY-MM-DD')
TO_TIMESTAMP(string, 'YYYY-MM-DD HH24:MI:SS')
要进行全面的 SAP 开发,请将此技能与以下技能结合使用:
| 技能 | 用例 |
|---|---|
| sap-abap | 用于 AMDP 上下文的 ABAP 编程模式 |
| sap-abap-cds | 使用 SQLScript 过程的 CDS 视图 |
| sap-cap-capire | CAP 框架数据库过程集成 |
| sap-hana-cli | 用于过程部署和测试的 HANA CLI |
| sap-btp-cloud-platform | HANA 工件的 BTP 部署 |
references/skill-reference-guide.md - 所有参考的索引,带快速导航references/glossary.md - SQLScript 术语和概念references/syntax-reference.md - 完整的 SQLScript 语法参考references/built-in-functions.md - 内置函数目录references/data-types.md - 数据类型和转换references/exception-handling.md - 异常处理模式references/amdp-integration.md - AMDP 集成模式references/performance-guide.md - 优化技术references/advanced-features.md - 横向连接、JSON、查询提示、货币转换references/troubleshooting.md - 常见错误和解决方案复制并自定义这些模板以用于常见模式:
templates/simple-procedure.sql - 带错误处理的基本存储过程templates/procedure-with-error-handling.sql - 全面的错误处理模式templates/table-function.sql - 带验证的表 UDFtemplates/scalar-function.sql - 标量 UDF 示例templates/amdp-class.abap - 完整的 AMDP 类样板templates/amdp-procedure.sql - AMDP 实现模板templates/cursor-iteration.sql - 游标模式(经典和 FOR 循环)templates/bulk-operations.sql - 高性能批量操作/sqlscript-validate - 验证代码并具有自动修复能力/sqlscript-optimize - 性能分析和优化建议/sqlscript-convert - 在独立格式和 AMDP 格式之间转换在写入/编辑操作时自动进行代码质量检查:
每周安装数
60
仓库
GitHub 星标数
167
首次出现
Jan 23, 2026
安全审计
安装于
gemini-cli53
opencode53
codex52
github-copilot51
amp46
cursor46
SQLScript is SAP HANA's procedural extension to SQL, enabling complex data-intensive logic execution directly within the database layer. It follows the code-to-data paradigm , pushing computation to where data resides rather than moving data to the application layer.
:variableName)DUMMY table for single-row operations| Type | Description | Execution |
|---|---|---|
| Declarative | Pure SQL sequences | Converted to data flow graphs, processed in parallel |
| Imperative | Control structures (IF, WHILE, FOR) | Processed sequentially, prevents parallel execution |
Single-use logic not stored in the database. Useful for testing and ad-hoc execution.
DO [(<parameter_clause>)]
BEGIN [SEQUENTIAL EXECUTION]
<body>
END;
Example:
DO
BEGIN
DECLARE lv_count INTEGER;
SELECT COUNT(*) INTO lv_count FROM "MYTABLE";
SELECT :lv_count AS record_count FROM DUMMY;
END;
Reusable database objects with input/output parameters.
CREATE [OR REPLACE] PROCEDURE <procedure_name>
(
[IN <param> <datatype>],
[OUT <param> <datatype>],
[INOUT <param> <datatype>]
)
LANGUAGE SQLSCRIPT
[SQL SECURITY {DEFINER | INVOKER}]
[DEFAULT SCHEMA <schema_name>]
[READS SQL DATA | READS SQL DATA WITH RESULT VIEW <view_name>]
AS
BEGIN
<procedure_body>
END;
Scalar UDF - Returns single value:
CREATE FUNCTION <function_name> (<input_parameters>)
RETURNS <scalar_type>
LANGUAGE SQLSCRIPT
AS
BEGIN
<function_body>
RETURN <value>;
END;
Table UDF - Returns table (read-only):
CREATE FUNCTION <function_name> (<input_parameters>)
RETURNS TABLE (<column_definitions>)
LANGUAGE SQLSCRIPT
READS SQL DATA
AS
BEGIN
RETURN SELECT ... FROM ...;
END;
SQLScript supports comprehensive data types for different use cases. See references/data-types.md for complete documentation including:
DECLARE <variable_name> <datatype> [:= <initial_value>];
-- Examples
DECLARE lv_name NVARCHAR(100);
DECLARE lv_count INTEGER := 0;
DECLARE lv_date DATE := CURRENT_DATE;
Note: Uninitialized variables default to NULL.
Implicit declaration:
lt_result = SELECT * FROM "MYTABLE" WHERE status = 'A';
Explicit declaration:
DECLARE lt_data TABLE (
id INTEGER,
name NVARCHAR(100),
amount DECIMAL(15,2)
);
Using TABLE LIKE:
DECLARE lt_copy TABLE LIKE :lt_original;
DECLARE arr INTEGER ARRAY := ARRAY(1, 2, 3, 4, 5);
-- Access: arr[1], arr[2], etc. (1-based index)
-- Note: Arrays cannot be returned from procedures
IF <condition1> THEN
<statements>
[ELSEIF <condition2> THEN
<statements>]
[ELSE
<statements>]
END IF;
Comparison Operators:
| Operator | Meaning |
|---|---|
= | Equal to |
> | Greater than |
< | Less than |
>= | Greater than or equal |
<= | Less than or equal |
!=, <> |
Important: IF-ELSE cannot be used within SELECT statements. Use CASE WHEN instead.
WHILE <condition> DO
<statements>
END WHILE;
-- Numeric range
FOR i IN 1..10 DO
<statements>
END FOR;
-- Reverse
FOR i IN REVERSE 10..1 DO
<statements>
END FOR;
-- Cursor iteration
FOR row AS <cursor_name> DO
<statements using row.column_name>
END FOR;
LOOP
<statements>
IF <condition> THEN
BREAK;
END IF;
END LOOP;
Define reusable table structures:
CREATE TYPE <type_name> AS TABLE (
<column1> <datatype>,
<column2> <datatype>,
...
);
Usage in procedures:
CREATE PROCEDURE get_employees (OUT et_result MY_TABLE_TYPE)
LANGUAGE SQLSCRIPT AS
BEGIN
et_result = SELECT * FROM "EMPLOYEES";
END;
Cursors handle result sets row by row. Pattern: Declare → Open → Fetch → Close
Performance Note: Cursors bypass the database optimizer and process rows sequentially. Use primarily with primary key-based queries. Prefer set-based operations when possible.
DECLARE CURSOR <cursor_name> FOR
SELECT <columns> FROM <table> [WHERE <condition>];
OPEN <cursor_name>;
FETCH <cursor_name> INTO <variables>;
CLOSE <cursor_name>;
Complete Example:
DO
BEGIN
DECLARE lv_id INTEGER;
DECLARE lv_name NVARCHAR(100);
DECLARE CURSOR cur_employees FOR
SELECT id, name FROM "EMPLOYEES" WHERE dept = 'IT';
OPEN cur_employees;
FETCH cur_employees INTO lv_id, lv_name;
WHILE NOT cur_employees::NOTFOUND DO
-- Process row
SELECT :lv_id, :lv_name FROM DUMMY;
FETCH cur_employees INTO lv_id, lv_name;
END WHILE;
CLOSE cur_employees;
END;
FOR Loop Alternative:
FOR row AS cur_employees DO
SELECT row.id, row.name FROM DUMMY;
END FOR;
Suspends execution and performs cleanup when exceptions occur.
DECLARE EXIT HANDLER FOR <condition_value>
<statement>;
Condition values:
SQLEXCEPTION - Any SQL exceptionSQL_ERROR_CODE <number> - Specific error codeAccess error details:
::SQL_ERROR_CODE - Numeric error code::SQL_ERROR_MESSAGE - Error message textExample:
CREATE PROCEDURE safe_insert (IN iv_id INTEGER, IN iv_name NVARCHAR(100))
LANGUAGE SQLSCRIPT AS
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SELECT ::SQL_ERROR_CODE AS err_code,
::SQL_ERROR_MESSAGE AS err_msg FROM DUMMY;
END;
INSERT INTO "MYTABLE" VALUES (:iv_id, :iv_name);
END;
Associate user-defined names with error codes:
DECLARE <condition_name> CONDITION FOR SQL_ERROR_CODE <number>;
-- Example
DECLARE duplicate_key CONDITION FOR SQL_ERROR_CODE 301;
DECLARE EXIT HANDLER FOR duplicate_key
SELECT 'Duplicate key error' FROM DUMMY;
Throw user-defined exceptions (codes 10000-19999):
-- Throw exception
SIGNAL <condition_name> SET MESSAGE_TEXT = '<message>';
-- Re-throw in handler
RESIGNAL [<condition_name>] [SET MESSAGE_TEXT = '<message>'];
Common Error Codes:
| Code | Description |
|---|---|
| 301 | Unique constraint violation |
| 1299 | No data found |
ABAP Managed Database Procedures allow SQLScript within ABAP classes.
CLASS zcl_my_amdp DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_amdp_marker_hdb. " Required interface
TYPES: BEGIN OF ty_result,
id TYPE i,
name TYPE string,
END OF ty_result,
tt_result TYPE STANDARD TABLE OF ty_result.
CLASS-METHODS: get_data
IMPORTING VALUE(iv_filter) TYPE string
EXPORTING VALUE(et_result) TYPE tt_result.
ENDCLASS.
CLASS zcl_my_amdp IMPLEMENTATION.
METHOD get_data BY DATABASE PROCEDURE
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING ztable.
et_result = SELECT id, name
FROM ztable
WHERE category = :iv_filter;
ENDMETHOD.
ENDCLASS.
-- Good: Filter and project early
lt_filtered = SELECT col1, col2 FROM "BIGTABLE" WHERE status = 'A';
lt_result = SELECT a.col1, b.name
FROM :lt_filtered AS a
JOIN "LOOKUP" AS b ON a.id = b.id;
-- Bad: Join then filter
lt_result = SELECT a.col1, b.name
FROM "BIGTABLE" AS a
JOIN "LOOKUP" AS b ON a.id = b.id
WHERE a.status = 'A';
-- Good: Set-based operation
lt_result = SELECT id, amount * 1.1 AS new_amount FROM "ORDERS";
-- Bad: Row-by-row processing
FOR row AS cur_orders DO
UPDATE "ORDERS" SET amount = row.amount * 1.1 WHERE id = row.id;
END FOR;
-- Faster when duplicates impossible or acceptable
SELECT * FROM table1 UNION ALL SELECT * FROM table2;
-- Slower: removes duplicates
SELECT * FROM table1 UNION SELECT * FROM table2;
-- Bad: Re-optimized each execution
EXECUTE IMMEDIATE 'SELECT * FROM ' || :lv_table;
-- Good: Static SQL with parameters
SELECT * FROM "MYTABLE" WHERE id = :lv_id;
Place control structures at the end of procedures to maximize parallel processing of declarative statements.
| Limit | Value |
|---|---|
| Table locks per transaction | 16,383 |
| Tables in a statement | 4,095 |
| SQL statement length | 2 GB |
| Procedure size | Bounded by SQL statement length (2 GB) |
Note: Actual limits may vary by HANA version. Consult SAP documentation for version-specific limits.
lv_result = lv_str1 || ' ' || lv_str2;
COALESCE(value, default_value)
IFNULL(value, default_value)
NULLIF(value1, value2)
ADD_DAYS(date, n)
ADD_MONTHS(date, n)
DAYS_BETWEEN(date1, date2)
CURRENT_DATE
CURRENT_TIMESTAMP
CAST(value AS datatype)
TO_VARCHAR(value)
TO_INTEGER(value)
TO_DATE(string, 'YYYY-MM-DD')
TO_TIMESTAMP(string, 'YYYY-MM-DD HH24:MI:SS')
For comprehensive SAP development, combine this skill with:
| Skill | Use Case |
|---|---|
| sap-abap | ABAP programming patterns for AMDP context |
| sap-abap-cds | CDS views that consume SQLScript procedures |
| sap-cap-capire | CAP framework database procedures integration |
| sap-hana-cli | HANA CLI for procedure deployment and testing |
| sap-btp-cloud-platform | BTP deployment of HANA artifacts |
references/skill-reference-guide.md - Index of all references with quick navigationreferences/glossary.md - SQLScript terminology and conceptsreferences/syntax-reference.md - Complete SQLScript syntax referencereferences/built-in-functions.md - Built-in functions catalogreferences/data-types.md - Data types and conversionreferences/exception-handling.md - Exception handling patternsreferences/amdp-integration.md - AMDP integration patternsreferences/performance-guide.md - Optimization techniquesCopy and customize these templates for common patterns:
templates/simple-procedure.sql - Basic stored procedure with error handlingtemplates/procedure-with-error-handling.sql - Comprehensive error handling patternstemplates/table-function.sql - Table UDF with validationtemplates/scalar-function.sql - Scalar UDF examplestemplates/amdp-class.abap - Complete AMDP class boilerplatetemplates/amdp-procedure.sql - AMDP implementation templatetemplates/cursor-iteration.sql - Cursor patterns (classic and FOR loop)templates/bulk-operations.sql - High-performance bulk operations/sqlscript-validate - Validate code with auto-fix capability/sqlscript-optimize - Performance analysis and optimization suggestions/sqlscript-convert - Convert between standalone and AMDP formatsAutomatic code quality checks on Write/Edit operations:
Weekly Installs
60
Repository
GitHub Stars
167
First Seen
Jan 23, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
gemini-cli53
opencode53
codex52
github-copilot51
amp46
cursor46
lark-cli 共享规则:飞书资源操作指南与权限配置详解
45,100 周安装
| Not equal |
references/advanced-features.md - Lateral joins, JSON, query hints, currency conversionreferences/troubleshooting.md - Common errors and solutions