开发者们应该知道,使用那些非标准的sql命令(比如oracle、微软和mysql等数据库系统)存在程度相当高的危险。也就是说,从跨平台和遵守标准的角度出发,你应该尽量采用ansi sql,它是一种和平台无关的数据库语言。不管你在使用哪种数据库系统,如果它完全支持sql那么它就应该支持ansi sql-92标准。可是,“应该支持”和“确实支持”完全是两码事。在进行dbms跨平台编程的时候,并不是所有的系统都完全支持ansi sql标准。这篇文章主旨就是提出使用非标准sql时所存在的风险及其相关的建议。
别使用存储过程
在某些编程环境下,出于效率和安全等方面的原因,存储过程成为程序员开发数据库应用程序的唯一方法。visual basic、c和java程序员都并不需要了解sql。然而,在其他某些编程环境下,存储过程又是完全禁用的。mysql通常和apache web服务器组合使用,这是因为这两种软件不仅免费、可靠而且功能强大,但是,恰恰是mysql不支持存储过程。
--------------------------------------------------------------------------------
存储过程的定义
所谓存储过程就是组成一个逻辑单元而且执行特别任务的一组sql语句。存储过程用来封装针对数据库服务器的一整套操作或查询。
--------------------------------------------------------------------------------
oracle和sql服务器两者都包括了“内建”的存储过程,其使用也是很方便的。可是,如果明智的话千万别指望它们,你无法保证数据库管理员是否锁定、删除或修改了这些存储过程。如果你发现可用的某些存储过程正是你需要的,你这才可以在自己的代码中使用它们的功能。
通常,你能在oracle或sql server上使用存储过程但在mysql上则无法利用。如果你确实用到了它们,那么你得保证自己没有用到同特定平台相关的命令(以后讨论)。
别使用连接
连接是oracle和sql server 这两种dbms上令人头痛的一个问题,因为这两种系统在连接的概念上有根本的不同。基本上,各个dbms的连接工作原理不总是一样的,而且你最终可能会得到意外的结果集合。在我们谈论各个系统有关连接的概念差别以及如何解决这些问题之前,你应该理解基本的连接子句:
连接
join(连接)是从多个数据源获取数据的sql数据表创建命令。
等连接
equi-join从两个独立的数据源获取数据并把它们组合成一个大表。
内/外连接
内连接(inner join)把两个表的内部列连接起来。外连接把两个表的外部列连接起来。
左/右连接
左连接(left join)连接两个表左边的列。右连接则连接两个表右边的列。
复合/复杂连接
其他各种连接—左/内、左/外、右/内和右/外等。
反正你得记清楚了,如果你想要自己的应用程序能在各种数据库服务器上都能工作那么就别使用连接。
ansi sql:create, drop, add, update, delete, insert, select
总之,你应当用到的唯一命令如下:
数据定义语言(ddl)下的create 和drop。
数据操作语言(dml)下的add、update、delete和insert 。
获取数据的select。
如果你在这些命令中使用了区分大小写的表格或字段名,或者这些名字包含了空格或其它特殊字符,那么你最好用方括号把名字围起来。这样做有助于防止非标准字符引发dbms的不正常反应。
引用的完整性:键和数据类型
使用关系数据库的决定性原因就是明确数据之间的关系而且维持那些关系的完整性。这样才能让开发者以最小的冗余性、最高效的方式存储数据。键定义了关系。数据类型定义了存储和操作数据的规则。这些就是一个数据库的基本方面,但是具体的语法却可能因为数据库的不同而不同。
数据类型
只有很少部分的数据类型得到所有数据库服务器的支持。每一种dbms都有它自己的数据类型以及为什么要这样使用它们的原因。某些专有数据类型(比如microsoft access的autonumber)用起来确实相当方便。
以下是ansi数据类型:
bit, character, date, decimal, double precision, float, integer, interval, numeric, real, smallint, timestamp, time, varbit, varchar, char
以下是oracle/access/sql不支持的“标准”数据类型:
interval, time, varbit
只有oracle才支持date,但是以下的“标准”数据类型不被oracle支持:
bit, decimal, numeric, timestamp
以下的“标准”数据类型不被access支持:
bit, character, date, numeric, smallint, timestamp
这样,只有以下的数据类型可以保证在各类数据库上都能使用:
double precision, float, integer, numeric, real, smallint, varchar, char
主/外键
假设某个表内有两个字段,创建这个表的语法如下:
create table [mytable] ([fielda] varchar, [fieldb] varchar);
为了添加主键以便表内的每一条记录都唯一标识你可以采用primary key 表达式:
create table [mytablea] ([recordid] varchar primary key, [fielda] varchar, [fieldb] varchar);
在创建另一个表,其中一个字段索引第1个表,你可以把该字段定义为同第1个表的字段具有关系的外键:
create table [mytableb] ([recordid] varchar primary key, [fielda] varchar, [fieldb] varchar, [fieldc] varchar references [mytablea]([fielda]))
在以上例子中,所有的字段都是varchar类型;但是你得记住,某一数据类型字段只能索引同一数据类型的字段。
odbc 和 jdbc
如果你在编写的应用程序要用到sql数据库连接,那么你可以用odbc完成该功能。如果它是一个java应用程序则可以用jdbc(简而言之就是odbc的java接口)。
因为你希望自己的应用程序最好不要引起管理员的注意,所以你应该为你用户的dbms包括所有必要的odbc驱动程序。这样,如果用户从一个平台转移到另一个平台,它们所需要的驱动程序却已经事先拥有了。
你的应用程序应该通过编程的方式决定当前用到的odbc驱动程序对应何种dbms。这样你才能用上那些数据库服务器上强大的、同特定平台相关的命令。
另类浏览器之战
最流行的浏览器当然是微软的internet explorer和netscape的navigator了。但是,不管你手头用的是哪一种,它能保证支持现有的所有网站吗?错!很多花哨的东西,比如dhtml、框架以及多媒体等等都各自受到两类浏览器中非标准的html标签的支持。
因为程序在这两种国际标准的岔路口无所适从,所以你必须为两种浏览器编写代码或者编写最具普遍性的功能代码而放弃大量的动态内容。
数据库服务器也面临同样的问题。ansi sql-92是人人赞同的标准。然而,oracle、微软以及其他数据库厂商还自作主张加入了很多破坏sql代码的特性。因此,你不仅得编写遵从基本规范(sql-92)的代码,而且的代码还得根据具体用到的产品实现不同的特性。
在你自己的应用程序内,你必须正确地决定应用程序将使用什么类型的数据库,而且数据库应该定位在哪里。你还得老练地处理应用程序或用户产生的任何错误。你当然不希望仅仅因为文件被删除或者网线连接松弛就导致程序崩溃(或服务器崩溃)。在经过精心设计的网络上,数据库服务器通常同工作站和web服务器、应用服务器在物理上相分离,因此断开连接是很常见的。
小结
作为者,你需要对应用程序使用非标准sql命令的危险保持高度的小心。这篇文章的中心思想是建议用ansi sql编写跨平台的应用程序。利用ansi sql减少商业数据库系统的非标准方言所带来的头疼问题。