有奖捉虫:办公协同&微信生态&物联网文档专题 HOT

MSSQL 兼容版与 T-SQL 使用差异

云数据库 PostgreSQL 已经支持了大部分 T-SQL 语法。您可以在下表中当前支持的 T-SQL 功能表,其中包含一些关于行为与 SQL Server 行为差异的注释。
功能或语法
行为或差异描述
\\(行延续字符)
当前不支持字符串和十六进制字符串的行延续字符(换行符前的反斜杠)。对于字符串,反斜杠换行符被解释为字符串中的字符。对于十六进制字符串,反斜杠换行符会导致语法错误。
@@version
@@version 返回的值的格式与 SQL Server 返回的值略有不同。如果您的代码取决于 @@version 的格式化,可能无法正常工作。
聚合函数
部分支持聚合函数(支持 AVG、COUNT、COUNT_BIG、GROUPING、MAX、MIN、STRING_AGG 和 SUM)。
ALTER TABLE
仅支持添加或删除单个列或约束。
BACKUP 语句
备份方式不同,在云数据库 PostgreSQL 的 SQL Server 兼容版中只能通过云控制台进行备份操作。
没有列别名的空白列名
sqlcmd 和 psql 实用程序以不同方式处理空名的列:SQL Server sqlcmd 返回空白列名。PostgreSQL psql 返回生成的列名称。
排序规则,根据 ICU 库对类型进行索引
当库的版本更改时,依赖于 International Components for Unicode(ICU)排序规则库(MSSQL 兼容版使用的库)的用户定义类型的索引不会失效。
COLLATIONPROPERTY 函数
排序规则属性仅适用于受支持的 MSSQL 兼容版 BBF 排序规则。
列原定设置
创建列原定设置时,约束名称将被忽略。要删除列原定设置,请使用以下语法:ALTER TABLE...ALTER COLUMN..DROP DEFAULT...
约束
PostgreSQL 不支持打开和关闭单个约束条件。将忽略语句,并发出警告。
使用 DESC(降序)列创建的约束
约束是使用 ASC(升序)列创建的。
具有 IGNORE_DUP_KEY 的约束
不支持此属性创建约束。
CREATE、ALTER、DROP SERVER ROLE
ALTER SERVER ROLE 仅支持 sysadmin。不支持其他语法。对于登录(服务器主体)、数据库和数据库用户(数据库主体)的概念,MSSQL 兼容版中的 T-SQL 用户的体验类似于 SQL Server。
MSSQL 兼容版用户数据库中只有 dbo 用户。要以 dbo 用户身份进行操作,登录名必须是服务器级别 sysadmin 角色(ALTER SERVER ROLE sysadmin ADD MEMBER login)的成员。
没有 sysadmin 角色的登录名目前只能以 guest 用户身份访问 master 和 tempdb。目前,因为 MSSQL 兼容版只支持用户数据库中的 dbo 用户,所有应用程序用户都必须使用属于 sysadmin 成员的一个登录名。您不能创建具有较低权限的用户,例如对某些表的只读权限。
CREATE、ALTER LOGIN 子句支持有限的语法
支持 CREATE LOGIN... PASSWORD 子句、...DEFAULT_DATABASE 子句和 ...DEFAULT_LANGUAGE 子句。支持 ALTER LOGIN... PASSWORD 子句,但 ALTER LOGIN... OLD_PASSWORD 子句不受支持。只有系统管理员成员的登录名才能修改密码。
CREATE DATABASE 区分大小写的排序规则
CREATE DATABASE 语句不支持区分大小写的排序规则。
CREATE DATABASE 关键字和子句
不支持 COLLATE 和 CONTAINMENT=NONE 以外的选项。COLLATE 子句只能接受 babelfishpg_tsql.server_collation_name 所设置的值。
CREATE SCHEMA... 支持子句
您可以使用 CREATE SCHEMA 命令创建空 schema。使用其他命令创建 schema 对象。
CREATE、ALTER LOGIN 子句支持有限的语法
支持 CREATE LOGIN... PASSWORD 子句、...DEFAULT_DATABASE 子句和 ...DEFAULT_LANGUAGE 子句。支持 ALTER LOGIN... PASSWORD 子句,但 ALTER LOGIN... OLD_PASSWORD 子句不受支持。只有系统管理员成员的登录名才能修改密码。
LOGIN 对象
支持 LOGIN 对象的所有选项,但以下各项除外:PASSWORD、DEFAULT_DATABASE、ENABLE、DISABLE。
数据库 ID 值
主数据库和 tempdb 数据库将不是数据库 ID 1和2。
超过63个字符的标识符
PostgreSQL 最多为标识符支持63个字符。MSSQL 兼容版将长度超过63个字符的标识符转换为包含原名哈希的名称。
IDENTITY 列支持
IDENTITY 列支持数据类型 tinyint、smallint、int、bigint、numeric 和 decimal。SQL Server 为 IDENTITY 列中的数据类型 numeric 和 decimal 支持的精度达到38位。PostgreSQL 为 IDENTITY 列中的数据类型 numeric 和 decimal 支持的精度达到19位。
使用 IGNORE_DUP_KEY 的索引
创建包含 IGNORE_DUP_KEY 的索引的语法会创建一个索引,就像省略此属性一样。
包含32列以上的索引
索引不能包含超过32列。包含的索引列在 PostgreSQL 中计入最大值,但在 SQL Server 中不计。
索引(聚集)
聚集索引的创建就像指定了 NONCLUSTERED 一样。
索引子句
忽略以下子句:FILLFACTOR、ALLOW_PAGE_LOCKS、ALLOW_ROW_LOCKS、PAD_INDEX、STATISTICS_NORECOMPUTE、OPTIMIZE_FOR_SEQUENTIAL_KEY、SORT_IN_TEMPDB、DROP_EXISTING、ONLINE、COMPRESSION_DELAY、MAXDOP 和 DATA_COMPRESSION。
NEWSEQUENTIALID 函数
作为 NEWID 实施;不保证顺序行为。调用 NEWSEQUENTIALID 时,PostgreSQL 会生成一个新的 GUID 值。
OUTER APPLY
不支持 SQL Server 横向连接。PostgreSQL 提供了允许横向连接的 SQL 语法,但行为并不相同。
支持 OUTPUT 子句,但存在以下限制
同一个 DML 查询中不支持 OUTPUT 和 OUTPUT INTO。不支持在 OUTPUT 子句中对 UPDATE 或 DELETE 操作的非目标表进行引用。OUTPUT... DELETED *INSERTED * 在同一个查询中不受支持。
过程或函数参数限制
MSSQL 兼容版最多支持100个过程或函数的参数。
RESTORE 语句
数据库的 PostgreSQL 快照与 SQL Server 中创建的备份文件不同。此外,SQL Server 与 PostgreSQL 之间进行备份和还原的粒度也可能不同。
ROLLBACK:表变量不支持事务回滚
如果在包含表变量的会话中发生回滚,则处理可能会中断。
ROWGUIDCOL
此子句当前被忽略。引用 $GUIDGOL 的查询导致语法错误。
SEQUENCE 对象支持
数据类型 tinyint、smallint、int、bigint、numeric 和 decimal 支持 SEQUENCE 对象。对于 SEQUENCE 中的数据类型 numeric 和 decimal,PostgreSQL 支持的精度达到19位。
服务器级角色
支持 sysadmin 服务器级角色。不支持 sysadmin 以外的其他服务器级角色。
除 db_owner 以外的数据库级别角色
支持 db_owner 数据库级角色。不支持 db_owner 以外的其他服务器级角色。
SQL 关键字 SPARSE
接受并忽略关键字 SPARSE。
SQL 关键字子句 ON filegroup
此子句当前被忽略。
索引和约束的 SQL 关键字 CLUSTERED 和 NONCLUSTERED
MSSQL 兼容版接受并忽略 CLUSTERED 和 NONCLUSTERED 关键字。
sysdatabases.cmptlevel
sysdatabases.cmptlevel 始终为 NULL。
tempdb 在重启时没有重新初始化
重新启动数据库时,不会删除在 tempdb 中创建的永久对象(如表和过程)。
TEXTIMAGE_ON 文件组
MSSQL 兼容版忽略 TEXTIMAGE_ON filegroup 子句。
时间精度
MSSQL 兼容版对小数秒支持6位数的精度。预计这种行为不会产生负面影响。
事务隔离级别
以与 READCOMMITTED 相同的方式对待 READUNCOMMITTED。不支持 REPEATABLEREAD 和 SERIALIZABLE。
虚拟计算列(非持久性)
虚拟计算列是作为永久列创建的。
WITHOUT SCHEMABINDING 子句
函数、过程、触发器或视图不支持此子句。

有限支持的功能

MSSQL 兼容版的每个新版本都会增加对更多功能的支持,这些功能更好地与 T-SQL 功能和行为保持一致。尽管如此,当前实施中存在一些不受支持的功能和差异。下文为您介绍 MSSQL 兼容版和 T-SQL 之间功能差异的相关信息,以及一些解决方法或使用说明。
从 MSSQL 兼容版本1.2.0开始,以下功能当前具有有限实施:
SQL Server 目录(系统视图) 目录 sys.sysconfigures、sys.syscurconfigs 和 sys.configurations 仅支持单个只读配置。当前不支持 sp_configure。有关 MSSQL 兼容版实现的其他一些 SQL Server 视图,更多信息,请参阅查询数据库以获取对象信息。
授予权限 支持 GRANT... TO PUBLIC,但是当前不支持 GRANT..TO PUBLIC WITH GRANT OPTION。
SQL Server 所有权链和权限机制限制 在 MSSQL 兼容版中,SQL Server 所有权链适用于视图,但不适用于存储过程。这意味着必须授予过程与调用过程相同的所有者拥有的其他对象的显式访问权限。在 SQL Server 中,授予调用者对该过程的 EXECUTE 权限就足以调用同一所有者拥有的其他对象。在 MSSQL 兼容版中,还必须向调用者授予对该过程访问的对象的权限。
解析非限定(without schema name)对象的引用 当 SQL 对象(过程、视图、函数或触发器)引用一个对象而没有使用 schema 名称对其进行限定时,SQL Server 会使用引用发生的 SQL 对象的架构名称来解析对象的架构名称。目前,MSSQL 兼容版通过使用执行该过程的数据库用户的默认模式,以不同方式来解析该名称。
默认模式更改、会话和连接 如果用户使用 ALTER USER...WITH DEFAULT SCHEMA 更改默认模式,更改将立即在该会话中生效。但是,对于属于同一用户的其他当前连接的会话,时间有所不同,如下所示:
对于 SQL Server:此更改将立即在所有其他连接中对此用户生效。
对于 MSSQL 兼容版:此更改将仅在新连接中对此用户生效。
非确定性排序规则和 CHARINDEX 当适用的排序规则是非确定性时,目前无法使用 CHARINDEX。因为 MSSQL 兼容版默认使用不区分大小写的排序规则,它是非确定性的,您可能会收到一个运行时错误,指出“子字符串搜索不支持非确定性排序规则”。在此错误得到解决之前,可以通过以下任一方法解决此问题:
将表达式显式转换为区分大小写的排序规则,然后通过应用 LOWER 或 UPER 将两个参数转换为大写。例如,SELECT charindex('x', a) FROM t1 将变为以下内容:
SELECT charindex(LOWER('x'), LOWER(a COLLATE sql_latin1_general_cp1_cs_as)) FROM t1
创建一个 SQL 函数 f_charindex,然后将 CHARINDEX 调用替换为对以下函数的调用:
CREATE function f_charindex(@s1 varchar(max), @s2 varchar(max)) returns int
AS
BEGIN
declare @i int = 1
WHILE len(@s2) >= len(@s1)
BEGIN
if LOWER(@s1) = LOWER(substring(@s2,1,len(@s1))) return @i
set @i += 1
set @s2 = substring(@s2,2,999999999)
END
return 0
END
go
ROWVERSION 和 TIMESTAMP 数据类型的实现和 escape hatch 设置 MSSQL 兼容版现在支持 ROWVERSION 和 TIMESTAMP 数据类型。要在 MSSQL 兼容版中使用 ROWVERSION 或 TIMESTAMP,必须将转义孵化的设置 babelfishpg_tsql.escape_hatch_rowversion 从默认值 strict 更改为 ignore。ROWVERSION 和 TIMESTAMP 数据类型的 MSSQL 兼容版实现在语义上基本上与 SQL Server 相同,但存在以下例外:
在 SQL Server 中,每个插入或更新的行都会获得一个唯一的 ROWVERSION/TIMESTAMP 值。在 MSSQL 兼容版中,由同一语句更新的每个插入的行都会被分配相同的 ROWVERSION/TIMESTAMP 值。 例如,当 UPDATE 语句或 INSERT-SELECT 语句影响多行时,在 SQL Server 中,受影响的行在其 ROWVERSION/TIMESTAMP 列中都有不同的值。在 MSSQL兼容版中,行具有相同的值。
在 SQL Server 中,当您使用 SELECT-INTO 创建新表时,可以将显式值(例如 NULL)转换为待创建的 ROWVERSION/TIMESTAMP 列。当您在 MSSQL 兼容版中做同样的事情时,MSSQL 兼容版会为新表中的每一行分配一个实际的 ROWVERSION/TIMESTAMP 值。
注意
ROWVERSION/TIMESTAMP 数据类型的这些细微差异应避免在 MSSQL 兼容版上运行的应用程序产生负面影响。
模式创建、所有权和权限 SQL Server 和 MSSQL 兼容版非 DBO 用户在数据库所有者(使用 CREATE SCHEMA…AUTHORIZATION DBO)创建的架构中创建对象的权限不同,如下表所示:
数据库用户(非 DBO)可以执行以下操作
SQL Server
Babelfish
在没有 DBO 额外授权的情况下在模式中创建对象?
由 DBO 在架构中创建的引用对象,无需额外授权?