
# Babelfish部分支持的功能示例
Babelfish 的每个迭代版本都在逐步扩展对 T-SQL 功能的支持范围，以提升兼容性。但当前版本仍存在部分未支持功能及行为差异，下文详细列出了 Babelfish 与 T-SQL 之间的功能差异，并对部分有差异的部分提供建议的改造方案。
#### 视图
在Babelfish中不存在如下SQL Server系统视图，详情如[表1]。
 表1Babelfish中不存在的SQL Server系统视图 
| 视图名称                                            | 功能描述                       |
|:---|:---|
| sys.parameters                                  | 包含存储过程、函数等对象的参数信息。         |
| sys.periods                                     | 存储时态表（历史表）的时间周期定义信息。       |
| sys.service_queues                              | 提供Service Broker服务队列的配置信息。 |
| sys.sql_dependencies                            | 记录数据库对象之间的依赖关系。            |
| sys.stats_columns                               | 显示统计信息关联的列信息。              |
| sys.masked_columns                              | 包含动态数据掩码应用的列信息。            |
| sys.memory_optimized_tables_internal_attributes | 内存优化表的内部属性信息。              |
| sys.numbered_procedure_parameters               | 包含编号存储过程的参数信息。             |
| sys.allocation_units                            | 显示数据库中分配单元(存储结构)的信息。       |
| sys.event_notifications                         | 包含事件通知配置信息。                |
| sys.extended_procedures                         | 提供扩展存储过程信息。                |
| sys.function_order_columns                      | 包含CLR表值函数中顺序列的信息。          |
| sys.trigger_event_types                         | 列出触发器可以响应的事件类型。            |
   
#### ROWVERSION/TIMESTAMP 赋值行为差异
在 SQL Server 中，每插入（INSERT）或更新（UPDATE）一行均会分配唯一的 ROWVERSION/TIMESTAMP 值，而Babelfish在同一语句中修改的所有行将分配相同的 ROWVERSION/TIMESTAMP值。
例如，当执行影响多行的 UPDATE 或 INSERT SELECT操作时：
- SQL Server 会为每一行的 ROWVERSION/TIMESTAMP 列生成不同值。
- Babelfish (PostgreSQL) 会为所有受影响行赋予相同值。
 
#### 对JSON数据类型提供有限兼容支持
Babelfish不直接支持SQL Server原生JSON数据类型。而是存储为NVARCHAR、VARCHAR或TEXT数据类型。更多详细信息请参考[JSON data in SQL Server](https://learn.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server?view=azuresqldb-current)和[JSON data type](https://learn.microsoft.com/en-us/sql/t-sql/data-types/json-data-type?view=azuresqldb-current#feature-availability)。
以下JSON函数是Babelfish支持的函数，可以操作JSON：
- JSON_VALUE
- JSON_QUERY
- OPENJSON
- JSON_MODIFY
- ISJSON
 
#### 标识符差异
T-SQL中定义的索引名 ix1在表t1上，Babelfish会将其内部重命名为类似ix1t1a5111d2a1767bc43a700e9f2162be019 的形式（ix1t1 + 哈希值）。
- T-SQL透明性：用户仍使用原始标识符编写查询，Babelfish自动映射到内部名称。
- PostgreSQL可见性：在PostgreSQL端（如通过psql查看），实际对象名是包含哈希值的名称。
Babelfish通过哈希算法动态调整标识符，既兼容了SQL Server的长名称和宽松规则，又满足了PostgreSQL的严格限制。这种处理对T-SQL用户无感知，但需注意在PostgreSQL中看到的对象名会包含哈希后缀。更多详细信息参考[Babelfish官方文档标识符描述](https://babelfishpg.org/docs/usage/interoperability)。
Babelfish中标识符差异对系统视图的影响：
- 若对象名称\<= 64个字符，通过SQL命令访问该对象无影响（use、select等SQL命令），且在sys.databases、sys.indexes、sys.table等系统视图中存储的是对象原始名称。
- 若对象名称\>64个字符，通过SQL命令访问该对象无影响（use、select等SQL命令），但在sys.databases、sys.indexes、sys.tables等系统视图中存储的是对象经过转换后的名称"部分前缀+hash值"，且通过简单的字符串处理无法还原对象原始名称。
标识符差异的影响场景：
- DRS在以Babelfish为目标端的迁移链路中，迁移开始前会对目标Babelfish实例进行预检查。预检查会根据sys.\*系统视图查询对象是否已存在，如果源端SQL Server存在超过64个字符的数据库对象，则预检查会存在问题。
- 用户的业务访问sys.\*系统视图时，对于超过64字符的对象，也会存在查找无结果的问题。
 
#### 系统视图表差异
如下视图存在差异：
#### sys.hash_indexes
- 列缺失：is_ignored_in_optimization 列在 Babelfish 中不存在。 ![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002353902517.png "点击放大")
  
- 数据类型匹配：name 列的数据类型一致（因为sysname 是 nvarchar 的别名，不存在不兼容），**sys.triggers** ，**sys.procedures** ，**sys.check_constraints** 同此。
  ![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002353782713.png "点击放大")
  
 
#### sys.index_columns
Babelfish缺失column_store_order_ordinal列：
![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002313371680.png "点击放大")
#### sys.system_objects 和 sys.all_objects
- sysname：nvarchar 的别名。
- type：在mssql和babelfish中都存在。
 
#### sys.objects
Babelfish 的sys.objects也有type列, babelfish的"type"列的类型是char(2)，与mssql匹配，**sys.sequences 同此**；
sysname是nvarchar的别名，所以不是兼容性问题。
#### sys.schemas
![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002347541581.png "点击放大")
Babelfish也有schema_id和principal_id列，它们的类型是"oid"，是一个4字节的int数据类型，所以不存在兼容性问题，详细信息参考[oid类型官方说明](https://www.postgresql.org/docs/current/datatype-oid.html)
#### sys.sql_modules
Babelfish中缺失inline_type 和 is_inlineable 列。
![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002316078468.png "点击放大")
#### sys.computed_columns
sysname是nvarchar的别名，不存在兼容性问题。
另一个不同点是：MSSQL 使用 tinyint，而 Babelfish 使用 int。由于 int 类型比 tinyint 大，因此这一点上，应用程序从 MSSQL 迁移到 Babelfish不存在不兼容。
![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002350160841.png "点击放大")
在[Microsoft 的文档](https://learn.microsoft.com/de-de/sql/t-sql/data-types/int-bigint-smallint-and-tinyint-transact-sql?view=sql-server-ver17)中，给出了 tinyint 和 int 的限制，如下所示：
![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002316082216.png "点击放大")
sys.table_types和 sys.types 同此。
另外，Babelfish一侧，**sys.computed_columns**缺少以下列：
![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002317644534.png "点击放大")
#### sys.sysdatabases
差异如表
![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002350622025.png "点击放大")
'TEXT' 变量比 'sysname' （128字符）大，因此不存在不兼容。
#### sys.sysprocesses
- spid、blocked、dbid 列在 MS-SQL 中定义为 smallint，在 BABELFISH 中定义为 int。
- 在 Babelfish 的 中未定义 "uid" 列的类型 ID，根据 Postgres 文档，该类型当前实现为无符号的四字节整数 oid； 也未定义 "context_info" 列的类型 ID，根据 Postgres 文档，数据类型允许存储二进制字符串 bytea
  
- "loginname"（ms-sql） 和 "loginame"（babelfish）， babelfish一侧缺少 'n' 字符。
- babelfish缺少"page_resource"列。
影响：不影响功能使用。
#### sys.key_constraints
sysname 是 nvarchar（128） 的别名。
Babelfish缺失is_enforced列，在 SQL Server 中，此列告诉我们是否强制执行了 PRIMARY KEY 或 UNIQUE 约束，即 SQL Server 在数据修改期间是否主动检查唯一性，在Babelfish中不支持该参数。
#### sys.default_constraints
sysname 是 nvarchar（128） 的别名; "modified_date" 与 "modify_date" 等同。
![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002317708218.png "点击放大")
#### sys.stats
sysname 是 nvarchar（128） 的别名， babelfish中缺少 "auto_drop" 列。
#### sys.indexes
Babelfish缺少以下几列：
| 列名 (Column)                 | 用途 (Purpose)        | 适用对象 (Applies To)              |
|:---|:---|:---|
| compression_delay           | 延迟压缩行组的时间（列存储索引）    | 列存储索引 (Columnstore indexes)    |
| suppress_dup_key_messages   | 抑制重复键错误的详细提示信息      | 唯一索引 (Unique indexes)          |
| optimize_for_sequential_key | 优化递增键索引的插入性能，减少插入争用 | B树索引（如自增列上的索引）(B-tree indexes) |
| is_ignored_in_optimization  | 在查询优化过程中忽略该索引       | 所有索引类型 (Any index)             |
   
#### sys.identity_columns
Babelfish缺少以下几列：
| 列名 (Column Name)               | 描述 (Description)                               |
|:---|:---|
| is_data_deletion_filter_column | 标识该列是否用于筛选账本视图（ledger view）中的数据删除操作。           |
| ledger_view_column_type        | 账本视图列的数字类型（用于内部存储）。                            |
| ledger_view_column_type_desc   | 账本视图列的描述性类型（如 GENERATED ALWAYS 或 APPEND_ONLY）。 |
| is_dropped_ledger_column       | 标识该列是否原本属于账本表（ledger table），但已被删除。             |
| graph_type                     | 图的列的数字类型（用于内部存储）。                              |
| graph_type_desc                | 图的列的描述性类型（如 NODE 或 EDGE）。                      |
   
#### sys.syscharsets
与之前的类似，MSSQL是smallint和tiny，babelfish是int的区别，不再赘述。
#### sys.assembly_modules/sys.synonyms
与之前的类似，sysname 是 nvarchar（128） 的别名，不再赘述。
#### 表元数据不匹配说明
如下视图表元数据不匹配，详情见前文，不再赘述，不匹配是由于 SQL Server 和 PostgreSQL（Babelfish 的底层引擎）之间的架构差异而导致的预期差异，只是列中的文本表示形式不同，但从功能上讲，返回的元数据是等效的，因此不会影响使用 Babelfish 的应用程序的功能正确性。
- **sys.views**
- **sys.columns**
- **sys.databases**
- **sys.foreign_keys**
- **sys.all_views**
- **sys.partitions**
- **sys.sql_expression_dependencies**
- **sys.all_columns**
- **sys.tables**
 
#### 参数
Babelfish不支持以下设置：
SET ANSI_NULL_DFLT_OFF ON
SET ANSI_NULL_DFLT_ON OFF
SET ANSI_PADDING OFF
SET ANSI_WARNINGS OFF
这将导致SET ANSI_DEFAULTS命令对于这些服务器端设置无法正常工作。
以下参数禁止修改：
![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002349411233.png "点击放大")
更多详细内容请参考[Babelfish官方文档-不应修改的参数](https://babelfishpg.org/docs/internals/configuration/#parameters-that-should-not-be-modified)
#### 游标（cursors）
Babelfish中不支持SET CURSOR_Closed_ON_COMMIT ON。此外，Babelfish不识别在存储过程或函数中动态定义的游标。作为一种解决方法，您可以使用临时表重写此类游标。
也不支持以下游标类型和行为：
- 可更新游标（Updatable cursors）
- 全局游标（Global cursors）
- 不支持游标提取行为：FETCH PRIOR, FIRST, LAST, ABSOLUTE, 和 RELATIVE 。
- 游标类型的输出参数：游标类型的变量和参数不能用作输出参数（会引发错误）。
- 光标选项：不支持以下选项：SCROLL, KEYSET, DYNAMIC, FAST_FORWARD, SCROLL_LOCKS, OPTIMISTIC, TYPE_WARNING, 和 FOR UPDATE。
此外，[Babelfish社区文档](https://babelfishpg.org/docs/usage/limitations-of-babelfish/)指出："当 ANSI_DEFAULTS 开启时，它会启用以下设置：ANSI_NULLS、ANSI_NULL_DFLT_ON、IMPLICIT_TRANSACTIONS、ANSI_PADDING、QUOTED_IDENTIFIER、ANSI_WARNINGS 和 CURSOR_CLOSE_ON_COMMIT。驱动程序和提供商将 CURSOR_CLOSE_ON_COMMIT 和 IMPLICIT_TRANSACTIONS 设置为 OFF（因此CURSOR_CLOSE_ON_COMMIT 实际上在连接时处于 OFF 状态，尽管 ANSI_DEFAULTS 处于 ON 状态）"。
#### 命令
- SET STATISTICS 和SET STATISTICS_ALL 不支持，但是有代替的功能：
  - SET BABELFISH_STATISTICS PROFILE \[ON\|OFF\]：对于实际查询执行计划，设置为 ON，此函数实现了PostgreSQL 命令EXPLAIN ANALYZE 的功能。
  
  - SET BABELFISH_SHOWPLAN_ALL \[ON\|OFF\] ：设置为 ON 可生成估计的查询执行计划，此函数实现 PostgreSQL 的 EXPLAIN 命令的行为，使用此命令获取给定查询的解释计划。
  
  
  另外，babelfish社区文档中表示："**从版本 2.2.0 开始，您可以将 escape_hatch_showplan_all 参数设置为 *ignore* ，以避免在 SQL Server 语法中对 SHOWPLAN_ALL 和 STATISTICS PROFILE SET 命令使用 *BABELFISH_* 前缀。"**
  因此，为了将其用作不带 BABELFISH 前缀的 SET **SHOWPLAN_ALL** 和 SET STATISTICS PROFILE 应该运行：
  ```
  EXEC sp_babelfish_configure 'babelfishpg_tsql.escape_hatch_showplan_all', 'ignore';
  ```
  或：
  ```
  EXEC sp_babelfish_configure 'babelfishpg_tsql.escape_hatch_showplan_all', 'strict';
  ```
  可以使用 sp_babelfish_configure 更改参数的设置，如下例所示：
  ```
  execute sp_babelfish_configure 'explain_buffers', 'on';
  ```
  

- Babelfish不支持SET SHOWPLAN_XML Babelfish可以输出查询计划，并且可以以 XML 格式输出查询计划。详细信息请[参考文档](https://babelfishpg.org/docs/usage/query_planning/)了解如何查看Babelfish 查询计划。
  在运行查询之前，您可以使用以下方法可视化STATISTICS PROFILE，可视化时需执行SET BABELFISH_STATISTICS PROFILE ON。
  - 执行如下命令设置说明格式。
    ```
    execute sp_babelfish_configure 'explain_format'， 'xml'
    ```
    
  
  - 执行如下命令进行可视化。
    ```
    select set_config（'babelfishpg_tsql.explain_format'， 'xml'， false）;
    ```
    ```
    SET BABELFISH_STATISTICS PROFILE ON;
    ```
    
   

- Babelfish 不支持SET FORCEPLAN。
- Babelfish 不支持SET SHOWPLAN_TEXT。
- 对于SET NOEXEC，Babelfish只支持"OFF",更多详细信息请参考[Babelfish限制社区文档](https://babelfishpg.org/docs/limitations/usf_2.1.0/)。
- Babelfish不支持SET TEXTSIZE功能，但有代替功能，如下： Babelfish在会话初始化时，将TEXTSIZE参数设置为4096。如果要更改它，按如下操作：
  如果将 "-y" 参数设置为小于 "TEXTSIZE" 值，则无法调整输出的文本大小，这种情况下，优先考虑-y参数。
  1. 使用sqlcmd命令行工具，执行以下命令进行连接。
     ```
     sqlcmd -U babelfish_user -P 12345678 -No -y <textsize_value>
     ```
     
  
  2. 设置TEXTSIZE参数。
     ```
     SET TEXTSIZE <textsize_value>
     ```
     
  
  3. 执行如下命令查询TEXTSIZE参数的值。
     ```
     SELECT id, LEFT(name, CAST(current_setting('babelfishpg_tsql.textsize') as int )) AS name FROM <table_name>;
     ```
     ```
     SELECT * FROM <table_name>;
     ```
     
   
 
#### 函数
如下函数存在差异。
#### DATABASE_PRINCIPAL_ID()
该函数定义了两种有效的使用模式：
- 不带参数，检索当前用户的数据库主体 ID。
- 使用指定的数据库主体名称作为字符串输入，例如（ 'db_owner'）。
因此用户应避免传递空字符串：DATABASE_PRINCIPAL_ID('')，这是不受支持的用法。对此函数详细解释请参考[DATABASE_PRINCIPAL_ID](https://learn.microsoft.com/en-us/sql/t-sql/functions/database-principal-id-transact-sql?view=sql-server-ver16)。
#### FULLTEXTSERVICEPROPERTY()
Babelfish中无论输入参数如何，函数总是返回0，因为当前在 Babelfish 中不支持全文搜索功能；
在 SQL Server 中，无效属性通常会返回NULL ，如果安装并启用了括号内的服务，则返回1，例如FULLTEXTSERVICEPROPERTY('IsFullTextInstalled') 返回 1。
#### concat_ws
PostgreSQL（PG） 中的一个字符串聚合函数，用于将多个字符串（或文本值）按指定的 分隔符（separator） 连接成一个字符串。
**函数语法**：
```
concat_ws(separator, str1, str2, ..., strN)
```
注意：第一个参数用作分隔符字符串，不应为 NULL，否则会返回NULL。其他参数填 NULL 无影响，会自动忽略。详情见[postgresql官方文档说明](https://www.postgresql.org/docs/16/functions-string.html)，这一点上babelfish与pg保持一致。
因此为了正常使用此函数，用户应避免在第一个参数填入NULL。
#### HAS_PERMS_BY_NAME
SQL Server 中的一个安全相关函数，用于检查当前用户对指定数据库对象是否拥有特定权限。
**函数语法**：
```
HAS_PERMS_BY_NAME (
securable,
securable_class,
permission
)
```
**参数说明**
- securable ：安全对象名称。要检查权限的对象名称，可以是表、视图、存储过程等数据库对象，为 NULL 时表示当前数据库。
- securable_class：安全对象类别。 支持的对象类型：如 DATABASE, OBJECT, SCHEMA, TABLE, VIEW 等。
  
- permission：权限，即要检查的具体权限，如 'SELECT', 'INSERT', 'UPDATE', 'DELETE' 等。
**返回值**
- 1：用户拥有指定权限。
- 0：用户不拥有指定权限。
- NULL：参数无效或查询失败。
 
**SQL server与babelfish差异**
- 当对象名称为 NULL 但指定了对象类别时，SQL Server 会认为这是检查当前数据库的权限并返回 1；
- 而 Babelfish 实现则要求这种情况下两个参数必须同时为 NULL 或同时不为 NULL，否则返回 NULL。
 
#### 服务器身份验证输出不匹配
因为如果身份验证方法设置为 trust，PostgreSQL 将允许在不验证密码的情况下登录，这是问题的根本原因。
为了确保强制实施密码身份验证，我们必须验证pg_hba.conf文件没有对有问题的用户使用trust方法。
按以下步骤操作：
1. 打开pg_hba.conf文件，该文件通常位于PostgreSQL数据目录（例如，/home/postgres/taurus-postgres/pg/install/data/pg_hba.conf或类似目录）中。
2. 查找与特定用户或连接类型（例如，local、host）相关的条目。
3. 确保将方法字段设置为md5（而不是trust），这将强制进行密码检查。
![](https://support.huaweicloud.com/kerneldesc-taurusdb-pg/figure/zh-cn_image_0000002319377086.png "点击放大")
DATEADD函数输出不匹配：
运行此命令：
```
SELECT 'DATEADD - NULL Interval' AS TestCase, DATEADD(DAY, NULL, '2025-04-25') AS Result;
```
MSSQL报错：NULL 不是有效的参数，但是BABELFISH返回NULL
原因：DATEADD 函数的调用方已使用 "STRICT" 关键字进行声明，STRICT指示每当函数的任何参数为 null 时，该函数始终返回 null，见[参考文档](https://www.postgresql.org/docs/16/sql-createfunction.html)。
#### 时间精度
- MS SQL：SQL Server 支持将datetime2数据类型精度精确到 7 位数字和 3 位小数数字的几分之一秒。SQL Server 将此精度舍入为 3 毫秒。这意味着，当您存储特定时间值时，毫秒可能会四舍五入，并最终以与您指定的不同方式存储。
  例如
  ```
  SELECT CAST('2016-12-26 23:59:59.999' as datetime)
  ```
  返回值：2016-12-27 00:00:00.000
  
- Babelfish：PostgreSQL 支持小数秒的 6 位精度，超过6位不支持,PostgreSQL 不执行 SQL Server 3 毫秒舍入。
 
#### 字符串类型
关于 TEXT 和 VARCHAR(MAX) 的注意事项：
- Microsoft SQL Server已弃用TEXT数据类型（[参考文档](https://learn.microsoft.com/en-us/sql/t-sql/data-types/ntext-text-and-image-transact-sql?view=sql-server-ver17)），建议改用 VARCHAR(MAX)。
- 在原生MSSQL中，VARCHAR(MAX) 在某些操作（如排序、索引）下可能受 8060 字节行限制影响，导致错误（如 Error 512）。
- Babelfish 运行于 PostgreSQL 环境，PostgreSQL 的 VARCHAR 默认无硬性长度限制（除非显式指定 VARCHAR(n)），因此：
  - TEXT 类型在 Babelfish 中仍可使用，且不会因超长文本报错（与 MSSQL行为不同）。
  
  - VARCHAR(MAX) 在 Babelfish 中不会强制限制为8000字节，允许存储更大的文本（符合 PostgreSQL 特性）。
   
- 如需严格兼容MSSQL行为，请避免使用TEXT并注意VARCHAR(MAX) 的行限制场景。
 
