现在市场上存在很多厂商推出的数据库管理系统,商业化的有Oracle、SQLServer、DB2,开源的有MYSQL、SQLite等,这些数据库产品的出现给了开发者更多的选择余地。众所周知,各个数据库管理系统支持的SQL语法是存在一定差异的,在Oracle下能够成功运行的SQL迁移到DB2下可能就无法运行,因此如何使得系统能够在多种数据库管理系统下运行就成了一个非常棘手的问题,耿股首先对主流数据库管理系统的SQL语法差异进行分析,明天的文章中给出相应的解决方案。
SQL语法差异分析
主流数据库系统支持的SQL语句的差异主要有以下几点:数据类型的差异;运算符的差异;函数的差异;常用SQL的差异;取元数据信息的差异。
1数据类型的差异
整数类型:在MYSQL中整数相关的类型有TINYINT、SMALLINT、MEDIUMINT、INT、INTEGER和 BIGINT;在SQLServer中整数相关的类型有BIT、INT、SMALLINT、TINYINT和BIGINT;在Oracle中整数相关的类型有NUMBER;在DB2中整数相关的类型有 SMALLINT、INTEGER和 BIGINT。
数值类型:在MYSQL中数值相关的类型有FLOAT、DOUBLE、REAL、DECIMAL和NUMERIC;在SQLServer中数值相关的类型有DECIMAL、NUMERIC、MONEY、SAMLLMONEY、FLOAT和REAL;在Oracle中数值相关的类型有NUMBER;在DB2中数值相关的类型有DECIMAL、NUMERIC、REAL和DOUBLE。
字符类型:在MYSQL中字符相关的类型有CHAR、VARCHAR、TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT、ENUM和SET;SQLServer中字符相关的类型有CHAR、VARCHAR、TEXT、NCHAR、NVARCHAR和NTEXT;在Oracle中字符相关的类型有CHAR、VARCHAR2、NVARCHAR2、CLOB和NCLOB;在DB2中字符相关的类型有CHARACTER、VARCHAR、LONG VARCHAR、CLOB、GRAPHIC、VARGRAPHIC和LONG VARGRAPHIC。
日期时间类型:在MYSQL中日期时间相关的类型有DATE、TIME、DATETIME、TIMESTAMP和YEAR;在SQLServer中日期时间相关的类型有DATETIME、SAMLLDATETIME和TIMESTAMP;在Oracle中日期时间相关的类型有DATE和TIMESTAMP;在DB2中日期时间相关的类型有DATE、TIME和TIMESTAMP。
二进制类型:MYSQL、Oracle和DB2都支持BLOB类型,而在SQLServer中支持IMAGE类型。
2运算符的差异
在不同的数据库系统中字符串拼接的方式是不同的,下面的主流数据库系统对字符串拼接的支持:
MYSQL:在MYSQL中进行字符串的拼接要使用CONCAT函数,CONCAT函数支持一个或者多个参数,比如CONCAT('Hello',1,'World');MYSQL中还提供了另外一个进行字符串拼接的函数CONCAT_WS,CONCAT_WS可以在待拼接的字符串之间加入指定的分隔符,比如CONCAT_WS ('Hello',1,'World')。
SQLServer:SQLServer中可以直接使用加号“+”来拼接字符串,比如'Hello'+'World'。Oracle:Oracle中使用“||”进行字符串拼接,比如'Hello'||'World';除了“||”,Oracle还支持使用CONCAT()函数进行字符串拼接,不过与MYSQL的CONCAT()函数不同,Oracle的CONCAT()函数只支持两个参数,不支持两个以上字符串的拼接。
DB2:DB2中使用“||”进行字符串拼接,比如'Hello'||'World'。
3函数的差异
不同数据库系统对函数的差异是非常大的,不仅同样功能的函数在不同数据库系统中的名称不同,而且一些高级的函数也并不是在所有数据库系统中都有提供支持。比如将一个字符串转换为小写的函数在MYSQL、SQLServer以及Oracle中为LOWER,而在DB2中则为LCASE;MYSQL中 支持IF函数,而在其他数据库系统中则只有通过变通方式才能实现。
4常用SQL的差异
主流数据库系统对SELECT、UPDATE、DELETE、CREATE、DROP等基本语法的支持是相同,不过在一些高级特性支持方面仍然有差异。
4.1限制结果集行数
在实现分页检索、排行榜等功能的时候,需要限制检索的结果集行数,不同的数据库系统对此的支持是不同的。
MYSQL中提供了LIMIT关键字用来限制返回的结果集,比如:
SQLServer:SQLServer中提供了TOP关键字用来返回结果集中的前N条记录,比如:
在SQLServer中还可以使用窗口函数ROW_NUMBER()实现限制结果集行数,比如:
Oracle:Oracle中支持窗口函数ROW_NUMBER(),其用法和SQLServer中相同;除了窗口函数ROW_NUMBER(),Oracle中还提供了更方便的rownum机制,Oracle为每个结果集都增加了一个默认的表示行号的列,这个列的名称为rownum。使用rownum可以很轻松的取得结果集中前N条的数据行,比如:
DB2:DB2中支持窗口函数ROW_NUMBER(),其用法和SQLServer2005以及Oracle中相同。除此之外,DB2还提供了FETCH关键字用来提取结果集的前N行,比如:
4.2删除索引
索引的定义在各个数据库系统中基本相同,但是删除索引的语法则各有不同,比如删除T_Person表中定义的名称为idx1的索引在不同数据库系统下的SQL语句如下:
MYSQL:
SQLServer:
Oracle,DB2:
5取元数据信息的差异
在开发一些功能的时候有时需要查询数据的一些信息,比如数据库的名称、当前用户名、数据库中有哪些表、指定表的字段定义等,这些信息被称为元数据。对元数据的支持在不同的数据库系统下的差异性是非常大的。
5.1 获取数据库信息
MYSQL中可以通过函数来取得数据库的信息,包括当前数据库名、版本、当前登录用户等信息:DATABASE()函数 返回当前数据库名;VERSION()函数 以一个字符串形式返回MySQL服务器的版本;USER()函数(这个函数还有SYSTEM_USER、SESSION_USER两个别名) 返回当前MySQL用户名。
SQLServer中也可以通过函数来取得数据库的信息:APP_NAME()函数 返回当前会话的应用程序名称;CURRENT_USER函数(注意这个函数不能带括号调用) 返回当前登陆用户名;HOST_NAME()函数 返回工作站名。
不过,在SQLServer中如果要查询当前数据库名,则必须到系统表sysprocesses中查询,SQL语句如下:
系统表“master..sysprocesses”中存储了当前数据库系统中的进程信息,而“@@SPID”则表示当前进程号。
Oracle中使用USER函数用来取得当前登录用户名,注意使用这个函数的时候不能使用括号形式的空参数列表,也就是USER()这种使用方式是不对的。正确使用方式如下:
Oracle中使用USERENV()函数用来取得当前登录用户相关的环境信息,USERENV()函数有一个参数,参数的可选值如下:ISDBA、LANGUAGE、TERMINAL、SESSIONID、ENTRYID、LANG和INSTANCE。
DB2中可以通过CURRENT_USER来取得当前登陆用户名, 而CURRENT_SERVER用来取得当前服务名,比如:
DB2中取得当前数据库的版本的SQL语句如下:
5.2取得所有表
MYSQL中取得当前数据库中所有表定义的SQL语句如下:
SQLServer中的系统表sysobjects中记录了当前系统中定义的对象,其中xtype字段等于U的记录为表定义,因此取得当前数据库中所有表定义的SQL语句如下:
Oracle中的系统表all_objects中记录了当前系统中定义的对象,其中Object_Type字段等于TABLE的记录为表定义,因此取得当前数据库中所有表定义的SQL语句如下:
DB2中的系统表all_ syscat.tables中记录了当前系统中定义的表和视图,其中TYPE字段等于T的记录为表定义,因此取得当前数据库中所有表定义的SQL语句如下:
5.3取得指定Schema下的表
MYSQL中取得指定Schema下所有表定义的SQL语句如下(假设Schema名为demoschema):
SQLServer中的系统表sysobjects中记录了当前系统中定义的对象,其中xtype字段等于U的记录为表定义,因此取得当前数据库中所有表定义的SQL语句如下(假设Schema名为demoschema):
Oracle中的系统表all_objects中记录了当前系统中定义的对象,其中Object_Type字段等于TABLE的记录为表定义,OWNER字段为Schema,因此取得当前数据库中所有表定义的SQL语句如下(假设Schema名为demoschema):
DB2中的系统表all_ syscat.tables中记录了当前系统中定义的表和视图,其中TYPE字段等于T的记录为表定义,TABSCHEMA字段为Schema,因此取得当前数据库中所有表定义的SQL语句如下(假设Schema名为demoschema):
5.4取得指定表的字段定义
MYSQL中取得指定表的字段定义(假设表名为mytable):
SQLServer中取得指定表的字段定义(假设表名为mytable):
Oracle中的all_tab_columns表是系统中所有表的字段定义,其中TABLE_NAME字段为表名,因此取得指定表的字段定义(假设表名为mytable):
DB2中的syscat.columns表是系统中所有表的字段定义,其中TABNAME字段为表名,因此取得指定表的字段定义(假设表名为mytable):
领取专属 10元无门槛券
私享最新 技术干货