This skill has been validated on the Qoder / QoderWork platform. It is a pure content-generation skill that does not invoke external tools. It can also be used on other Agent platforms, though trigger matching behavior may vary.
Never embed real customer database/table/column names in conversion examples or output (replace with tbl_demo, col_x)
Never embed real business data (phone numbers, IDs, account numbers, etc.) in example SQL; use placeholders where needed
Conversion output is generated content — for reference only; human review before executing in production is recommended
Never store any AK/SK, passwords, or plaintext connection strings in SKILL.md or references files
MCP Tool Inventory
This skill is pure content generation and does not depend on external MCP tools or CLI. All conversions are driven by built-in rule documents and mapping tables.
1. Overview
Provides SQL syntax conversion capabilities across big-data engines (DML / DDL / stored procedures / functions, etc.). This skill uses a "multi-directional language-pair + extensible conversion-rules" architecture, following a unified 5-step main process to complete each conversion, with implementations for additional engine pairs added incrementally.
Important: For language pairs marked 🟡 TODO in the table above, the corresponding references/<src>_to_<dst>.md files have not yet been created. When a user requests an unimplemented language pair, the Agent must explicitly inform the user that the pair is not yet implemented; fabricating conversion results based on speculation is strictly prohibited.
Rejection Policy for Unimplemented Language Pairs (Hard Constraint)
When a user's conversion request involves a 🟡 TODO language pair (especially Hive → Hologres), the Agent must perform the following actions:
Explicitly inform: "Hive → Hologres language pair is not yet implemented (TODO); no conversion rules are currently available."
Suggest alternatives (the reply must include specific, actionable recommendations):
Manually convert by referencing the Synapse → Hologres rule structure in this document (identifiers / data types / functions / query syntax / DDL)
Consult the data-type mapping table and function mapping table in reference.md as a general reference
Consult the official Alibaba Cloud Hologres documentation for SQL syntax details
Absolutely prohibited:
❌ Fabricating or extrapolating conversion results
❌ Outputting pseudo-conversions with Status: PASS or -- TODO: verify markers
❌ Pretending rules exist when the rewrite is actually a guess
Output delivery (hard requirement):
The rejection notice and alternative suggestions must be presented directly in the conversation reply, not merely declared as "saved to a file"
If a file needs to be written (e.g. outputs/refusal_notice.md), the file write must actually be executed; claiming a write was performed without doing so is prohibited
Hallucinated writes are prohibited: any file mentioned in logs or replies as "saved / written / generated" must actually exist in the file system with complete content
Recommended practice: reply directly in the conversation with the rejection notice and alternative suggestions — no extra file needed
Example rejection reply (output directly in conversation, not written to a file):
"SQL conversion rules for Hive → Hologres are not yet implemented (only Synapse → Hologres is currently supported). Recommendations: ① Reference the Synapse → Hologres conversion rule structure in this skill and manually rewrite against Hive syntax; ② Consult the official Hologres documentation for PostgreSQL-compatible functions and data types; ③ Re-run automatic conversion once the references/hive_to_hologres.md rule file is added."
Extension method: To add a new language pair, simply create references/<src>_to_<dst>.md using the same five-section template (identifiers / data types / functions / query syntax / DDL), and supplement the detailed mapping tables in reference.md. At runtime, the Agent loads the corresponding file based on the source/target pair.
4. Iron Rules (Violating Any Rule = Conversion Failure)
#
Prohibition
Explanation
0
No conversion for unimplemented language pairs
Language pairs marked 🟡 TODO in the support matrix (e.g. Hive → Hologres) must be rejected with a notice to the user. Suggest manual conversion using the implemented Synapse → Hologres rules or official documentation. Never output speculative conversion results
1
No speculative SQL rewrites
Every change must have a documented rule basis (this document / references / engines files) or an authoritative source. Rule not covered → keep original and annotate -- TODO: verify
2
No skipping validation
All DML/DQL must pass the "Validation Checklist" item by item. "Too complex" or "should be fine" are not valid reasons to skip
3
Validation fails → no output
When the validation checklist has unresolved items, never deliver results to the user; iterate until fixed
4
No structural loss
Conversion must not drop or merge subqueries, reduce SELECT column count, or remove WHERE/GROUP BY/HAVING clauses
5
TRUNCATE must be preserved
If the source SQL contains TRUNCATE, the conversion must preserve it
6
Each file runs the full pipeline independently
Parse → Load Rules → Transform → Validate → Output. Never reuse a template from a previous file or skip steps
7
No hallucinated writes
Never claim in logs or replies that a file has been "saved / written / generated" when no actual write was performed. Any file mentioned must exist in the file system with complete content
5. Main Process (Universal 5-Step Skeleton)
All language pairs share the same conversion process:
flowchart LR
A[Step 1<br>Parse] --> B[Step 2<br>Load Rules]
B --> C[Step 3<br>Transform]
C --> D[Step 4<br>Validate]
D --> E[Step 5<br>Output]
D -->|Fail| C
Step
Name
Description
1
Parse
Identify the scope of the input SQL: DML / DDL / stored procedure / hybrid; decompose complex SQL (see "Complex SQL Decomposition Strategy")
2
Load Rules
Based on the "source → target" pair, load the rule set from the corresponding references/<src>_to_<dst>.md (identifiers / data types / functions / query syntax / DDL / procedural code)
3
Transform
Apply rules in order: identifiers → data types → functions → query syntax → DDL → procedural. Only change what the rules cover; leave everything else untouched
4
Validate
Run the "Validation Checklist" item by item; if any item fails, return to Step 3 for iterative repair (max 3 rounds)
5
Output
Emit the converted SQL; add inline comments noting semantic differences and assumptions; mark uncertain mappings with -- TODO: verify
Complex SQL Decomposition Strategy
When the input SQL contains deeply nested subqueries (≥ 3 levels) or multiple CTEs combined with complex JOINs, apply a "transform from innermost layer outward" strategy:
Hologres folds unquoted identifiers to lowercase; if tables/columns are stored lowercase, do NOT add ""
Reserved words
If a column name is a PostgreSQL reserved word (e.g. level, name, user, order, table, type, comment), wrap in ""
Mixed-case needed
Only use "" when the Hologres object was created with "" and stores mixed case
Schema mapping
dbo.xxx → verify target schema; Hologres default schema is public, not dbo
Decision logic: Ask the user or infer from context whether their Hologres tables use lowercase (default) or mixed case. When unsure, default to no quotes and add a comment noting the assumption.
2. Data Types
See reference.md → Data Type Mapping for the complete table. Key conversions:
NVARCHAR/VARCHAR(MAX) → TEXT
DATETIME/DATETIME2/SMALLDATETIME → TIMESTAMP
DATETIMEOFFSET → TIMESTAMPTZ
BIT → BOOLEAN
TINYINT → SMALLINT
MONEY/SMALLMONEY → NUMERIC(19,4) / NUMERIC(10,4)
UNIQUEIDENTIFIER → UUID
VARBINARY/IMAGE → BYTEA
IDENTITY(seed,inc) → SERIAL / BIGSERIAL or GENERATED ALWAYS AS IDENTITY
3. Functions
See reference.md → Function Mapping for the full reference. Critical conversions:
Synapse
Hologres
Notes
GETDATE()
CURRENT_TIMESTAMP
ISNULL(a,b)
COALESCE(a,b)
DATEDIFF(day,a,b)
(b::date - a::date)
Returns integer days
DATEADD(month,3,d)
d + INTERVAL '3 month'
LEN(s)
LENGTH(s)
CHARINDEX(sub,str)
POSITION(sub IN str)
IIF(cond,t,f)
CASE WHEN cond THEN t ELSE f END
CONVERT(type,expr)
CAST(expr AS type) or TO_CHAR
TOP n
LIMIT n
Move to end of query
CONCAT(a,b)
CONCAT(a,b)
Keep as-is; both are NULL-safe. Do NOT replace with || which treats NULL differently
STRING_AGG
STRING_AGG
Same syntax in both
CROSS APPLY
CROSS JOIN LATERAL
OUTER APPLY
LEFT JOIN LATERAL ... ON TRUE
STUFF(s,i,l,r)
OVERLAY(s PLACING r FROM i FOR l)
NEWID()
gen_random_uuid()
PG 13+ built-in
FORMAT(val,fmt)
TO_CHAR(val,fmt)
Format tokens differ
4. Query Syntax
Synapse
Hologres
SELECT TOP n ...
SELECT ... LIMIT n
SELECT TOP n WITH TIES ...
Use FETCH FIRST n ROWS WITH TIES
WITH (NOLOCK)
Remove (Hologres uses MVCC)
OPTION (LABEL = ...)
Remove
+ for string concat
|| (but prefer CONCAT() for NULL safety)
; optional
; required as statement terminator
#temp_table
CREATE TEMPORARY TABLE temp_table or use CTE
@table_variable
Use CTE or TEMPORARY TABLE
DECLARE @var type = val
In PL/pgSQL: DECLARE var type := val;
SET @var = expr
In PL/pgSQL: var := expr;
5. DDL Conversion
Table Creation
-- Synapse
CREATE TABLE dbo.sales (
id INT IDENTITY(1,1),
name NVARCHAR(100),
amount MONEY,
created DATETIME2
)
WITH (
DISTRIBUTION = HASH(id),
CLUSTERED COLUMNSTORE INDEX
);
-- Hologres
BEGIN;
CREATE TABLE public.sales (
id BIGSERIAL,
name TEXT,
amount NUMERIC(19,4),
created TIMESTAMP
);
CALL set_table_property('public.sales', 'distribution_key', 'id');
CALL set_table_property('public.sales', 'orientation', 'column');
COMMIT;
-- Synapse
CREATE TABLE dbo.orders (
order_date DATE,
amount DECIMAL(18,2)
)
WITH (
PARTITION (order_date RANGE RIGHT FOR VALUES
('2024-01-01','2024-04-01','2024-07-01','2024-10-01'))
);
-- Hologres
BEGIN;
CREATE TABLE public.orders (
order_date DATE,
amount DECIMAL(18,2)
) PARTITION BY LIST (order_date);
-- Or use PARTITION BY RANGE if Hologres version supports it
COMMIT;
6. Stored Procedures → PL/pgSQL Functions
-- Synapse
CREATE PROCEDURE dbo.update_status @id INT, @status VARCHAR(20)
AS
BEGIN
UPDATE dbo.orders SET status = @status WHERE order_id = @id;
SELECT @@ROWCOUNT AS affected;
END;
-- Hologres
CREATE OR REPLACE FUNCTION public.update_status(p_id INT, p_status VARCHAR(20))
RETURNS TABLE(affected BIGINT) AS $$
DECLARE
row_cnt BIGINT;
BEGIN
UPDATE public.orders SET status = p_status WHERE order_id = p_id;
GET DIAGNOSTICS row_cnt = ROW_COUNT;
RETURN QUERY SELECT row_cnt;
END;
$$ LANGUAGE plpgsql;
7. External Tables
Synapse external tables (PolyBase / CETAS) need rewriting to Hologres foreign tables or federated queries. These are highly environment-specific — flag them and ask the user about the target data source.
7. Validation Checklist
After conversion, verify:
No remaining [] brackets
No GETDATE, ISNULL, LEN, CHARINDEX, IIF, STUFF etc.
No DATEDIFF, DATEADD, DATEPART, DATENAME
No TOP n (should be LIMIT n)
No WITH (NOLOCK) or query hints
No #temp or @table variables outside PL/pgSQL
No T-SQL data types (NVARCHAR, DATETIME2, BIT, MONEY, etc.)
CONCAT() preserved (not replaced with ||) for NULL safety
Statements end with ;
Schema references match Hologres target schemas
Identifier quoting matches Hologres conventions
SELECT column count matches the original SQL (no columns dropped)
FROM/JOIN structure preserved (no JOINs merged or split)
WHERE/GROUP BY/HAVING/ORDER BY clauses fully preserved
NULL handling semantics are correct (COALESCE, not ||)
8. Conversion Quality Requirements
Rules Must Be Compatible with All Data Values
The target expression of every conversion rule must be a generic expression compatible with all possible data values in that scenario — NULL, empty string, zero, normal values. Never assume "this field will never be NULL" or "this array will never be empty".
No NULL-Introducing Conversions
If a source SQL expression does not return NULL for non-NULL inputs, the converted expression must not introduce additional NULL risk either. Typical anti-pattern: replacing ISNULL(a,b) with a || b (which yields NULL when a is NULL).
Distance Validation Principle
The conversion result should minimize the "structural distance" from the original SQL:
Check Item
Requirement
SELECT column count
Identical
FROM/JOIN count
Unchanged
Subquery depth
Unchanged (no merging or splitting)
WHERE/GROUP BY clauses
Fully preserved
Distance validation fails → fall back to the original SQL and apply only the minimum changes needed to fix syntax differences.
Never omit TODO markers (uncertain mappings must be flagged)
Never output empty files or files containing only comments
Never merge multiple source files into a single output
Never include verbatim source-engine syntax keywords in output files (including SQL comments and conversion logs). Specific rules:
❌ Do not reference source-engine syntax verbatim in comments, e.g. MERGE, WHEN MATCHED, WHEN NOT MATCHED, [dbo]., GETDATE(), ISNULL, TOP n, SET NOCOUNT ON, @variable_name, etc.
❌ Do not write comments like -- NOTE: MERGE...WHEN MATCHED/NOT MATCHED → INSERT...ON CONFLICT
❌ Do not reference source-engine originals in conversion logs as "explanations of transformations", e.g. @ReportMonth → p_report_month, SET NOCOUNT ON → removed
✅ Comments should only describe target-engine semantics, e.g. -- upsert: update quantity and last_updated on conflict
✅ When indicating transformation origin, use abstract descriptions rather than source syntax, e.g. -- original upsert logic → INSERT ON CONFLICT (do not write the MERGE keyword)
✅ In logs, describe parameter renaming as: parameter renamed to p_report_month (do not write the original @-prefixed variable name)
✅ In logs, describe statement removal as: removed row-count control statement (not needed on target engine) (do not write SET NOCOUNT ON)
ran_scripts/conversion_log.md and other log files are equally subject to this rule, with no exceptions — "documenting transformations" is not a justification for using source-engine keywords verbatim
10. Additional Resources
Complete function and type mappings: reference.md
Before/after conversion examples: examples.md
DryRun errors and repair strategies: error-patterns.md
11. Extending to Other Engine Pairs (Four-Step Method)
This skill reserves extension slots for multiple engine pairs. To add a new language pair (e.g. Hive → MaxCompute):
Create references/<src>_to_<dst>.md using the same section structure as this document:
Add a " → Reference" section in reference.md with complete data-type and function mapping tables
Add before/after examples in examples.md
Update the corresponding row in the "Support Matrix" table above from 🟡 TODO to ✅
Conversion Rule Generalization Recommendations
The following rules are broadly reusable across most "T-SQL / traditional data-warehouse → PostgreSQL-family / MaxCompute" scenarios and can serve as starting points when adding new language pairs:
A construct fails repeatedly with no corresponding rule
Add rules to references files
Imprecise rule description
Rule exists but the Agent misinterprets it
Rewrite the rule and add examples
Error pattern not cataloged
A class of errors recurs without a repair strategy
Supplement error-patterns.md
Structurally non-auto-convertible
Fails across multiple rounds (e.g. recursive CTEs, GEOGRAPHY)
Flag for manual handling
Reflection Output
After each batch conversion, a reflection report is recommended, including:
Health metrics
Discovered failure patterns and their attribution
List of rules updated
Focus areas for the next evaluation round
1---2name: alibabacloud-migration-sdm-sql-trans3description: 跨大数据引擎的 SQL 语法转换技能(DML/DDL/存储过程)。覆盖标识符、数据类型、函数、查询语法、分布/分区策略、存储过程/函数、外表等重写场景。目前已实现 Synapse → Hologres,框架为其他引擎对(如 SQL Server → MaxCompute、Hive → Hologres、PostgreSQL → Hologres、Oracle → MaxCompute 等)预留了可扩展位置(TODO)。当用户需要将 SQL/T-SQL/PL-SQL 从一个数仓转换到另一个数仓、跨源迁移查询语句、T-SQL 转 PostgreSQL、数仓 SQL 兼容性改写时使用。不适用于:表结构 DDL 迁移(用 ddl-trans)、ADF 工作流迁移(用 adf2dw)、数据集成作业生成(用 dw-di-generator)。已知局限:不支持递归 CTE、动态 SQL 拼接、SQL Server GEOGRAPHY/GEOMETRY 等空间类型;基于规则匹配,转换结果建议人工审核。4---56> This skill has been validated on the Qoder / QoderWork platform. It is a pure content-generation skill that does not invoke external tools. It can also be used on other Agent platforms, though trigger matching behavior may vary.
78# Cross-Engine SQL Syntax Translation (migration-sdm-sql-trans)
910## Security Red Lines
1112- Never embed real customer database/table/column names in conversion examples or output (replace with `tbl_demo`, `col_x`)
13- Never embed real business data (phone numbers, IDs, account numbers, etc.) in example SQL; use placeholders where needed
14- Conversion output is generated content — **for reference only; human review before executing in production is recommended**
15- Never store any AK/SK, passwords, or plaintext connection strings in SKILL.md or references files
1617## MCP Tool Inventory
1819> This skill is pure content generation and does not depend on external MCP tools or CLI. All conversions are driven by built-in rule documents and mapping tables.
2021## 1. Overview
2223Provides SQL syntax conversion capabilities across big-data engines (DML / DDL / stored procedures / functions, etc.). This skill uses a **"multi-directional language-pair + extensible conversion-rules" architecture**, following a unified 5-step main process to complete each conversion, with implementations for additional engine pairs added incrementally.
2425## 2. When to Use / When NOT to Use
2627| When to Use | When NOT to Use |
28|-------------|-----------------|
29| Cross-data-warehouse SQL rewriting (T-SQL → PG, Hive → MaxCompute, etc.) | Table structure (DDL) migration only → `migration-sdm-ddl-trans` |
30| Full conversion of DML / views / stored procedures | ADF workflow migration → `migration-sdm-adf2dw` |
31| Compatibility checks and rewriting suggestions | Data integration job generation → `migration-sdm-dw-di-generator` |
3233## 3. Support Matrix
3435| Source → Target | Status | Implementation Location |
36|-----------------|--------|------------------------|
37| **Synapse (T-SQL) → Hologres (PostgreSQL)** | ✅ Implemented | "Scenario Implementation" section below + [reference.md](references/reference.md) + [examples.md](references/examples.md) |
38| SQL Server (T-SQL) → MaxCompute (ODPS-SQL) | 🟡 TODO | Pending `references/sqlserver_to_maxcompute.md` |
39| Hive QL → Hologres | 🟡 TODO | Pending `references/hive_to_hologres.md` |
40| Hive QL → MaxCompute | 🟡 TODO | Pending `references/hive_to_maxcompute.md` |
41| PostgreSQL → Hologres | 🟡 TODO | Pending `references/postgresql_to_hologres.md` |
42| Oracle (PL/SQL) → MaxCompute | 🟡 TODO | Pending `references/oracle_to_maxcompute.md` |
43| Teradata → MaxCompute / Hologres | 🟡 TODO | Pending `references/teradata_to_*.md` |
44| Snowflake → MaxCompute / Hologres | 🟡 TODO | Pending `references/snowflake_to_*.md` |
4546> **Important**: For language pairs marked 🟡 TODO in the table above, the corresponding `references/<src>_to_<dst>.md` files **have not yet been created**. When a user requests an unimplemented language pair, the Agent **must** explicitly inform the user that the pair is not yet implemented; fabricating conversion results based on speculation is strictly prohibited.
4748### Rejection Policy for Unimplemented Language Pairs (Hard Constraint)
4950When a user's conversion request involves a 🟡 TODO language pair (especially **Hive → Hologres**), the Agent **must** perform the following actions:
51521. **Explicitly inform**: "Hive → Hologres language pair is not yet implemented (TODO); no conversion rules are currently available."
532. **Suggest alternatives** (the reply must include specific, actionable recommendations):
54 - Manually convert by referencing the Synapse → Hologres rule structure in this document (identifiers / data types / functions / query syntax / DDL)
55 - Consult the data-type mapping table and function mapping table in [reference.md](references/reference.md) as a general reference
56 - Consult the official Alibaba Cloud Hologres documentation for SQL syntax details
573. **Absolutely prohibited**:
58 - ❌ Fabricating or extrapolating conversion results
59 - ❌ Outputting pseudo-conversions with `Status: PASS` or `-- TODO: verify` markers
60 - ❌ Pretending rules exist when the rewrite is actually a guess
61624. **Output delivery (hard requirement)**:
63 - The rejection notice and alternative suggestions **must be presented directly in the conversation reply**, not merely declared as "saved to a file"
64 - If a file needs to be written (e.g. `outputs/refusal_notice.md`), **the file write must actually be executed**; claiming a write was performed without doing so is prohibited
65 - **Hallucinated writes are prohibited**: any file mentioned in logs or replies as "saved / written / generated" must actually exist in the file system with complete content
66 - Recommended practice: reply directly in the conversation with the rejection notice and alternative suggestions — no extra file needed
6768> **Example rejection reply** (output directly in conversation, not written to a file):
69> "SQL conversion rules for Hive → Hologres are not yet implemented (only Synapse → Hologres is currently supported). Recommendations: ① Reference the Synapse → Hologres conversion rule structure in this skill and manually rewrite against Hive syntax; ② Consult the official Hologres documentation for PostgreSQL-compatible functions and data types; ③ Re-run automatic conversion once the `references/hive_to_hologres.md` rule file is added."
7071> **Extension method**: To add a new language pair, simply create `references/<src>_to_<dst>.md` using the same five-section template (identifiers / data types / functions / query syntax / DDL), and supplement the detailed mapping tables in [reference.md](references/reference.md). At runtime, the Agent loads the corresponding file based on the source/target pair.
7273## 4. Iron Rules (Violating Any Rule = Conversion Failure)
7475| # | Prohibition | Explanation |
76|---|-------------|-------------|
77| 0 | **No conversion for unimplemented language pairs** | Language pairs marked 🟡 TODO in the support matrix (e.g. Hive → Hologres) must be rejected with a notice to the user. Suggest manual conversion using the implemented Synapse → Hologres rules or official documentation. Never output speculative conversion results |
78| 1 | **No speculative SQL rewrites** | Every change must have a documented rule basis (this document / references / engines files) or an authoritative source. Rule not covered → keep original and annotate `-- TODO: verify` |
79| 2 | **No skipping validation** | All DML/DQL must pass the "Validation Checklist" item by item. "Too complex" or "should be fine" are not valid reasons to skip |
80| 3 | **Validation fails → no output** | When the validation checklist has unresolved items, never deliver results to the user; iterate until fixed |
81| 4 | **No structural loss** | Conversion must not drop or merge subqueries, reduce SELECT column count, or remove WHERE/GROUP BY/HAVING clauses |
82| 5 | **TRUNCATE must be preserved** | If the source SQL contains TRUNCATE, the conversion must preserve it |
83| 6 | **Each file runs the full pipeline independently** | Parse → Load Rules → Transform → Validate → Output. Never reuse a template from a previous file or skip steps |
84| 7 | **No hallucinated writes** | Never claim in logs or replies that a file has been "saved / written / generated" when no actual write was performed. Any file mentioned must exist in the file system with complete content |
8586---
8788## 5. Main Process (Universal 5-Step Skeleton)
8990All language pairs share the same conversion process:
9192```mermaid
93flowchart LR
94 A[Step 1<br>Parse] --> B[Step 2<br>Load Rules]
95 B --> C[Step 3<br>Transform]
96 C --> D[Step 4<br>Validate]
97 D --> E[Step 5<br>Output]
98 D -->|Fail| C
99```
100101| Step | Name | Description |
102|------|------|-------------|
103| 1 | **Parse** | Identify the scope of the input SQL: DML / DDL / stored procedure / hybrid; decompose complex SQL (see "Complex SQL Decomposition Strategy") |
104| 2 | **Load Rules** | Based on the "source → target" pair, load the rule set from the corresponding `references/<src>_to_<dst>.md` (identifiers / data types / functions / query syntax / DDL / procedural code) |
105| 3 | **Transform** | Apply rules in order: identifiers → data types → functions → query syntax → DDL → procedural. **Only change what the rules cover; leave everything else untouched** |
106| 4 | **Validate** | Run the "Validation Checklist" item by item; if any item fails, return to Step 3 for iterative repair (max 3 rounds) |
107| 5 | **Output** | Emit the converted SQL; add inline comments noting semantic differences and assumptions; mark uncertain mappings with `-- TODO: verify` |
108109### Complex SQL Decomposition Strategy
110111When the input SQL contains deeply nested subqueries (≥ 3 levels) or multiple CTEs combined with complex JOINs, apply a "transform from innermost layer outward" strategy:
1121131. Identify subquery levels (floor 0 = outermost, floor N = innermost)
1142. Start transforming from the highest-floor leaf nodes; sibling nodes at the same floor can be processed in parallel
1153. After a subquery is transformed, substitute the result back into the corresponding position in the parent query
1164. The parent query then re-enters the Step 2–4 transform loop
1175. Proceed layer by layer upward until the root query (floor 0) is completed
118119### Iterative Repair Process (Step 3 ↔ 4 Loop)
120121Repair strategy when validation fails:
122123| Round | Strategy |
124|-------|----------|
125| Round 1 | Identify the failing validation item and locate the corresponding rule to fix it |
126| Round 2 | If the same issue persists, consult [error-patterns.md](references/error-patterns.md) for repair strategies |
127| Round 3 | Fall back to the original SQL and re-transform with minimal changes; if still failing, annotate `-- TODO: manual review required` and output |
128129---
130131## 6. Scenario Implementation: Synapse → Hologres (Complete)
132133### Core Rules
134135#### 1. Identifiers
136137| Rule | Detail |
138|------|--------|
139| Remove `[]` | Synapse `[col]` → Hologres `col` (no brackets) |
140| Default: no quotes | Hologres folds unquoted identifiers to lowercase; if tables/columns are stored lowercase, do NOT add `""` |
141| Reserved words | If a column name is a PostgreSQL reserved word (e.g. `level`, `name`, `user`, `order`, `table`, `type`, `comment`), wrap in `""` |
142| Mixed-case needed | Only use `""` when the Hologres object was created with `""` and stores mixed case |
143| Schema mapping | `dbo.xxx` → verify target schema; Hologres default schema is `public`, not `dbo` |
144145**Decision logic**: Ask the user or infer from context whether their Hologres tables use lowercase (default) or mixed case. When unsure, default to no quotes and add a comment noting the assumption.
146147#### 2. Data Types
148149See [reference.md → Data Type Mapping](references/reference.md#data-type-mapping) for the complete table. Key conversions:
150151- `NVARCHAR/VARCHAR(MAX)` → `TEXT`
152- `DATETIME/DATETIME2/SMALLDATETIME` → `TIMESTAMP`
153- `DATETIMEOFFSET` → `TIMESTAMPTZ`
154- `BIT` → `BOOLEAN`
155- `TINYINT` → `SMALLINT`
156- `MONEY/SMALLMONEY` → `NUMERIC(19,4)` / `NUMERIC(10,4)`
157- `UNIQUEIDENTIFIER` → `UUID`
158- `VARBINARY/IMAGE` → `BYTEA`
159- `IDENTITY(seed,inc)` → `SERIAL` / `BIGSERIAL` or `GENERATED ALWAYS AS IDENTITY`
160161#### 3. Functions
162163See [reference.md → Function Mapping](references/reference.md#function-mapping) for the full reference. Critical conversions:
164165| Synapse | Hologres | Notes |
166|---------|----------|-------|
167| `GETDATE()` | `CURRENT_TIMESTAMP` | |
168| `ISNULL(a,b)` | `COALESCE(a,b)` | |
169| `DATEDIFF(day,a,b)` | `(b::date - a::date)` | Returns integer days |
170| `DATEADD(month,3,d)` | `d + INTERVAL '3 month'` | |
171| `LEN(s)` | `LENGTH(s)` | |
172| `CHARINDEX(sub,str)` | `POSITION(sub IN str)` | |
173| `IIF(cond,t,f)` | `CASE WHEN cond THEN t ELSE f END` | |
174| `CONVERT(type,expr)` | `CAST(expr AS type)` or `TO_CHAR` | |
175| `TOP n` | `LIMIT n` | Move to end of query |
176| `CONCAT(a,b)` | `CONCAT(a,b)` | Keep as-is; both are NULL-safe. Do NOT replace with `\|\|` which treats NULL differently |
177| `STRING_AGG` | `STRING_AGG` | Same syntax in both |
178| `CROSS APPLY` | `CROSS JOIN LATERAL` | |
179| `OUTER APPLY` | `LEFT JOIN LATERAL ... ON TRUE` | |
180| `STUFF(s,i,l,r)` | `OVERLAY(s PLACING r FROM i FOR l)` | |
181| `NEWID()` | `gen_random_uuid()` | PG 13+ built-in |
182| `FORMAT(val,fmt)` | `TO_CHAR(val,fmt)` | Format tokens differ |
183184#### 4. Query Syntax
185186| Synapse | Hologres |
187|---------|----------|
188| `SELECT TOP n ...` | `SELECT ... LIMIT n` |
189| `SELECT TOP n WITH TIES ...` | Use `FETCH FIRST n ROWS WITH TIES` |
190| `WITH (NOLOCK)` | Remove (Hologres uses MVCC) |
191| `OPTION (LABEL = ...)` | Remove |
192| `+` for string concat | `\|\|` (but prefer `CONCAT()` for NULL safety) |
193| `;` optional | `;` required as statement terminator |
194| `#temp_table` | `CREATE TEMPORARY TABLE temp_table` or use CTE |
195| `@table_variable` | Use CTE or `TEMPORARY TABLE` |
196| `DECLARE @var type = val` | In PL/pgSQL: `DECLARE var type := val;` |
197| `SET @var = expr` | In PL/pgSQL: `var := expr;` |
198199#### 5. DDL Conversion
200201##### Table Creation
202203```sql
204-- Synapse
205CREATE TABLE dbo.sales (
206 id INT IDENTITY(1,1),
207 name NVARCHAR(100),
208 amount MONEY,
209 created DATETIME2
210)
211WITH (
212 DISTRIBUTION = HASH(id),
213 CLUSTERED COLUMNSTORE INDEX
214);
215216-- Hologres
217BEGIN;
218CREATE TABLE public.sales (
219 id BIGSERIAL,
220 name TEXT,
221 amount NUMERIC(19,4),
222 created TIMESTAMP
223);
224CALL set_table_property('public.sales', 'distribution_key', 'id');
225CALL set_table_property('public.sales', 'orientation', 'column');
226COMMIT;
227```
228229##### Distribution Strategy
230231| Synapse | Hologres |
232|---------|----------|
233| `DISTRIBUTION = HASH(col)` | `CALL set_table_property('table', 'distribution_key', 'col')` |
234| `DISTRIBUTION = ROUND_ROBIN` | Omit distribution_key (Hologres defaults to random) |
235| `DISTRIBUTION = REPLICATE` | `CALL set_table_property('table', 'distribution_key', '')` (broadcast table) |
236237##### Index / Storage
238239| Synapse | Hologres |
240|---------|----------|
241| `CLUSTERED COLUMNSTORE INDEX` | `CALL set_table_property('t', 'orientation', 'column')` (default) |
242| `HEAP` | `CALL set_table_property('t', 'orientation', 'row')` |
243| `CLUSTERED INDEX(col)` | `CALL set_table_property('t', 'clustering_key', 'col')` |
244| Nonclustered index | `CREATE INDEX idx ON t(col)` (standard PG syntax) |
245246##### Partitioning
247248```sql
249-- Synapse
250CREATE TABLE dbo.orders (
251 order_date DATE,
252 amount DECIMAL(18,2)
253)
254WITH (
255 PARTITION (order_date RANGE RIGHT FOR VALUES
256 ('2024-01-01','2024-04-01','2024-07-01','2024-10-01'))
257);
258259-- Hologres
260BEGIN;
261CREATE TABLE public.orders (
262 order_date DATE,
263 amount DECIMAL(18,2)
264) PARTITION BY LIST (order_date);
265-- Or use PARTITION BY RANGE if Hologres version supports it
266COMMIT;
267```
268269#### 6. Stored Procedures → PL/pgSQL Functions
270271```sql
272-- Synapse
273CREATE PROCEDURE dbo.update_status @id INT, @status VARCHAR(20)
274AS
275BEGIN
276 UPDATE dbo.orders SET status = @status WHERE order_id = @id;
277 SELECT @@ROWCOUNT AS affected;
278END;
279280-- Hologres
281CREATE OR REPLACE FUNCTION public.update_status(p_id INT, p_status VARCHAR(20))
282RETURNS TABLE(affected BIGINT) AS $$
283DECLARE
284 row_cnt BIGINT;
285BEGIN
286 UPDATE public.orders SET status = p_status WHERE order_id = p_id;
287 GET DIAGNOSTICS row_cnt = ROW_COUNT;
288 RETURN QUERY SELECT row_cnt;
289END;
290$$ LANGUAGE plpgsql;
291```
292293#### 7. External Tables
294295Synapse external tables (PolyBase / CETAS) need rewriting to Hologres foreign tables or federated queries. These are highly environment-specific — flag them and ask the user about the target data source.
296297---
298299## 7. Validation Checklist
300301After conversion, verify:
302303- [ ] No remaining `[]` brackets
304- [ ] No `GETDATE`, `ISNULL`, `LEN`, `CHARINDEX`, `IIF`, `STUFF` etc.
305- [ ] No `DATEDIFF`, `DATEADD`, `DATEPART`, `DATENAME`
306- [ ] No `TOP n` (should be `LIMIT n`)
307- [ ] No `WITH (NOLOCK)` or query hints
308- [ ] No `#temp` or `@table` variables outside PL/pgSQL
309- [ ] No T-SQL data types (`NVARCHAR`, `DATETIME2`, `BIT`, `MONEY`, etc.)
310- [ ] `CONCAT()` preserved (not replaced with `||`) for NULL safety
311- [ ] Statements end with `;`
312- [ ] Schema references match Hologres target schemas
313- [ ] Identifier quoting matches Hologres conventions
314- [ ] SELECT column count matches the original SQL (no columns dropped)
315- [ ] FROM/JOIN structure preserved (no JOINs merged or split)
316- [ ] WHERE/GROUP BY/HAVING/ORDER BY clauses fully preserved
317- [ ] NULL handling semantics are correct (`COALESCE`, not `||`)
318319## 8. Conversion Quality Requirements
320321### Rules Must Be Compatible with All Data Values
322323The target expression of every conversion rule must be a generic expression compatible with all possible data values in that scenario — NULL, empty string, zero, normal values. Never assume "this field will never be NULL" or "this array will never be empty".
324325### No NULL-Introducing Conversions
326327If a source SQL expression does not return NULL for non-NULL inputs, the converted expression must not introduce additional NULL risk either. Typical anti-pattern: replacing `ISNULL(a,b)` with `a || b` (which yields NULL when `a` is NULL).
328329### Distance Validation Principle
330331The conversion result should minimize the "structural distance" from the original SQL:
332333| Check Item | Requirement |
334|------------|-------------|
335| SELECT column count | Identical |
336| FROM/JOIN count | Unchanged |
337| Subquery depth | Unchanged (no merging or splitting) |
338| WHERE/GROUP BY clauses | Fully preserved |
339340**Distance validation fails → fall back to the original SQL and apply only the minimum changes needed to fix syntax differences.**
341342## 9. Output Format Specification
343344Conversion results must follow this format:
345346```sql
347-- ============================================================
348-- Source: <source file name>
349-- Engine: <source engine> → <target engine>
350-- Status: PASS | PASS_WITH_TODO | FAIL
351-- ============================================================
352353-- Converted SQL content
354-- Add inline comments for semantic differences (using target-engine terminology only), e.g.:
355-- NOTE: date-difference calculation → (b::date - a::date), returns integer days
356SELECT ...;
357358-- TODO: verify - no corresponding rule for this construct; manual review required
359```
360361**Prohibited output content (negative constraints):**
362- Never output unvalidated SQL
363- Never omit TODO markers (uncertain mappings must be flagged)
364- Never output empty files or files containing only comments
365- Never merge multiple source files into a single output
366- **Never include verbatim source-engine syntax keywords in output files (including SQL comments and conversion logs)**. Specific rules:
367 - ❌ Do not reference source-engine syntax verbatim in comments, e.g. `MERGE`, `WHEN MATCHED`, `WHEN NOT MATCHED`, `[dbo].`, `GETDATE()`, `ISNULL`, `TOP n`, `SET NOCOUNT ON`, `@variable_name`, etc.
368 - ❌ Do not write comments like `-- NOTE: MERGE...WHEN MATCHED/NOT MATCHED → INSERT...ON CONFLICT`
369 - ❌ Do not reference source-engine originals in conversion logs as "explanations of transformations", e.g. `@ReportMonth → p_report_month`, `SET NOCOUNT ON → removed`
370 - ✅ Comments should only describe target-engine semantics, e.g. `-- upsert: update quantity and last_updated on conflict`
371 - ✅ When indicating transformation origin, use abstract descriptions rather than source syntax, e.g. `-- original upsert logic → INSERT ON CONFLICT` (do not write the MERGE keyword)
372 - ✅ In logs, describe parameter renaming as: `parameter renamed to p_report_month` (do not write the original `@`-prefixed variable name)
373 - ✅ In logs, describe statement removal as: `removed row-count control statement (not needed on target engine)` (do not write `SET NOCOUNT ON`)
374 - **`ran_scripts/conversion_log.md` and other log files are equally subject to this rule, with no exceptions** — "documenting transformations" is not a justification for using source-engine keywords verbatim
375376## 10. Additional Resources
377378- Complete function and type mappings: [reference.md](references/reference.md)
379- Before/after conversion examples: [examples.md](references/examples.md)
380- DryRun errors and repair strategies: [error-patterns.md](references/error-patterns.md)
381382## 11. Extending to Other Engine Pairs (Four-Step Method)
383384This skill reserves extension slots for multiple engine pairs. To add a new language pair (e.g. `Hive → MaxCompute`):
3853861. Create `references/<src>_to_<dst>.md` using the same section structure as this document:
387 - 1. Identifiers / 2. Data Types / 3. Functions / 4. Query Syntax / 5. DDL Conversion / 6. Procedural / 7. External Tables
3882. Add a "<src> → <dst> Reference" section in [reference.md](references/reference.md) with complete data-type and function mapping tables
3893. Add before/after examples in [examples.md](references/examples.md)
3904. Update the corresponding row in the "Support Matrix" table above from 🟡 TODO to ✅
391392### Conversion Rule Generalization Recommendations
393394The following rules are broadly reusable across most "T-SQL / traditional data-warehouse → PostgreSQL-family / MaxCompute" scenarios and can serve as starting points when adding new language pairs:
395396| Conversion Point | Example (T-SQL → PG/MC) |
397|------------------|--------------------------|
398| Identifier `[col]` → `col` / `` `col` `` | T-SQL → PG uses double quotes; MaxCompute uses backticks or none |
399| `TOP n` → `LIMIT n` | Works in both PG and MC |
400| `GETDATE()` → `CURRENT_TIMESTAMP` (PG) / `GETDATE()` (MC) | MaxCompute has its own GETDATE |
401| `ISNULL(a,b)` → `COALESCE(a,b)` | Works in both targets |
402| `CHARINDEX` → `POSITION` (PG) / `INSTR` (MC) | PG uses POSITION; MC uses INSTR |
403| `IIF` → `CASE WHEN ...` | Works in both targets |
404| `NVARCHAR/MAX` → `TEXT` (PG) / `STRING` (MC) | Must distinguish targets |
405| `IDENTITY` → `SERIAL/BIGSERIAL` (PG) / not supported; use sequence + concat (MC) | |
406| `WITH (NOLOCK)` → remove | Not needed in either PG or MC |
407| `BIT` → `BOOLEAN` (PG) / `BOOLEAN` (MC) | Comparison expressions must be updated simultaneously |
408409> When adding a new language pair, start with **reserved-word conflicts + data types** — these are the most error-prone areas in cross-engine migration.
410411## 12. Conversion Quality Evaluation and Reflection
412413For batch conversions, the following evaluation framework is recommended:
414415### Health Metrics
416417| Metric | Description |
418|--------|-------------|
419| First-pass rate | Proportion of conversions that pass validation on the first attempt |
420| Post-iteration pass rate | Proportion that passes after multiple repair rounds |
421| Final failure rate | Proportion that cannot be auto-converted |
422| Average iteration rounds | Average repair rounds for successful cases |
423424### Root-Cause Attribution (for failing / high-iteration cases)
425426| Responsible Party | Evidence | Improvement Direction |
427|-------------------|----------|----------------------|
428| **Missing rule** | A construct fails repeatedly with no corresponding rule | Add rules to references files |
429| **Imprecise rule description** | Rule exists but the Agent misinterprets it | Rewrite the rule and add examples |
430| **Error pattern not cataloged** | A class of errors recurs without a repair strategy | Supplement [error-patterns.md](references/error-patterns.md) |
431| **Structurally non-auto-convertible** | Fails across multiple rounds (e.g. recursive CTEs, GEOGRAPHY) | Flag for manual handling |
432433### Reflection Output
434435After each batch conversion, a reflection report is recommended, including:
436- Health metrics
437- Discovered failure patterns and their attribution
438- List of rules updated
439- Focus areas for the next evaluation round
Run npx skillmds@latest add aliyun/alibabacloud-migration-sdm-sql-trans in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
跨大数据引擎的 SQL 语法转换技能(DML/DDL/存储过程)。覆盖标识符、数据类型、函数、查询语法、分布/分区策略、存储过程/函数、外表等重写场景。目前已实现 Synapse → Hologres,框架为其他引擎对(如 SQL Server → MaxCompute、Hive → Hologres、PostgreSQL → Hologres、Oracle → MaxCompute 等)预留了可扩展位置(TODO)。当用户需要将 SQL/T-SQL/PL-SQL 从一个数仓转换到另一个数仓、跨源迁移查询语句、T-SQL 转 PostgreSQL、数仓 SQL 兼容性改写时使用。不适用于:表结构 DDL 迁移(用 ddl-trans)、ADF 工作流迁移(用 adf2dw)、数据集成作业生成(用 dw-di-generator)。已知局限:不支持递归 CTE、动态 SQL 拼接、SQL Server GEOGRAPHY/GEOMETRY 等空间类型;基于规则匹配,转换结果建议人工审核。 It is listed under Data & Analytics on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Capability flags: makes network calls. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
aliyun (@aliyun) published this skill. Their other Agent Skills are listed on their SkillMD profile.