ODBC Rocks!

在发布了19年之后,ODBC已经成为软件工业的基石之一。本文将为您介绍为什么ODBC会扮演如此重要的角色,微软SQL Server和ODBC的关系,还会讨论未来ODBC的发展方向。

作为一个被广泛使用、跨平台、跨数据库的数据访问技术,ODBC已经取得了巨大的成功。ODBC可能是ISO/IEC 9075-3:2003 SQL调用级接口(Call Level Interface,全部SQL标准的第三部分)最广为人知的实现。ODBC包含在Windows、MacOS和所有主要的Linux版本中,也包含在很多Unix版本中,例如AIX、HP-UX、Solaris和FreeBSD。甚至PDA和Smartphone手机都包含ODBC!

虽然人们总是把ODBC作为C和C++程序应用接口(API),ODBC也可以在其他的编程语言环境下使用。举例来说,很多COBOL程序用ODBC来做数据访问,动态语言如PHP、Perl、Python、Ruby,还有一些快速应用开发工具(RAD)如微软Access也使用ODBC。

尽管ODBC多用于关系数据库的连接,其他数据源也很少能离得开ODBC驱动:文本文件、Excel表格,dBase、Paradox、C-ISAM、Btrieve还有VSAM等索引顺序存取方法(ISAM)数据源,你能想到的基本上都有相应的ODBC驱动程序。对于没有ODBC驱动的数据源,你很容易就能找到一个第三方的ODBC驱动,或者用驱动开发工具包来填补这个空缺。总而言之,没有一个关系数据库离得开ODBC驱动。

ODBC广泛用于企业级应用开发,大多数主流独立软件供应商(ISV)都提供对其的支持。ERP、CRM、SCM和微软office,都通过ODBC来做查询、分析、报表生成,还有ETL(数据抽取、转换和加载)。

是什么让ODBC在不同的软件业细分市场都如此流行呢?为什么ODBC在可以预见的未来还会继续流行下去?

对于数据源(Data Source)的拥有者,ODBC是必须的。ODBC同ADO.NET、JDBC和OLE DB一样, 作为工业标准的应用编程接口(API),使数据源可以被程序开发者、被第三方工具和程序包访问。为所有这些数据访问技术开发相对应的驱动需要花费大量的时间、财力和物力。如果资源有限或者时间紧迫,最好的策略是什么呢?应该是先实现ODBC驱动,之后再考虑实现别的驱动。为什么?第一,其它所有的API都可以桥接到ODBC上,一旦有了ODBC驱动,你就可以通过其它任何API来访问数据库。第二,即使不考虑桥接,ODBC可以给数据源用户提供最广泛的第三方软件支持,因为ODBC是最早最成熟的数据访问技术,累计了大量的工具和应用。

ODBC能,而且通常是在专有的(proprietary)API之上实现的。在ODBC发展的早期,很多人认为这是第一代ODBC驱动的缺点。但是后来的研究表明,把ODBC建立在专有的Native (Native)API上对性能的影响微乎其微。在某些情况下,如果ODBC驱动引入策略去克服底层Native API的薄弱环节,ODBC甚至比专有API更高效。对于一些数据库来讲,包括微软SQL Server,ODBC都能满足作为专有Native API的角色。

企业IT和企业开发人员生活在一个非常多变的环境中,他们必须支持多语言、多操作系统,还有多种数据源。他们的压力一方面来自整合和标准化应用平台,另一方面来自改进现有程序,重整业务流程,提高信息整合,还有引入商业智能(Business Intelligence)。如何应付这些压力呢?

在数据集成和数据整合的情景下,从ETL到BI,ODBC的普及是很有价值的,它能将数据从数据包和客户应用中提取出来。

.Net平台现在被广泛应用于新的开发中。但在许多情况下,从时间、业务风险、整体成本因素上考量,代码重用和修改现有程序更容易被接受。在这方面,ODBC能做的很多。通常来说,应用程序开发人员通过在Visual Studio里使用/CLR编译选项,可以很容易的重新编译现有的代码,使得它能在.Net应用里被重用。这极大地简化了现有的C++和ODBC的业务逻辑与一个现代化的用户界面之间的结合,用户可以快速开发.NET平台应用。ODBC为各种不同的数据源和操作系统提供了一个通用的API,可以同步的访问多个数据源。这些是信息整合,聚集和集成的基本要求,无论是在native应用中,还是通过.Net平台的ODBC数据提供程序(Data Provider for ODBC)。

除了直接重用现有的业务逻辑,ODBC也是替换其他专有的API的一个重要候选。比如在做数据库迁移的时候,把使用如DB – Library,CT-Library或者OCI的应用程序迁移到ODBC上,要比完全用.Net重写来得高效和低成本,因为ODBC同其他Native API是很相似的 。

ISV通常会支持多种不同的数据库,从而增加市场和客户吸引力。ODBC提供了多种办法来满足这一要求。总之,ODBC提供了一个通用的API,可以处理多个数据源,而且如上所述,有广泛且可用的驱动程序。当然,不同的数据源也有不同的特性,这反映在一系列不同的ODBC驱动程序上。

解决这一问题的最简单的办法是使用最严格的行为模式和SQL方言子集(SQL dialect subset)。ODBC提供转义序列(escape sequences)来解决SQL方言之间的细小分歧。如果这还不够,下一步应用程序可以通过ODBC查询驱动程序的特性、数据库的特性,动态的来处理。应用程序也可以判断出实际的驱动程序和数据库,在通用性和驱动程序特性之间权衡,从而满足严格的功能和性能要求。而且,ODBC对应用程序提交到数据源的SQL语句没有任何限制,因此不会影响SQL方言的丰富性。

一些ISV使用内部的数据抽象层来实现功能——用不同的API访问不同的数据库。即使是在这种情况下,ODBC也可以胜任。对于一些数据库,特别是微软SQL Server,ODBC是性能最好的API。

系统集成商和增值经销商(VAR,Value Added Reseller)从两方面受益于ODBC。他们可以确信,无论什么操作平台和其他基础设施,所有数据源都会有ODBC支持,从而不需要开发一个专门的工具。其次,相比于技能相对狭窄的技术人员,熟悉ODBC的技术人员可以满足更广泛的客户需求。

ODBC和微软的SQL Server

对于软件行业的方方面面来说,ODBC有广泛而持久的吸引力。虽然有时候低调了些,ODBC仍然是Microsoft数据平台一个重要的组成部分。现在,让我们讨论一下关于ODBC和Microsoft SQL Server之间关系的更多细节。

最早的时候, DB-Library是SQL Server唯一的客户端应用程序API。后来,SQL Server API家族又添加了ODBC,然后是OLE DB,以及最近的ADO.NET。DB-Library由于技术上的限制已经不推荐使用,只是为旧的应用程序提供向后兼容性。

“在OLE DB发布后,微软的专家们相信它将取代ODBC 。现在情况已经彻底改变了... ”

在OLE DB发布的时候, SQL Server团队相信OLE DB将取代ODBC 。实际情况已经完全改变了,ODBC的未来前景十分看好。ODBC的应用比OLE DB广泛的多,和OLE DB比,ODBC更适合于一些关键的应用,我们将在本文后面一些讨论这个问题。

OLE DB和ODBC都是用于SQL Server的Native API,它们直接映射API调用到SQL Server的网络协议——TDS(Tabular Data Stream,一种表格式数据流的协议) 。ODBC是TDS之上一个非常薄的封装,在网络数据包缓冲和应用程序之间,没有额外的中间缓冲层。因此,它具有优良的性能和很好的负载能力。

支持Microsoft SQL Server的ODBC和OLE DB驱动包含于WDAC (Windows数据访问组件)中。WDAC就是原来的MDAC ( Microsoft数据访问组件)。另外,ODBC和OLE DB驱动也包含在Microsoft SQL Server Native Client(SQL Server 本地客户端)中,用来支持微软SQL Server 2005,2008和更高版本。WDAC中的ODBC和OLE DB驱动已经不推荐新的应用使用,只是为旧的应用程序提供向后兼容性。想要有更高的性能,更好的稳定性,或使用SQL Server新特性的应用程序需要使用Microsoft SQL Server Native Client。这些新特性包括快照隔离,数据库镜像,查询通知和某些数据类型(如XML和VARCHAR (max))等。微软将继续在ADO.NET (通过SqlClient)、ODBC和OLE DB (通过SQL Server Native Client)和JDBC 中添加对SQL Server新特性的支持。

ODBC未来的角色

我现在列举一些关键的应用,来说明ODBC将在SQL Server的未来中扮演的重要角色。一些SQL Server的组件内在地依赖于OLE DB,并反映在外部接口上。由于认识到ODBC的广泛普及,微软已经决定继续支持Microsoft OLE DB Provider for ODBC, 包括Windows Server 2003、 Windows Vista、Windows Server 2008、Windows 7和Windows Server 2008 R2的32位和64位版本。 这保证了当用户认为ODBC是最好选择的时候,可以很容易的找到相关组件。

动态语言,如PHP、Perl、Python和Ruby,应用十分广泛。.NET平台支持其中一些动态语言,其他一些平台上也同样支持多种动态语言。虽然不同的库有着不同的质量和性能,几乎所有这些语言都可以通过ODBC访问微软SQL Server。微软将不断评估是否有必要对这些库进行基于SQL Server的优化。说到这里,微软已经发布了一个基于Microsoft SQL Server Native Client ODBC Driver的PHP扩展库。

应用迁移和服务器整合作为一种降低运营和许可费用的手段,越来越受到业界的重视。 SQL Server卓越的总拥有成本(TCO)在这一点上很有吸引力。正如上文所讲,ODBC在数据整合和应用迁移上扮演了一个重要的角色。微软SQL Server迁移助手(Migration Assistant)是一个用来帮助客户迁移架构(schema)和数据库本身到Microsoft SQL Server的工具。微软也致力于开发一些文档和工具,以帮助用户将应用程序迁移到ODBC和Transact SQL上。

非Windows客户端和mid-tier服务器在上述情况之下又增加一个额外的层面。目前第三方ODBC驱动程序已经基本满足客户的需求,但微软仍会不断评估提供自有驱动的必要性,以确保客户获得最好的体验。

最后,微软希望现有的客户将来能获得更大的成功。这涉及到将他们现有的代码通过应用程序更新和代码重用来获得最大的回报。如果现有的业务逻辑能继续满足业务需求,那么代码重用比重写一遍更有意义。例如,不管采用何种应用架构,金融应用程序都使用相同的算法来做预测分析。又例如,分析批处理和call center程序,并将其重新部署成SOA(面向服务体系结构)模式,从而使其适用于B2B和无人售货等情形,也很有商业上的意义。当然,.NET在开发新的通讯、用户界面程序方面很有竞争力,但是,基于C++和ODBC的业务逻辑和数据访问程序可以很容易的被重用,而且只需要很小的改动和很低的成本。Visual Studio和C + + CLI提供很好的重用和互用性,而且以后还会通过提供完善的重构(re-factoring)工具来继续拓展这些能力。

未来15年内,ODBC蕴藏怎样的机遇和挑战呢?

有两个重要的且相关联的问题。第一,作为最重要的native API,如何保证ODBC继续更新从而适应SQL Server的新功能?第二,ODBC如何继续扮演作为工业标准的跨平台、跨数据库API的角色?

ODBC驱动程序可以在核心ODBC规范的基础上添加驱动特有的扩展, 正是有了这种可扩展性,Microsoft SQL Server Native Client添加了对Microsoft SQL Server新特性的支持。其他驱动也可以添加自己的扩展。下面的两个例子演示了Microsoft SQL Server Native Client如何支持SQL Server的新特性。

SQL Server 2008增加了额外的日期/时间数据类型,以补充现有的datetime和smalldatetime类型:date和datetime2对应于现有的SQL_TYPE_DATE和SQL_TYPE_TIMESTAMP类型;time(具有7位小数秒精度)和datetimeoffset(datetime2加上时区信息)没有相对应的ODBC数据类型,所以Microsoft SQL Server Native Client添加了新的数据类型:SQL_SS_TIME2和SQL_SS_DATETIMEOFFSET。

SQL Server中,table-valued参数(TVP)是用于T - SQL语句或存储过程中、可以由多个行和列组成的参数。例如,考虑以下声明:

Insert into OrderItems (OrdID, ProdCode, Qty)
Select ?, ProdCode, Qty from ?

第一个参数是新插入的OrdID主键,但二个参数是一个TVP参数,它包含了每个OrdID相对应的列,TVP实现了在一个SQL语句中,用一个参数,来插入多行。TVP通过减少客户端和服务器端的交互以及在TDS和关系数据库引擎上的优化,有效的改进了性能。通过加强封装性,一个单一的存储过程可以执行完整的事务处理。存储过程通常限制参数为“矩阵式”,TVP弱化了这种限制,极大的提高了代码清晰度。看下面的例子:

create type OrdItemType as table(
ProdCode integer, Qty integer)

create procedure OrderEntry
(
      @CustCode varchar(5),
      @Items OrdItemType READONLY,
      @OrdNo integer output,
      @OrdDate datetime output)
as
      set @OrdDate = GETDATE();
      insert into Orders (OrdDate, CustCode)
          values (@OrdDate, @CustCode);
      select @OrdNo = SCOPE_IDENTITY();
      insert into TVPItem (OrdNo, ProdCode, Qty)
          select @OrdNo, ProdCode, Qty from @Items
)

如果没有TVP,你需要用两个存储过程:每个数据表对应一个存储过程。

因为我们可以把TVP和传统的单值参数在一个SQL语句中混用,绑定ODBC参数时,SQL Server Native Client必须提供一种方法来处理这种嵌套表。具体是这样的:首先把TVP绑定成SQL_SS_TABLE——一个代表嵌套表的新SQL类型;然后通过SQLSetStmtAttr将SQL_SOPT_SS_PARAM_FOCUS 设置为TVP参数的序号,这表明接下来的SQLBindParameter是用来绑定该TVP中各列的(而不是“顶层“的参数)。一开始我们认为TVP这个ODBC扩展过于复杂和困难,通过上述实现,这变得十分简单,代码紧凑而且清晰可读。SQL Server中完整的TVP实现建立在已有的ODBC规范——array binding和“data at execution“之上。这允许TVP中的各行数据可以在运行时提供,这些数据既可以是内存中的数组,也可以是分批地传到服务器的一行或者多行数据。

到目前为止,一切都很顺利。 SQL Server Native Client的实践表明,一个ODBC驱动程序可以添加一些重要功能,而无需更改ODBC规范。但是如果一个SQL Server新的功能超出ODBC的扩展能力怎么办?ODBC的结构是否会在新的SQL Server应用下显得捉襟见肘?这些都是棘手的问题,其中可能的解决办法包括:更新ODBC核心规范,或者将SQL Server Native Client变成一个Native API ,可以从ODBC驱动程序管理器(ODBC Driver Manager)上剥离,从而不再受到ODBC规范的限制。这两个办法都影响深远。

改变ODBC规范并非完全无风险。ODBC最大的优点之一是它的稳定性。改变ODBC规范和现有的驱动程序,可能会让应用程序产生新的不确定的行为。如果从当前的规范中分离出来,能满足某些应用但是可能会破坏其它更多的应用。对于ODBC和SQL Server Native Client来说,有没有一个乌托邦式的“第三种选择”呢?IBM DB2的调用级接口(Call Level Interface)可以运行在两种模式下:作为ODBC 驱动(通过驱动管理器Driver Manager)或者独立的call level interface. 对于SQL Server Native Client和ODBC来说,这可能是一个渐进的过程。另一个选择是,让现有的和将来的ODBC版本并存。目前,ODBC驱动程序管理器已经做到ODBC2和ODBC3的并存。

有没有其他组织对扩展ODBC现有规范感兴趣呢?在这方面,微软要鼓励有关方之间的讨论,评估某些广泛共识的可行性。而某些社区形式为基础的创新,比起ISO或ANSI,可能反应更快速,投入更广泛。不过有一点可以肯定,不管发生什么,没有什么可以破坏ODBC丰富的遗产和其持久的产业价值。

微软把实体数据模型(Entity Data Model,EDM)视为一个改变整个软件产业的革命性技术,在现有的ADO.NET实体框架(Entity Framework)上得到了很好的应用。想象一下,如果把ODBC和EDM结合起来,将是多么的激动人心。ODBC可以来支持实体SQL(Entity SQL)上的查询,返回有多行和嵌套实体值的实体结果。TVP中处理非矩阵性数据的经验表明在SQL Server Native Client上对EDM做驱动层面上的扩展是完全可行的。另外,除了SQL Server,微软正在引入越来越多的数据源来支持EDM,其他的一些关系数据库产品也可以通过ADO.NET Entity Framework来支持EDM。所以为什么我们不能直接在ODBC的核心规范层面上来支持EDM呢?答案在一定程度上取决于ODBC应用程序在哪个层面上使用EDM:EDM和关系型访问分别在不同的驱动上?同一个驱动的不同连接上?还是在同一个连接上?是渐进的将EDM应用到现有的代码里,还是只在新的代码里使用?这是另一个微软希望能听到有关各方讨论的领域。

ODBC已经走过了漫长的道路,希望这篇文章能给你带来对ODBC一些新的理解:ODBC有哪些已经存在了很久而且还将一直为你所用的功能;它今后会如何发展;微软保证将长期提供对ODBC的改进和支持。

如果你想就本文中所提及的内容做进一步的讨论,请发送电子邮件至odbcfut@microsoft.com

你可以在以下链接找到更多关于ODBC的信息:

  1. ODBC Rocks!英文原文 

    https://www.code-magazine.com/Article.aspx?quickid=0712172

  2. Mike Pizzo:微软数据访问APIs 的历史
    https://blogs.msdn.com/data/archive/2006/12/05/data-access-api-of-the-day-part-i.aspx

  3. Wikipedia ODBC
    https://en.wikipedia.org/wiki/Open_Database_Connectivity

  4. Ken North:SQL and ODBC in integration frameworks for Business Integration Journal
    https://www.sqlsummit.com/PDF/BIJ_North_Nov2004.pdf

  5. Ken North:ODBC portal
    https://www.sqlsummit.com/ODBCPORT.HTM 

  6. ODBC MSDN文档
    https://msdn2.microsoft.com/en-us/library/ms710252.aspx 

  7. Microsoft SQL Server Native Client MSDN文档
    https://msdn2.microsoft.com/en-us/data/aa937705.aspx 

  8. SQL Native Client 博客
    https://blogs.msdn.com/sqlnativeclient/

  9. MSDN DATA 博客
    https://blogs.msdn.com/data/

  10. SQL Server Data Access论坛
    https://social.msdn.microsoft.com/forums/en-us/sqldataaccess

  11. SQL Server 中文论坛
    https://social.msdn.microsoft.com/forums/zh-CN/sqlserverzhchs/

软件测试工程师
于凯