sap-sqlscript

安装量: 50
排名: #14739

安装

npx skills add https://github.com/secondsky/sap-skills --skill sap-sqlscript

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.

Key Characteristics

  • Case-insensitive language

  • All statements end with semicolons

  • Variables use colon prefix when referenced (:variableName)

  • No colon when assigning values

  • Use DUMMY table for single-row operations

Two Logic Types

| Declarative | Pure SQL sequences | Converted to data flow graphs, processed in parallel

| Imperative | Control structures (IF, WHILE, FOR) | Processed sequentially, prevents parallel execution

Table of Contents

Anonymous Blocks

Container Types

1. Anonymous Blocks

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;

2. Stored Procedures

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;

3. User-Defined Functions

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;

Data Types

SQLScript supports comprehensive data types for different use cases. See references/data-types.md for complete documentation including:

  • Numeric types (TINYINT, INTEGER, DECIMAL, etc.)

  • Character types (VARCHAR, NVARCHAR, CLOB, etc.)

  • Date/Time types (DATE, TIME, TIMESTAMP, SECONDDATE)

  • Binary types (VARBINARY, BLOB)

  • Type conversion functions (CAST, TO_ functions)

  • NULL handling patterns

Variable Declaration

Scalar Variables

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.

Table Variables

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;

Arrays

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

Control Structures

IF-ELSE Statement

IF <condition1> THEN
  <statements>
[ELSEIF <condition2> THEN
  <statements>]
[ELSE
  <statements>]
END IF;

Comparison Operators:

| = | Equal to

| > | Greater than

| < | Less than

| >= | Greater than or equal

| <= | Less than or equal

| !=, <> | Not equal

Important: IF-ELSE cannot be used within SELECT statements. Use CASE WHEN instead.

WHILE Loop

WHILE <condition> DO
  <statements>
END WHILE;

FOR Loop

-- 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 with EXIT

LOOP
  <statements>
  IF <condition> THEN
    BREAK;
  END IF;
END LOOP;

Table Types

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

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;

Exception Handling

EXIT HANDLER

Suspends execution and performs cleanup when exceptions occur.

DECLARE EXIT HANDLER FOR <condition_value>
  <statement>;

Condition values:

  • SQLEXCEPTION - Any SQL exception

  • SQL_ERROR_CODE <number> - Specific error code

Access error details:

  • ::SQL_ERROR_CODE - Numeric error code

  • ::SQL_ERROR_MESSAGE - Error message text

Example:

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;

CONDITION

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;

SIGNAL and RESIGNAL

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:

| 301 | Unique constraint violation

| 1299 | No data found

AMDP Integration

ABAP Managed Database Procedures allow SQLScript within ABAP classes.

Class Definition

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.

Method Implementation

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.

AMDP Restrictions

  • Parameters must be pass-by-value (no RETURNING)

  • Only scalar types, structures, internal tables allowed

  • No nested tables or deep structures

  • COMMIT/ROLLBACK not permitted

  • Must use Eclipse ADT for development

  • Auto-created on first invocation

Performance Best Practices

1. Reduce Data Volume Early

-- 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';

2. Prefer Declarative Over Imperative

-- 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;

3. Avoid Engine Mixing

  • Don't mix Row Store and Column Store tables in same query

  • Avoid Calculation Engine functions with pure SQL

  • Use consistent storage types

4. Use UNION ALL Instead of UNION

-- Faster when duplicates impossible or acceptable
SELECT * FROM table1 UNION ALL SELECT * FROM table2;

-- Slower: removes duplicates
SELECT * FROM table1 UNION SELECT * FROM table2;

5. Avoid Dynamic SQL

-- Bad: Re-optimized each execution
EXECUTE IMMEDIATE 'SELECT * FROM ' || :lv_table;

-- Good: Static SQL with parameters
SELECT * FROM "MYTABLE" WHERE id = :lv_id;

6. Position Imperative Logic Last

Place control structures at the end of procedures to maximize parallel processing of declarative statements.

System Limits

| 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.

Debugging Tools

  • SQLScript Debugger - SAP Web IDE / Business Application Studio

  • Plan Visualizer - Analyze execution plans

  • Expensive Statement Trace - Identify bottlenecks

  • SQL Analyzer - Query optimization recommendations

Quick Reference

String Concatenation

lv_result = lv_str1 || ' ' || lv_str2;

NULL Handling

COALESCE(value, default_value)
IFNULL(value, default_value)
NULLIF(value1, value2)

Date Operations

ADD_DAYS(date, n)
ADD_MONTHS(date, n)
DAYS_BETWEEN(date1, date2)
CURRENT_DATE
CURRENT_TIMESTAMP

Type Conversion

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:

| 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

Bundled Resources

Reference Documentation

  • references/skill-reference-guide.md - Index of all references with quick navigation

  • references/glossary.md - SQLScript terminology and concepts

  • references/syntax-reference.md - Complete SQLScript syntax reference

  • references/built-in-functions.md - Built-in functions catalog

  • references/data-types.md - Data types and conversion

  • references/exception-handling.md - Exception handling patterns

  • references/amdp-integration.md - AMDP integration patterns

  • references/performance-guide.md - Optimization techniques

  • references/advanced-features.md - Lateral joins, JSON, query hints, currency conversion

  • references/troubleshooting.md - Common errors and solutions

Production-Ready Templates

Copy and customize these templates for common patterns:

  • templates/simple-procedure.sql - Basic stored procedure with error handling

  • templates/procedure-with-error-handling.sql - Comprehensive error handling patterns

  • templates/table-function.sql - Table UDF with validation

  • templates/scalar-function.sql - Scalar UDF examples

  • templates/amdp-class.abap - Complete AMDP class boilerplate

  • templates/amdp-procedure.sql - AMDP implementation template

  • templates/cursor-iteration.sql - Cursor patterns (classic and FOR loop)

  • templates/bulk-operations.sql - High-performance bulk operations

Specialized Agents

  • sqlscript-analyzer - Analyze code for performance issues and best practices

  • procedure-generator - Generate procedures interactively from requirements

  • amdp-helper - Assist with AMDP class creation and debugging

Slash Commands

  • /sqlscript-validate - Validate code with auto-fix capability

  • /sqlscript-optimize - Performance analysis and optimization suggestions

  • /sqlscript-convert - Convert between standalone and AMDP formats

Validation Hooks

Automatic code quality checks on Write/Edit operations:

  • Error handling completeness

  • Security vulnerabilities

  • Performance anti-patterns

  • Naming conventions

  • AMDP compliance

返回排行榜