KingbaseES(SQLServer兼容版)V9R4C12版本说明
KingbaseES(SQLServer兼容版)V9R4C12版本加入了更多针对各行业应用场景的定制化功能,助力企业实现平滑迁移和业务高效运行。该版本新增了对SQLServer若干系统视图和内置函数的支持,支持ICU库并对其进行了优化;支持更多的高级查询功能,包括FOR XML子句、PIVOT行列转换操作、GROUP BY子句中基于不同数据类型进行分组、DINSTICT子句与ORDER BY联合中列别名的使用等;新增DML操作触发更新统计信息功能,提升查询性能与增强系统的稳定性;新增临时表优化功能,提升了函数执行效率。在客户端编程接口方面,.Net驱动中新增了对SQL Server 中一些日期函数的支持,这些新功能可以支撑应用灵活处理各种日期运算场景。
该版本修复了对GBK编码支持、索引选项、SQL操作符、存储过程、.NET接口以及KStudio使用中的若干缺陷,为用户高效使用SQLServe兼容版的各项功能提供了有效的支撑与保障。
当前,金仓数据库KingbaseES已在医疗、海关、政务等领域打造了一系列替代SQL Server的典型案例,为千行百业的数字化转型升级提供持续服务。
本文主要是做KingbaseES(SQLServer兼容版)和 SQLServer数据库兼容性测试。
KingbaseES(SQLServer兼容版)单机部署
请参考前一篇文章:KingbaseES(SQLServer兼容版)单机部署
KingbaseES(SQLServer兼容版)和 SQLServer 数据库兼容性测试
SQL兼容
1、数据类型:ROWVERSION
该类型是自动生成的唯一二进制数字的数据类型。该类型存储大小为8个字节。接受NULL输入,固定以0x****************的8字节的16进制格式输出。timestamp类型为rowversion类型的同义词。
--创建测试表
CREATE TABLE students (
id int primary key,
name VARCHAR(50),
deptno int,
rv ROWVERSION
);
--插入数据
insert into students(id,name,deptno) values(1,'张三',10);
insert into students(id,name,deptno) values(2,'李四',20);
insert into students(id,name,deptno) values(3,'王五',30);
insert into students(id,name,deptno) values(4,'王艳',10);
insert into students(id,name,deptno) values(5,'颜小',20);
--查询数据
select * from students;
注意:在master或者自己创建的数据库中都可以使用rowversion类型,在test数据库中不能使用。报错如下:

在master和自己创建的sqlserver数据库中正常:


结论:执行结果一致,KingbaseES和SQLServer的ROWVERSION数据类型是完全兼容的。
2、数据类型:SQL_VARIANT
sql_variant数据类型用于存储支持的各种数据类型。支持的基础数据类型范围见下表:
| 数据类型 | 数据类型类别 |
|---|---|
| datetime2 | 日期和时间 |
| datetime | 日期和时间 |
| smalldatetime | 日期和时间 |
| date | 日期和时间 |
| time | 日期和时间 |
| float(float8) | 近似数值 |
| real(float4) | 近似数值 |
| decimal(numeric) | 精确数值 |
| money | 精确数值 |
| bigint(int8) | 精确数值 |
| int(int4) | 精确数值 |
| smallint(int2) | 精确数值 |
| tinyint | 精确数值 |
| bit | 精确数值 |
| nvarchar | Unicode |
| nchar | Unicode |
| varchar | Unicode |
| char(bpchar) | Unicode |
| varbinary | Binary |
| binary | Binary |
| uniqueidentifier | Uniqueidentifier |
使用说明:
- sql_variant数据类型支持作为表列,变量,函数参数和返回值使用。
- 上表中描述的基础数据类型,都可以隐式转换为sql_variant类型,但不支持sql_variant类型隐式转换为其它类型。
- sql_variant数据类型必须先转换为基本数据类型值,然后才能参与算数运算。
- sql_variant数据支持导入导出。导出时如果指定–copy-binary参数,能够导出属性,导入后数据的属性信息不变。如果不指定–copy-binary参数时,导出仅备份数据,不导出属性信息,导入时数据的基础类型全部是varchar类型。
--创建测试表
CREATE TABLE TEST_SQL_VARIANT (
id INT IDENTITY PRIMARY KEY,
var_col SQL_VARIANT
);
-- 插入不同类型的数据
INSERT INTO TEST_SQL_VARIANT(var_col) VALUES (N'字符串文本');
INSERT INTO TEST_SQL_VARIANT(var_col) VALUES (12345678);
INSERT INTO TEST_SQL_VARIANT(var_col) VALUES (3.14159);
INSERT INTO TEST_SQL_VARIANT(var_col) VALUES (CAST('2023-10-01' AS DATE));
INSERT INTO TEST_SQL_VARIANT(var_col) VALUES (1);
-- 查询数据
SELECT id, var_col, SQL_VARIANT_PROPERTY(var_col, 'BaseType') AS BaseType
FROM TEST_SQL_VARIANT;


结论:执行结果一致,KingbaseES和SQLServer的SQL_VARIANT数据类型是兼容的。
3、数据类型:UNIQUEIDENTIFIER
UNIQUEIDENTIFIER类型是一个16字节的 GUID 类型。
NEWID()函数生成随机GUID,或NEWSEQUENTIALID()生成顺序GUID(减少索引碎片)。
-- 创建测试表
CREATE TABLE TEST_GUID (
ID INT PRIMARY KEY,
GuidCol UNIQUEIDENTIFIER DEFAULT NEWID(), --NEWID()函数生成随机GUID
Description NVARCHAR(50)
);
-- 插入数据(显式指定GUID)
INSERT INTO TEST_GUID (ID, GuidCol, Description)
VALUES
(1, '6F9619FF-8B86-D011-B42D-00C04FC964FF', 'Explicit GUID'),
(2, DEFAULT, 'Auto-generated GUID');
-- 查询数据
SELECT * FROM TEST_GUID;


结论:执行结果一致,KingbaseES和SQLServer的UNIQUEIDENTIFIER是兼容的。
4、sql语句:top子句
--创建测试表
CREATE TABLE EMP
(
empno NUMERIC(4) NOT NULL,
ename VARCHAR(10),
job VARCHAR(9),
mgr NUMERIC(4),
hiredate DATE,
sal NUMERIC(7,2),
comm NUMERIC(7,2),
deptno NUMERIC(2)
);
--插入数据
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);
--查询数据
select top 3 * from emp;


结论:执行结果一致,KingbaseES和SQLServer的 top子句 是兼容的。
5、sql语句:index …rebuild 子句
--创建索引
create index idx_ename on emp(ename);
--重建索引
alter index idx_ename rebuild;
alter index idx_ename on emp rebuild;


结论:执行结果不一致,KingbaseES和SQLServer的 index …rebuild 子句是不兼容的。
T-SQL兼容测试
1、GO批处理语句
批处理语句GO是SQLServer的一个强大的工具。它可以帮助用户更好地组织和管理 SQL 脚本,提高脚本的可读性和可维护性,并增强错误处理和事务管理的能力以及执行效率。GO命令可以将 SQL 脚本中的语句分隔成多个逻辑上的批处理,允许用户将相关的语句组合在一起作为一个逻辑单元来执行。由于每个GO命令之前的语句被视为一个独立的批处理,这种错误隔离的特性使得调试和修复问题变得更加容易。另外GO命令所带来的事务管理能力有助于确保数据的完整性和一致性。而通过在GO命令后指定一个数字,可以重复执行前面的批处理语句指定的次数。这对于需要多次执行相同操作的场景非常有用。
SQLServer中,单个批处理语句集合会被编译为单一的执行计划被系统缓存,当再次执行时无需重新编译,从而极大地提升了SQL语句集的执行效率。
金仓数据库最新的SQLServer 兼容版,实现了对批处理命令GO语句的全面支持。无论是通过客户端工具(ksql、kstudio),还是从客户端编程接口,用户均可以在SQL层以及PLSQL层通过GO命令,对单条或多条SQL语句在数据库服务器端完成批量执行,从而继续享受GO命令带来的巨大便利与效率提升了。
create table testgo1(id int,sal numeric(7,2));
insert into testgo1 values(1,10000);
insert into testgo1 values(2,20000);
insert into testgo1 values(3,30000);
create table testgo2(id int,sal numeric(7,2));
insert into testgo2 values(4,10000);
insert into testgo2 values(5,20000);
insert into testgo2 values(6,30000);
\set SQLTERM /
select * from testgo1
go
select * from testgo2
/


结论:执行结果一致,KingbaseES和SQLServer的GO批处理语句是兼容的。
2、PRINT打印语句
create table emp2(id int,sal numeric(7,2));
insert into emp2 values(1,10000);
insert into emp2 values(2,20000);
insert into emp2 values(3,30000);
insert into emp2 values(4,40000);
insert into emp2 values(5,50000);
insert into emp2 values(6,60000);
PRINT '开始执行数据清理...';
DELETE FROM emp2 WHERE ID > 2;
PRINT '数据清理完成,影响行数:' + CAST(@@ROWCOUNT AS VARCHAR);


结论:执行结果一致,KingbaseES和SQLServer的PRINT打印语句是兼容的。
3、RAISERROR错误处理语句
\set SQLTERM /
BEGIN TRY
IF NOT EXISTS (SELECT 1 FROM Employee)
RAISERROR('表中无数据!', 16, 1); -- 严重级别16,状态1
END TRY
BEGIN CATCH
PRINT '错误信息:' + ERROR_MESSAGE();
END CATCH
/


结论:执行结果一致,KingbaseES和SQLServer的RAISERROR错误处理语句兼容。
4、THROW错误处理语句
\set SQLTERM /
BEGIN TRY
INSERT INTO tab VALUES (1); -- tab表不存在,故意引发错误
END TRY
BEGIN CATCH
--THROW; -- 重新抛出原始错误
THROW 51000, '自定义错误消息', 1; -- 自定义错误
END CATCH
/


KingbaseES中不管是否使用动态sql,都能抛出了自定义错误消息。
下面是sqlserver中的处理:

sqlserver中直接抛出原始错误:对象名 tab 无效。

sqlserver中使用动态sql后,抛出了自定义错误消息。
结论:执行结果稍有差异,KingbaseES和SQLServer的THROW错误处理语句兼容。
5、语句缺失分号
SQLServer支持SQL语句之间无分号分隔符。在 SQLServer Management Studio (SSMS) 中,默认情况下,用户可以在一个查询窗口中输入多个不带分号的 SQL 语句,并且可以一次执行这些语句。对于这种看似奇怪的“特性”,KingbaseES也在最新的SQLServer 兼容版本中实现了支持。
\set SQLTERM /
CREATE TABLE emp3 (
EmployeeID INT PRIMARY KEY,
Name NVARCHAR(100),
HireDate DATE,
)
select * from emp3
select * from emp2
/


结论:执行结果一致,KingbaseES和SQLServer的语句缺少分号功能是兼容的。
6、创建表最后一个字段可加逗号
CREATE TABLE Employee (
EmployeeID INT PRIMARY KEY,
Name NVARCHAR(100),
HireDate DATE,
);


结论:执行结果一致,KingbaseES和SQLServer在创建表的时候,最后一个字段都可加逗号功能是兼容的。
总结
经过上述测试可见,KingbaseES(SQLServer 兼容版)与 SQLServer 的兼容性相当高,后续有时间再继续验证其他功能。
金仓数据库产品体验官活动链接
https://bbs.kingbase.com.cn/forumDetail?articleId=5262510af41971c328bd0a78dd8aa56a
官方文档链接
https://bbs.kingbase.com.cn/documentGuide?recId=bf40609a9c064fe3593c2040d4d899c8
关于作者
网名:飞天,墨天轮2024年度优秀原创作者,拥有 Oracle 10g OCM 认证、PGCE认证、MySQL 8.0 OCP认证以及OBCA、KCP、KCSM、ACP、YCP、磐维等众多国产数据库认证证书,目前从事Oracle、Mysql、PostgresSQL、磐维数据库管理运维工作,喜欢结交更多志同道合的朋友,热衷于研究、分享数据库技术。
微信公众号:飞天online
墨天轮:https://www.modb.pro/u/15197
如有任何疑问,欢迎大家留言,共同探讨~~~




