AgentSkillsCN

Dialect Translator

方言转换器

SKILL.md

SQL Dialect Translator

Convert SQL queries between different database dialects (PostgreSQL, MySQL, SQL Server, Oracle, SQLite).

Trigger Conditions

Activate this skill when the user:

  • Says "convert to PostgreSQL/MySQL/etc."
  • Asks to migrate queries between databases
  • Needs help with dialect-specific syntax
  • Asks about differences between SQL dialects
  • Has queries failing after database migration

Translation Workflow

code
1. IDENTIFY    -> Detect source dialect
2. ANALYZE     -> Find dialect-specific features
3. MAP         -> Identify equivalent features in target
4. TRANSLATE   -> Convert syntax
5. VALIDATE    -> Verify correctness
6. OPTIMIZE    -> Apply target dialect best practices

Dialect Feature Comparison

Data Types

FeaturePostgreSQLMySQLSQL ServerOracleSQLite
Auto-incrementSERIAL, BIGSERIALAUTO_INCREMENTIDENTITYSEQUENCEINTEGER PRIMARY KEY
BooleanBOOLEANTINYINT(1), BOOLEANBITNUMBER(1)INTEGER
Text (unlimited)TEXTLONGTEXTVARCHAR(MAX)CLOBTEXT
BinaryBYTEABLOBVARBINARY(MAX)BLOBBLOB
JSONJSON, JSONBJSONNVARCHAR(MAX)JSON (21c+)TEXT
UUIDUUIDCHAR(36)UNIQUEIDENTIFIERRAW(16)TEXT
DateDATEDATEDATEDATETEXT
TimestampTIMESTAMPDATETIMEDATETIME2TIMESTAMPTEXT
ArrayARRAY[]JSONN/AVARRAYN/A

String Functions

OperationPostgreSQLMySQLSQL ServerOracle
Concatenate|| or CONCATCONCAT+ or CONCAT||
SubstringSUBSTRING(s, start, len)SUBSTRING(s, start, len)SUBSTRING(s, start, len)SUBSTR(s, start, len)
LengthLENGTHLENGTH, CHAR_LENGTHLENLENGTH
LowercaseLOWERLOWERLOWERLOWER
UppercaseUPPERUPPERUPPERUPPER
TrimTRIMTRIMLTRIM, RTRIMTRIM
PositionPOSITION(x IN y)LOCATE(x, y)CHARINDEX(x, y)INSTR(y, x)
ReplaceREPLACEREPLACEREPLACEREPLACE
Pad leftLPADLPADRIGHT(REPLICATE...)LPAD
Regex match~REGEXPLIKE (limited)REGEXP_LIKE

Date/Time Functions

OperationPostgreSQLMySQLSQL ServerOracle
Current dateCURRENT_DATECURDATE()GETDATE()SYSDATE
Current timestampCURRENT_TIMESTAMPNOW()GETDATE()SYSTIMESTAMP
Extract partEXTRACT(part FROM date)EXTRACT(part FROM date)DATEPART(part, date)EXTRACT(part FROM date)
Date adddate + INTERVAL '1 day'DATE_ADD(date, INTERVAL 1 DAY)DATEADD(day, 1, date)date + 1
Date diffdate1 - date2DATEDIFF(date1, date2)DATEDIFF(day, date1, date2)date1 - date2
Format dateTO_CHAR(date, 'fmt')DATE_FORMAT(date, 'fmt')FORMAT(date, 'fmt')TO_CHAR(date, 'fmt')
Parse dateTO_DATE(str, 'fmt')STR_TO_DATE(str, 'fmt')CONVERT(date, str)TO_DATE(str, 'fmt')
TruncateDATE_TRUNC('month', date)DATE_FORMAT(date, '%Y-%m-01')DATETRUNC(month, date)TRUNC(date, 'MM')

Limiting Results

DialectSyntax
PostgreSQLLIMIT 10 OFFSET 20
MySQLLIMIT 10 OFFSET 20 or LIMIT 20, 10
SQL ServerOFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY (2012+) or TOP 10
OracleOFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY (12c+) or ROWNUM
SQLiteLIMIT 10 OFFSET 20

Identifier Quoting

DialectSyntax
PostgreSQLDouble quotes: "table"
MySQLBackticks: `table`
SQL ServerSquare brackets: [table] or double quotes
OracleDouble quotes: "TABLE" (case-sensitive)
SQLiteDouble quotes, backticks, or square brackets

NULL Handling

OperationPostgreSQLMySQLSQL ServerOracle
CoalesceCOALESCE, NULLIFCOALESCE, IFNULL, NULLIFCOALESCE, ISNULL, NULLIFCOALESCE, NVL, NULLIF
NULL-safe equalIS NOT DISTINCT FROM<=>N/AN/A
First non-nullCOALESCECOALESCECOALESCENVL, COALESCE

Conditional Logic

OperationPostgreSQLMySQLSQL ServerOracle
If-thenCASE WHENCASE WHEN, IF()CASE WHEN, IIF()CASE WHEN, DECODE
Null checkNULLIF, COALESCENULLIF, IFNULLNULLIF, ISNULLNVL, NVL2

Upsert/Merge

PostgreSQL:

sql
INSERT INTO table (id, name) VALUES (1, 'test')
ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name;

MySQL:

sql
INSERT INTO table (id, name) VALUES (1, 'test')
ON DUPLICATE KEY UPDATE name = VALUES(name);

SQL Server:

sql
MERGE INTO table AS target
USING (VALUES (1, 'test')) AS source (id, name)
ON target.id = source.id
WHEN MATCHED THEN UPDATE SET name = source.name
WHEN NOT MATCHED THEN INSERT (id, name) VALUES (source.id, source.name);

Oracle:

sql
MERGE INTO table target
USING (SELECT 1 AS id, 'test' AS name FROM dual) source
ON (target.id = source.id)
WHEN MATCHED THEN UPDATE SET target.name = source.name
WHEN NOT MATCHED THEN INSERT (id, name) VALUES (source.id, source.name);

Common Table Expressions

All modern versions support standard CTE syntax:

sql
WITH cte AS (
    SELECT ...
)
SELECT * FROM cte;

Recursive CTEs:

  • PostgreSQL: WITH RECURSIVE
  • MySQL 8.0+: WITH RECURSIVE
  • SQL Server: WITH (recursive by default when self-referencing)
  • Oracle: WITH (use CONNECT BY for older versions)

Window Functions

All modern databases support standard window functions. Key differences:

FeaturePostgreSQLMySQLSQL ServerOracle
FILTER clauseYesNoNoNo
Frame: GROUPSYesYes (8.0+)NoYes
PERCENTILE_CONTYesNo (use variable)YesYes
STRING_AGGSTRING_AGGGROUP_CONCATSTRING_AGGLISTAGG

JSON Support

PostgreSQL:

sql
SELECT data->>'name' FROM table;
SELECT data->'nested'->>'field' FROM table;
SELECT data @> '{"key": "value"}' FROM table;

MySQL:

sql
SELECT JSON_EXTRACT(data, '$.name') FROM table;
SELECT data->'$.name' FROM table;
SELECT JSON_CONTAINS(data, '"value"', '$.key') FROM table;

SQL Server:

sql
SELECT JSON_VALUE(data, '$.name') FROM table;
SELECT JSON_QUERY(data, '$.nested') FROM table;

Translation Examples

LIMIT/OFFSET Translation

PostgreSQL:

sql
SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 20;

To SQL Server:

sql
SELECT * FROM users ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

To Oracle (12c+):

sql
SELECT * FROM users ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

To Oracle (11g):

sql
SELECT * FROM (
    SELECT t.*, ROWNUM rn FROM (
        SELECT * FROM users ORDER BY id
    ) t WHERE ROWNUM <= 30
) WHERE rn > 20;

Auto-Increment Translation

PostgreSQL:

sql
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100)
);

To MySQL:

sql
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
);

To SQL Server:

sql
CREATE TABLE users (
    id INT IDENTITY(1,1) PRIMARY KEY,
    name VARCHAR(100)
);

To Oracle:

sql
CREATE TABLE users (
    id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    name VARCHAR2(100)
);

String Concatenation Translation

PostgreSQL:

sql
SELECT first_name || ' ' || last_name AS full_name FROM users;

To MySQL:

sql
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;

To SQL Server:

sql
SELECT first_name + ' ' + last_name AS full_name FROM users;
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;

Date Arithmetic Translation

PostgreSQL:

sql
SELECT created_at + INTERVAL '30 days' FROM users;
SELECT DATE_TRUNC('month', created_at) FROM users;

To MySQL:

sql
SELECT DATE_ADD(created_at, INTERVAL 30 DAY) FROM users;
SELECT DATE_FORMAT(created_at, '%Y-%m-01') FROM users;

To SQL Server:

sql
SELECT DATEADD(day, 30, created_at) FROM users;
SELECT DATETRUNC(month, created_at) FROM users;  -- SQL Server 2022+
SELECT DATEFROMPARTS(YEAR(created_at), MONTH(created_at), 1) FROM users;  -- Earlier

To Oracle:

sql
SELECT created_at + 30 FROM users;
SELECT TRUNC(created_at, 'MM') FROM users;

Boolean Translation

PostgreSQL:

sql
SELECT * FROM users WHERE is_active = TRUE;

To MySQL:

sql
SELECT * FROM users WHERE is_active = 1;
SELECT * FROM users WHERE is_active = TRUE;  -- Also works

To SQL Server:

sql
SELECT * FROM users WHERE is_active = 1;

To Oracle:

sql
SELECT * FROM users WHERE is_active = 1;

Output Format

When translating queries:

  1. Source: Original query with identified dialect
  2. Target: Translated query for target dialect
  3. Changes Made: List of modifications
  4. Caveats: Any functionality differences or limitations
  5. Alternatives: Other approaches if applicable

Additional Resources

FileContent
examples.mdComplete translation examples