主流数据库系统支持的SQL语句的差异主要有以下几点:数据类型的差异;运算符的差异;函数的差异;常用SQL的差异;取元数据信息的差异。
1.1.1数据类型的差异
整数类型:在MYSQL中整数相关的类型有tinyint、smallint、mediumint、int、integer和bigint;在MSSQLServer中整数相关的类型有bit、int、smallint、tinyint和bigint;在Oracle中整数相关的类型有number;在DB2中整数相关的类型有smallint、integer和bigint。
数值类型:在MYSQL中数值相关的类型有float、double、real、decimal和numeric;在MSSQLServer中数值相关的类型有decimal、numeric、money、smallmoney、float和real;在Oracle中数值相关的类型有number;在DB2中数值相关的类型有decimal、numeric、real和double。
字符类型:在MYSQL中字符相关的类型有char、varchar、tinytext、text、mediumtext、longtext、enum和set;在MSSQLServer中字符相关的类型有char、varchar、text、nchar、nvarchar和ntext;在Oracle中字符相关的类型有char、varchar2、nvarchar2、clob和nclob;在DB2中字符相关的类型有CHARACTER、VARCHAR、LONG VARCHAR、CLOB、GRAPHIC、VARGRAPHIC和LONGVARGRAPHIC。
日期时间类型:在MYSQL中日期时间相关的类型有date、time、datetime、timestamp和year;在MSSQLServer中日期时间相关的类型有datetime、smalldatetime和timestamp;在Oracle中日期时间相关的类型有date 和timestamp;在DB2中日期时间相
关的类型有DATE、TIME和TIMESTAMP。
二进制类型:MYSQL、Oracle和DB2都支持Blob类型,而在MSSQLServer中支持image类型。
1.1.2运算符的差异
在不同的数据库系统中字符串拼接的方式是不同的,下面的主流数据库系统对字符串拼接的支持:
MYSQL:在MYSQL中进行字符串的拼接要使用CONCAT函数,CONCAT函数支持一个或者多个参数,比如CONCAT('Hello',1,'World');MYSQL中还提供了另外一个进行字符串拼接的函数CONCAT_WS,CONCAT_WS可以在待拼接的字符串之间加入指定的分
隔符,比如CONCAT_WS ('Hello',1,'World')。
MSSQLServer:MSSQLServer中可以直接使用加号“+”来拼接字符串,比如'Hello'+'World'。
Oracle:Oracle中使用“||”进行字符串拼接,比如'Hello'||'World';除了“||”,Oracle还支持使用CONCAT()函数进行字符串拼接,不过与MYSQL的CONCAT()函数不同,Oracle的CONCAT()函数只支持两个参数,不支持两个以上字符串的拼接。
DB2:DB2中使用“||”进行字符串拼接,比如'Hello'||'World'。
1.1.3函数的差异
不同数据库系统对函数的差异是非常大的,不仅同样功能的函数在不同数据库系统中的名称不同,而且一些高级的函数也并不是在所有数据库系统中都有提供支持。比如将一个字符串转换为小写的函数在MYSQL,MSSQLServer和Oracle中为LOWER,而在DB2中则为LCASE;MYSQL中支持IF函数,而在其他数据库系统中则只有通过变通方式才能实现。
1.1.4常用SQL的差异
主流数据库系统对SELECT、UPDATE、DELETE、CREATE、DROP等基本语法的支持是相同,不过在一些高级特性支持方面仍然有差异。
1.1.4.1限制结果集行数
在实现分页检索、排行榜等功能的时候,需要限制检索的结果集行数,不同的数据库系统对此的支持是不同的。
MYSQL中提供了LIMIT关键字用来限制返回的结果集,比如:
SELECT * FROM T_Employee
ORDERBY FSalary DESC LIMIT 2,5
MSSQLServer:MSSQLServer中提供了TOP关键字用来返回结果集中的前N条记录,比如:
select top 5 *from T_Employee
order by FSalaryDesc;
在MSSQLServer2005中还可以使用窗口函数ROW_NUMBER()实现限制结果集行数,比如:
SELECTROW_NUMBER() OVER(ORDER BY FSalary), FNumber,
FName,FSalary,FAge
FROM T_Employee
Oracle:Oracle中支持窗口函数ROW_NUMBER(),其用法和MSSQLServer2005中相同;除了窗口函数ROW_NUMBER(),Oracle中还提供了更方便的rownum机制,Oracle为每个结果集都增加了一个默认的表示行号的列,这个列的名称为rownum。使用rownum可以很轻松的取得结果集中前N条的数据行,比如:
SELECT * FROMT_Employee
WHERErownum<=6
ORDER BY FSalaryDesc
DB2:DB2中支持窗口函数ROW_NUMBER(),其用法和MSSQLServer2005以及Oracle中相同。除此之外,DB2还提供了FETCH关键字用来提取结果集的前N行,比如:
SELECT * FROMT_Employee
ORDER BY FSalaryDesc
FETCH FIRST 6ROWS ONLY
1.1.4.2 删除索引
索引的定义在各个数据库系统中基本相同,但是删除索引的语法则各有不同,比如删除T_Person表中定义的名称为idx1的索引在不同数据库系统下的SQL语句如下:
MYSQL:
DROP INDEX idx1ON T_Person
MSSQLServer:
DROP INDEXT_Person.idx1
Oracle,DB2:
DROP INDEX idx1
1.1.5取元数据信息的差异
在开发一些功能的时候有时需要查询数据的一些信息,比如数据库的名称、当前用户名、数据库中有哪些表、指定表的字段定义等,这些信息被称为元数据。对元数据的支持在不同的数据库系统下的差异性是非常大的。
1.1.5.1 取数据库信息
MYSQL中可以通过函数来取得数据库的信息,包括当前数据库名、版本、当前登录用户等信息:DATABASE()函数返回当前数据库名;VERSION()函数以一个字符串形式返回MySQL服务器的版本;USER()函数(这个函数还有SYSTEM_USER、SESSION_USER两个别名)返回当前MySQL用户名。
MSSQLServer中也可以通过函数来取得数据库的信息:APP_NAME()函数返回当前会话的应用程序名称;CURRENT_USER函数(注意这个函数不能带括号调用)返回当前登陆用户名;HOST_NAME()函数返回工作站名。
不过,在MSSQLServer中如果要查询当前数据库名,则必须到系统表sysprocesses中查询,SQL语句如下:
select
dbname =
case when dbid =0 then null
when dbid<> 0 then db_name(dbid)
end
frommaster..sysprocesses
wherespid=@@SPID
系统表“master..sysprocesses”中存储了当前数据库系统中的进程信息,而“@@SPID”则表示当前进程号。
Oracle中使用USER函数用来取得当前登录用户名,注意使用这个函数的时候不能使用括号形式的空参数列表,也就是USER()这种使用方式是不对的。正确使用方式如下:
SELECT USER FROM DUAL
Oracle中使用USERENV()函数用来取得当前登录用户相关的环境信息,USERENV()函数有一个参数,参数的可选值如下:ISDBA、LANGUAGE、TERMINAL、SESSIONID、ENTRYID、LANG和INSTANCE。
DB2中可以通过CURRENT_USER来取得当前登陆用户名,而CURRENT_SERVER用来取得当前服务名,比如:
SELECTCURRENT_USER,CURRENT_SERVER
FROM sysibm.sysdummy1
DB2中取得当前数据库的版本的SQL语句如下:
SELECT * FROM sysibm.sysversions
1.1.5.2 取得所有表
MYSQL中取得当前数据库中所有表定义的SQL语句如下:
SHOW TABLES
MSSQLServer中的系统表sysobjects中记录了当前系统中定义的对象,其中xtype字段等于U的记录为表定义,因此取得当前数据库中所有表定义的SQL语句如下:
SELECT name FROMsysobjects where xtype='U'
Oracle中的系统表all_objects中记录了当前系统中定义的对象,其中Object_Type字段等于TABLE的记录为表定义,因此取得当前数据库中所有表定义的SQL语句如下:
selectObject_Name from all_objects where Object_Type='TABLE'
DB2中的系统表all_syscat.tables中记录了当前系统中定义的表和视图,其中TYPE字段等于T的记录为表定义,因此取得当前数据库中所有表定义的SQL语句如下:
SELECT TABNAMEFROM syscat.tables where TYPE='T'
1.1.5.3 取得指定Schema下的表
MYSQL中取得指定Schema下所有表定义的SQL语句如下(假设Schema名为demoschema):
SHOW TABLES FROMdemoschema
MSSQLServer中的系统表sysobjects中记录了当前系统中定义的对象,其中xtype字段等于U的记录为表定义,因此取得当前数据库中所有表定义的SQL语句如下(假设Schema名为demoschema):
SELECT name FROMdemoschema.sysobjects where xtype='U'
Oracle中的系统表all_objects中记录了当前系统中定义的对象,其中Object_Type字段等于TABLE的记录为表定义,OWNER字段为Schema,因此取得当前数据库中所有表定义的SQL语句如下(假设Schema名为demoschema):
selectObject_Name from all_objects
whereObject_Type='TABLE' and OWNER='demoschema'
DB2中的系统表all_syscat.tables中记录了当前系统中定义的表和视图,其中TYPE字段等于T的记录为表定义,TABSCHEMA字段为Schema,因此取得当前数据库中所有表定义的SQL语句如下(假设Schema名为demoschema):
SELECT TABNAMEFROM syscat.tables
where TYPE='T' and TABSCHEMA='demoschema'
1.1.5.4 取得指定表的字段定义
MYSQL中取得指定表的字段定义(假设表名为mytable):
DESCRIBE mytable
MYSQLServer中取得指定表的字段定义(假设表名为mytable):
SELECTsyscols.name as COLUMN_NAME,
st.name asDATA_TYPE,
syscomm.text asDATA_DEFAULT,
syscols.isnullableas NULLABLE
FROM syscolumnssyscols
left joinsystypes st on syscols.xusertype=st.xusertype
left joinsyscomments syscomm on syscols.cdefault=syscomm.id
where syscols.id=OBJECT_ID(N'mytable')
order bysyscols.id,syscols.colorder
Oracle中的all_tab_columns表是系统中所有表的字段定义,其中TABLE_NAME字段为表名,因此取得指定表的字段定义(假设表名为mytable):
selectCOLUMN_NAME,DATA_TYPE,DATA_DEFAULT,NULLABLE
fromall_tab_columns where TABLE_NAME ='MYTABLE'
DB2中的syscat.columns表是系统中所有表的字段定义,其中TABNAME字段为表名,因此取得指定表的字段定义(假设表名为mytable):
select COLNAMEas COLUMN_NAME, TYPENAME as DATA_TYPE,DEFAULT as
DATA_DEFAULT,NULLSas NULLABLE
fromsyscat.columns where TABNAME='MYTABLE'