数据库编程
本文最后更新于68 天前,其中的信息可能已经过时。

数据库编程

SQL 编程语句技术可以有效克服 SQL 语言实现复杂应用方面的不足,提高应用系统和数据库管理系统间的互操作性。

SQL 编程访问和管理数据库的方式:嵌入式 SQL、过程化 SQL、存储过程和定义函数、开放数据库互连、OLE DB、Java 数据库连接等编程方式。

嵌入式 SQL

SQL 语言的特点之一是交互式和嵌入式两种不同的使用方式下,SQL 的语法结构基本一致。在程序设计的环境下,SQL 语句要做某些必要的扩充。

嵌入式 SQL 的处理过程

主语言:嵌入式 SQL 是将 SQL 语句嵌入程序设计语言中,被嵌入的程序设计语言,如 C、C++、Java,称为宿主语言,简称主语言。

嵌入式 SQL 前缀:为了区分 SQL 语句与主语句语句,所有 SQL 语句必须加前缀。

例:主语言为C语言时,语句格式:
    EXEC SQL <SQL语句>;

主语言为Java语言时,语句格式:
    #SQL <SQL语句>;

嵌入式 SQL 处理过程:预编译方法。具体过程如下图:

未命名文件(1)

嵌入式 SQL 语句与主语言之间的通信

嵌入式 SQL 语句中会含有两种不同计算模型的语句:SQL 语句负责操纵数据库,高级语言语句负责控制逻辑流程。

数据库工作单元与源程序工作单元之间的通信:

  1. 向主语言传递 SQL 语句的执行状态信息,使主语言能据此信息控制程序流程,主要用 SQL 通信区(SQLCA:SQL Communication Area)实现。
  2. 主语言向 SQL 语句提供参数,主要用主变量(host variable)实现。
  3. 将 SQL 语句查询数据库的结构交主语言处理,主要用主变量和游标(cursor)实现。

SQL 通信区

SQLCA 的用途:SQL 语句执行后,系统将描述系统当前工作状态的数据和描述运行环境的数据送到 SQL 通信区,应用程序从 SQL 通信区中取出这些状态信息,据此决定接下来执行的语句。

定义SQLCA格式:
    EXEC SQL INCLUDE SQLCA;

【说明】

  1. SQLCA 中设置变量 SQLCODE,存放每次执行 SQL 语句后返回代码。
  2. 当 SQLCODE 等于 SUCCESS,表示 SQL 语句成功,否则出错。
  3. 应用程序每执行完一条 SQL 语句都应该测试一下 SQLCODE 的值,以了解该 SQL 语句执行情况并做相应处理。

主变量

嵌入式 SQL 语句中可以使用主语句的程序变量来输入或输出数据,在 SQL 语句中使用的主语句程序变量,简称为主变量。

输入主变量:由应用程序对其赋值,SQL 语句引用。

输出主变量:由 SQL 语句对其赋值或设置状态信息,返回给应用程序。

指示变量:是一个整型变量,一个主变量可以附带一个指示变量,用来指示所指主变量的值或条件,例如指示变量的用途、指示输入主变量是否为空值、检测输出变量是否为空值、值是否被截断等。

定义主变量和指示变量的格式:
    BEGIN DECLARE SECTION;
        ...
        ...     (说明主变量和指示变量)
        ...
    END DECLARE SECTION;

【说明】

  1. 定义的主变量可以在 SQL 语句中任何一个能够使用表达式的地方出现。
  2. 为了与数据库对象名(表名、视图名、列名等)区别,SQL 语句中的主变量名前要加冒号(:)作为标志
  3. 指示变量必须紧跟在所指主变量之后,指示变量前也必须加冒号标志。
  4. 在 SQL 语句之外(主语言语句中)可以直接引用主变量和指示变量,不必加冒号。

游标

(1)为什么要使用游标

SQL 语言是面向集合的,一条 SQL 语句原则上可以产生或处理多条记录。主语言是面向记录的,一组主变量一次只能存放一条记录。仅使用主变量并不能完全满足 SQL 语句向应用程序输出数据的要求。嵌入式 SQL 引入了游标的概念吗,用来协调这两种不同的处理方式。

(2)什么是游标

游标是系统为用户开设的一个数据缓冲区,存放 SQL 语句的执行结果,每个游标区都有一个名字,用户可以用 SQL 语句逐一从游标中获取记录,并赋给主变量,交由主语言一步处理。

建立和关闭数据库连接

(1)建立数据库连接

格式:
    EXEC SQL CONNECT TO target[AS connection-name][USER user-name];

【说明】

  1. targer 是要连接的数据库服务器,常见的如:包含服务器标识的 SQL 串常量、< dbname >@< hostname >:< port >、DEFAULT。

  2. connection-name 指定的连接名。连接名必须是一个有效的标识符。如果在整个程序内只有一个连接时可以不指定连接名。

  3. 程序运行过程中可以用以下语句修改当前连接:

    EXEC SQL SET CONNECTION connection-name|DEFAULT;
    

(2)关闭数据库连接

格式:
    EXEC SQL DISCONNECT [connection];

【说明】

connection 是用 EXEC SQL CONNECT 所建立的数据库。

例:依次检查学生记录,交互式更新某些学生年龄。
    EXEC SQL BEGIN DECLARE SECTION;         /*主变量说明开始*/
        char Deptname[20];
        char HSno[9];
        char HSname[20];
        char HSsex[2];
        int HSage;
        int NEWAGE;
    EXEC SQL END DECLARE SECTION;           /*主变量说明结束*/
        long SQLCODE;
    EXEC SQL INCLUDE SQLCA;                 /*定义SQL通信区*/
    int main(void)                          /*C语言主程序开始*/
    {
        int count=0;
        char yn;                            /*变量yn代表yes或no*/
        printf("Please choose the department name(CS/MA/IS):");
        scanf("%s",Deprname);             /*为主变量deptname赋值*/
        EXEC SQL CONNECT TO TEST@localhost:54321 USER "SYSTEM"/"MANAGER";
                                            /*连接数据库TEST*/
        EXEC SQL DECLARE SX CURSOR FOR      /*定义游标SX*/
            SELECT Sno,Sname,Ssex,Sage      /*SX对应的语句*/
            FROM Student
            WHERE SDept=:deptname;
        EXEC SQL OPEN SX;                   /*打开游标SX,指向查询结果的第一行*/
        for(;;)                             /*用循环结构逐条处理结果集中的记录*/
        {
            EXEC SQL FETCH SX INTO :HSno,:HSname,:HSsex,:HSage;
                                            /*推进游标,将当前数据放入主变量*/
            if(SQLCA.SQLCODE!=0)
                break;                      /*如果表示连接不成功退出循环*/
            if(count++==0)                  /*如果是第一行的话,先打出行头*/
                printf("\n%-10s %-20s %-10s %-10s\n","Sno","Sname","Ssex","Sage");
            printf("%-10s %-20s %-10s %-10d\n",HSno,HSname,HSsex,HSage);
                                            /*打印查询结果*/
            printf("UPDATE AGE(y/n)?");       /*询问用户是否要更新该学生的年龄*/
            do{scanf("%c",&yn);}
            while(yn!=='N'&&yn!=='n'&&yn!=='Y'&&yn!=='y');
            if(yn=='y'||yn=='Y')            /*如果选择更新操作*/
            {
                printf("INPUT NEW AGE:");
                scanf("%d",&NEWAGE);      /*用户输入新年龄到主变量中*/
                EXEC SQL UPDATE Student     /*嵌入式SQL更新语句*/
                    SET Sage=:NEWAGE
                    WHERE CURRENT OF SX;    /*对当前游标指向学生的年龄进行更新*/
            }
        }
        EXEC SQL CLOSE SX;                  /*关闭游标SX,不再和查询结果对应*/
        EXEC SQL COMMIT WORK;               /*提交更新*/
        EXEC SQL DISCONNECT TEST;           /*断开数据库连接*/
    }

不用游标的 SQL 语句

当 SQL 语句为以下种类时,可以不用游标:

  1. 说明性语句。
  2. 数据定义语句。
  3. 数据控制语句。
  4. 查询结果为单记录的 SELECT 语句。
  5. 非 CURRENT 形式的增删改语句。

查询结果为单记录的 SELECT 语句

这类语句不需要使用游标,只需用 INTO 子句指定查询结果的主变量

例:根据学生号码查询学生信息。
    EXEC SQL SEELECT Sno,Sname,Ssex,Sage,Sdept
        INTO:Hsno,:Hname,:Hsex,:Hage,:Hdept
        FROM Student
        WHERE Sno=:givensno;        /*把要查询的学生的学号赋给了主变量givensno*/

【说明】

  1. INTO 子句、WHERE 子句和 HAVING 短语的条件表达式中均可以使用主变量。
  2. 查询结果的列为空值 NULL,系统会自动将主变量后的指示变量设置为负值,当指示变量为负值时,不管主变量为何值,系统均认为主变量为 NULL。
  3. 如果查询结果实际上是多条记录,则程序出错,关系数据库管理系统会在 SQLCA 中返回错误信息。
例:查询某个学生选修某门课程的成绩。假设已经把将要查询的学生的学号赋给了主变量givensno,将课程号赋给了主变量givencno。
    EXEC SQL SELECT Sno,Cno,Grade
        INTO:Hsno,:Hcno,:Hgrade:Gradeid     /*指示变量Gradeid*/
        FROM SC
        WHERE Sno=:givensno AND Cno=:givencno;
如果Grade<0,不论Hgrade为何值,均认为该学生成绩为空值。

非 CURRENT 形式的增删改语句

在 UPDATE 的 SET 子句和 WHERE 子句中可以使用主变量,SET 子句还可以使用指示变量。

例:修改某个学生选修1号课程的成绩。
    EXEC SQL UPDATE SC
        SET Grade=:newgrade
        WHERE Sno=:givensno;

例:某个学生新选修了某门课程,将有关记录插入SC表中。假设插入的学号已赋给主变量stdno,课程号已赋给主变量couno。
    gradeid=-1;     /*gradeid为指示变量,赋为负值*/
    EXEC SQL INSERT
        INTO SC(Sno,Cno,Grade)
        VALUES(:stdno,:couno,:gr:gradeid);
由于该学生刚选修课程,成绩应为空,所以要把指示变量赋为负值。

使用游标的 SQL 语句

必须使用游标的 SQL 语句如下:

  1. 查询结果为多条记录的 SELECT 语句。
  2. CURRENT 形式的 UPDATE 语句。
  3. CURRENT 形式的 DELETE 语句。

查询结果为多条记录的 SELECT 语句

使用游标的步骤:

  1. 说明游标。
  2. 打开游标。
  3. 推进游标指针并取当前记录。
  4. 关闭游标。

(1)说明游标

语句格式:
    EXEC SQL DECLARE <游标名> CURSOR <SELECT语句>;

功能:该语句是一条说明性语句,这时关系数据库管理系统并不执行 SELECT 语句。

(2)打开游标

语句格式:
    EXEC SQL OPEN <游标名>;

功能:执行相应的 SELECT 语句,把查询结果取到缓冲区中,这时游标处于活动状态,指针指向查询结果集中的第一条记录。

(3)推进游标指针并取当前记录

语句格式:
    EXEC SQL FETCH <游标名>
        INTO <主变量>[<指示变量>][,<主变量>[<指示变量>]]...;

功能:指定方向推动游标指针,同时将缓冲区中的当前记录取出来送至主变量供主语言进一步处理。

(4)关闭游标

语句格式:
    EXEC SQL CLOSE <游标名>

功能:关闭游标,释放结果集占用的缓冲区及其他资源。

【说明】

  1. 游标被关闭后,就不再和原来的查询结果相联系。
  2. 被关闭的游标可以再次被打开,与新的查询结果相联系。

CURRENT 形式的 UPDATE 语句和 DELETE 语句

如修改或删除某个记录,用带游标的 SELECT 语句查出满足条件的集合,从中进一步找出要修改或删除的记录,用 CURRENT 形式的 UPDATE 语句和 DELETE 语句修改或删除之。

UPDATE语句和DELETE语句中要用子句:
    WHERE CURRENT OF <游标名>
表示修改或删除游标指针指向的记录。

【注意】游标定义中的 SELETE 语句带有 UNION 或 ORDER BY 子句,或者该 SELECT 语句相当于定义了一个不可更新的视图时,不能使用 CURRENT 形式的 UPDATE 语句和 DELETE 语句。

动态 SQL

静态嵌入式 SQL: 静态嵌入式 SQL 语句能够满足一般要求,无法满足要到执行时才能够确定要提交的 SQL 语句、查询的条件。

动态嵌入式 SQL: 在程序运行过程中可临时“组装”SQL 语句,支持动态组装 SQL 语句和动态参数两种形式。

使用 SQL 语句主变量

SQL 语句主变量: 程序主变量包含的内容是 SQL 语句的内容,而不是原来保存数据的输入或输出变量。

SQL 语句主变量在程序执行期间可以设定不同的 SQL 语句,然后立即执行。

例:创建基本表TEST。
    EXEC SQL BEGIN DECLARE SECTION;
        const char *stms="CREATE TABLE test(a int);";
                        /*SQL语句主变量,内容是创建表的SQL语句*/
    EXEC SQL END DECLARE SECTION;
    ...
    EXEC SQL EXECUTE IMMEDIATE:stmt;    /*执行动态SQL语句*/

动态参数

动态参数是 SQL 语句中的可变元素,使用参数符号(?)表示该位置的数据在运行时设定。

与主变量不同动态参数的输入不是编译时完成绑定,而是通过 PREPARE 语句准备主变量和执行语句 EXECUTE 绑定数据或主变量来完成。

使用动态参数步骤

  1. 声明 SQL 语句主变量:SQL 语句主变量的值包含动态参数(?)。

  2. 准备 SQL 语句(PREPARE)

    EXEC SQL PREPARE <语句名> FROM <SQL语句主变量>;
    
  3. 执行准备好的语句(EXECUTE)

    格式:
        EXEC SQL EXECUTE <语句名>
            [INTO <主变量表>][USING <主变量或常量>]
    
例:向TEST中插入元组。
    EXEC SQL BEGIN DECLARE SECTION;
        const char *stms="INSERT INTO test VALUES(?);";
                        /*声明SQL主变量内容是INSERT语句*/
    EXEC SQL END DECLARE SECTION;
    ...
    EXEC SQL PREOARE mystmt FROM :stmt;     /*准备语句*/
    ...
    EXEC SQL EXECUTE mystmt USING 100;
    EXEC SQL EXECUTE mystmt USING 200;

过程化 SQL

过程化 SQL 的块结构

过程化 SQL 是 SQL 的扩展,增加了过程化语句功能,基本结构是块,每个块完成一个逻辑操作,块之间可以相互嵌套。

过程化 SQL 块的基本结构

  1. 定义部分

    • DECLARE:定义的变量、常量等只能在该基本块中使用。
    • 变量、常量、游标、异常等:当基本块执行结束时,定义就不在存在。
  2. 执行部分

    • BEGIN
          SQL语句、过程化SQL的流程控制语句
      EXCEPTION
          异常处理部分
      END;
      

变量和常量的定义

  1. 变量定义

    变量名 数据类型 [[NOT NULL]:=初值表达式]
    

    变量名 数据类型 [[NOT NULL] 初值表达式]
    
  2. 常量定义

    常量名 数据类型 CONSTANT:=常量表达式
    

    常量必须要给一个值,并且该值在存在期间或常量的作用域内不能改变。如果试图修改它,过程化 SQL 将返回一个异常。

  3. 赋值语句

    变量名称:=表达式
    

流程控制

过程化 SQL 主要提供了条件控制语句、循环控制语句等流程控制语句,这些语句的语法、语义和一般高级语言类似。

  1. 条件控制语句:IF-THEN、IF-THEN-ELSE、嵌套的 IF 语句。

    • IF 语句格式

      IF 条件 THEN
          语句;
      END IF;
      
    • IF-THEN-ELSE 语句格式

      IF 条件 THEN
          条件为真时执行的语句;
      ELSE
          条件为假或NULL时执行的语句;
      END IF;
      
    • 嵌套的 IF 语句:在 THEN 和 ELSE 子句中还可以包含 IF 语句,即 IF 语句可以嵌套。

  2. 循环控制语句:主要有 LOOP,WHILE-LOOP 和 FOR-LOOP 三类。

    • 简单的循环语句 LOOP 格式

      LOOP
          循环执行语句;
      END LOOP;
      

      多数数据库服务器的过程化 SQL 都提供 EXIT、BREAK 或 LEAVE 等循环结束语句,保证 LOOP 语句块能够结束。

    • WHILE-LOOP 循环格式

      WHILE 条件 LOOP
          条件为真时执行的语句;
      END LOOP;
      

      执行过程: 每次执行循环体语句之前,首先要对条件进行求值,如果条件为真,则执行循环体内的语句序列,如果条件为假,则跳过循环并把控制传递给下一个语句。

    • FOR-LOOP 循环

      FOR 循环变量 IN [REVERSE] bound1..bound2 LOOP
          循环语句;
      END LOOP;
      

      执行过程: 循环变量设置为下界 bound1,检查循环变量是否小于上界 bound2,如果是执行循环体,循环变量加 1,如果否,退出循环。当设置 REVERSE,表示 bound1 为上界,bound2 为下界,循环变量减 1。

  3. 错误处理

    • 如果过程化 SQL 在执行时出现异常,则应该让程序在产生异常的语句处停下来,根据异常的类型去执行异常处理语句。
    • SQL 标准对数据库服务器提供什么样的异常处理做出了建议,要求过程化 SQL 管理器提供完善的异常处理机制。

存储过程和函数

过程化 SQL 块分为匿名块和命名块两类。

匿名块: 每次执行时都要进行编译,它不能被存储到数据库中,也不能在其他过程化 SQL 块中调用。

命名块: 编译后保存在数据库中,可以被反复调用,运行速度较快,过程和函数是命名块。

存储过程

存储过程: 由过程化 SQL 语句书写的过程,经编译和优化后存储在数据库服务器中,使用时只要调用即可。

  1. 存储过程的优点

    • 运行效率高。
    • 降低了客户机和服务器之间的通信量。
    • 方便实施企业规则。
  2. 存储过程的用户接口

    • 创建存储过程格式

      CREATE OR REPLACE PROCEDURE 过程名([参数1,参数2,...])
      AS <过程化SQL块>
      
      • 【说明】

        • 过程名:数据库服务器合法的对象标识。
        • 参数列表:用名字来标识调用时给出的参数值,必须指定值的数据类型。参数也可以定义输入参数、输出参数或输入/输出参数,默认为输入参数。
        • 过程体:是一个 <过程化SQL块>,包括声明部分和可执行语句部分。
      • 例:利用存储过程来实现下面的应用:从账户1转指定数额的款项到账户2中。
            CREATE OR REPLACE PROCEDURE TRANSFER(inAccount INT,outAccount INT,amount FLOAT)
                    /*定义存储过程TRANSFER,参数为转入账户、转出账户、转账余额*/
            AS DECLARE      /*定义变量*/
                totalDepositOut Float;
                totalDepositIn Float;
                inAccountnum INT;
            BEGIN           /*检查转出账户的余额*/
                SELECT Total INTO totalDepositOut FROM Account WHERE accountnum=outAccount;
                IF totalDepositOut IS NULL THEN
                            /*如果转出账户不存在或账户中没有存款*/
                    ROLLBACK;   /*回滚事务*/
                    RETURN;
                END IF;
                IF totalDepositOut<amount THEN   /*账户存款不足*/
                    ROLLBACK;   /*回滚事务*/
                    RETURN;
                END IF;
                SELECT Accountnum INTO inAccountnum FROM Account WHERE accountnum=inAccount;
                IF inAccount IS NULL HTEN  /*如果转入账户不存在*/
                    ROLLBACK;   /*回滚事务*/
                    RETURN;
                END IF;
                UPDATE Account SET total=total-amount WHERE accountnum=outAccount;
                            /*修改转出账户余额,减去转出额*/
                UPDATE Account SET total=total+amount WHERE accountnum=inAccount;
                            /*修改转入账户余额,增加转入额*/
                COMMIT;     /*提交转账事务*/
            END;
        
    • 执行存储过程

      CALL/PERFORM PROCEDURE 过程名([参数1,参数2,...])
      
      • 【说明】使用 CALL 或者 PERFORM 等方式激活存储过程的执行。在过程化 SQL 中,数据库服务器支持在过程体中调用其他存储过程。

      • 例:从账户01003815868转10000元到01003813828账户中。
            CALL PROCEDURE TRANSFER(01003815868,01003813828,10000);
        
    • 修改存储过程

      ALTER PROCEDURE 过程名1 RENAME TO 过程名2
      
    • 删除存储过程

      DROP PROCEDURE 过程名()
      

函数

这里所讲的函数是用户自定义函数,函数和存储过程类似都是持久性存储模块,不同的是函数必须指定返回的类型

  1. 函数的定义语句格式

    CREATE OR REPLACE FUNCTION 函数名([参数1,参数2,...]) RETURNS <类型> AS <过程化SQL块>;
    
  2. 函数的执行语句格式

    CALL/SELECT 函数名([参数1,参数2,...]);
    
  3. 修改函数

    • 重命名:

      ALTER FUNCTION 函数名1 RENAME TO 函数名2;
      
    • 重新编译:

      ALTER FUNCTION 函数名 COMPILE;
      

过程化 SQL 中的游标

在过程化 SQL 中如果查询返回多条记录时,就要只用游标对结果进行处理。在存储过程中可以定义普通游标、REFCURSOR 类型游标、带参数游标等。

例:定义存储过程,多次打开游标并获取游标的当前记录。
    CREATE OR REPLACE PROCEDURE pro_cursor() AS
    DECLARE
        cno CHAR(3);
        cname CHAR(8);
    CURSOR mycursor(leaderno CHAR(3)) FOR       /*说明带参数游标mycursor*/
        SELECT lno,lname FROM leader WHERE lno=leaderno;
    BEGIN       /*mycursor能检索leader表中具有参数leaderno的记录*/
        OPEN mycursor('L01');       /*使用参数L01打开游标*/
        FETCH mycursor INTO cno,cname;      /*获取lno='L01'的游标元组*/
        INSERT INTO temp(lno,lname)VALUES(cno,cname);
                                    /*将游标元组插入临时表中*/
        CLOSE mycursor;             /*关闭游标*/
        OPEN mycursor('L02');       /*使用新的参数L02重新打开游标*/
        FETCH mycursor INTO cno,cname;
        INSERT INTO temp(lno,lname)VALUES(cno,cname);
        CLOSE mycursor;
    END;

ODBC 编程

使用 ODBC 编写的应用程序可移植性好,能同时访问不同的数据库,共享多个数据资源。

ODBC 概述

  1. ODBC 产生的原因

    • 由于不同的数据库管理系统的存在,在某个关系数据库管理系统下编写的应用程序就不能在另一个关系数据库管理系统下运行。
    • 许多应用程序需要共享多个部门的数据资源,访问不同的关系数据库管理系统。
  2. 什么是 ODBC

    • ODBC 是微软公司开放服务体系中有关数据库的一个组成部分,它提供了一组访问数据库的应用程序编程接口(API)。
    • 主要作用是规范应用开发和规范关系数据库管理系统应用接口。

ODBC 工作原理概述

ODBC 应用系统的体系结构包括:用户应用程序、ODBC 驱动程序管理器、数据库驱动程序、数据源。如下图: 未命名文件

用户应用程序

ODBC 应用程序包括的内容:

  1. 请求连接数据库。
  2. 向数据源发送 SQL 语句。
  3. 为 SQL 语句执行结果分配存储空间,定义读取的数据格式。
  4. 获取数据库操作结果或处理错误。
  5. 进行数据处理并向用户提交处理结果。
  6. 请求事务的提交和回滚操作。
  7. 断开与数据源的连接。

ODBC 驱动程序管理器

驱动程序管理器包含在 ODBC32.DLL 中,对用户透明,管理应用程序和驱动程序之间的通信。

主要功能:

  1. 装载 ODBC 驱动程序。
  2. 选择和连接正确的驱动程序。
  3. 管理数据源。
  4. 检查 ODBC 调用参数的合法性。
  5. 记录 ODBC 函数的调用等。

数据库驱动程序

ODBC 通过启动程序来提供应用系统与数据库平台的独立性,ODBC 应用程序不能直接存取数据库,各种操作由驱动程序提交给 DBMS 的 ODBC 驱动程序,调用驱动程序支持的函数来存取数据库。

ODBC 驱动程序类型:

  1. 单束:数据源和应用程序在同一台机器上,驱动程序直接完成对数据文件的 I/O 操作,驱动程序相当于数据管理器。
  2. 多束:支持客户机—服务器、客户机—应用服务器/数据库服务器等网络环境下的数据访问,由驱动程序完成数据库访问请求的提交和结果集接收,应用程序使用驱动程序提供的结果集管理接口操纵执行后的结果数据。

ODBC 数据源管理

数据源: 是最终用户需要访问的数据,包含了数据库位置和数据库类型等信息,是一种数据连接的抽象。

【说明】

  1. ODBC 给每个被访问的数据源指定唯一的数据源名(Data Source Name,简称 DSN),并映射到所有必要的、用来存取数据的底层软件。
  2. 在连接中,用数据源名来代表用户名、服务器名、所连接的数据库名等。用户无须知道数据库管理系统或其他数据管理软件、网络以及有关 ODBC 驱动程序的细节。

【例】假设某个学校在 SQL Server 和 KingbaseES 上创建了两个数据库:学校人事数据库和教学科研数据库。

学校的信息系统要从这两个数据库中存取数据,为了方便地与两个数据库连接,为学校人事据库创建一个数据源名 PERSON,为教学科研数据库创建一个名为 EDU 的数据源。当要访问每一个数据库时,只要与 PERSON 和 EDU 连接,不需要记住使用的驱动程序、服务器名称、数据库名。

ODBC API 基础

ODBC 应用程序编程接口的一致性是指 API 一致性和语法一致性。

函数概述

ODBC 3.0 标准提供了 76 个函数接口,大致可以分为:

  1. 分配和释放环境句柄、连接句柄、语句句柄。
  2. 连接函数(SQLDriverconnect 等)。
  3. 与信息相关的函数(SQLGetinfo、SQLGetFuction 等)。
  4. 事务处理函数(如 SQLEndTran)。
  5. 执行相关函数(SQLExecdirect、SQLexecute 等)。
  6. 编目函数,ODBC 3.0 提供了 11 个编目函数,如 SQLTables、SQLColumn 等。

句柄及其属性

句柄是 32 位整数值,代表一个指针。ODBC 3.0 中句柄分为环境句柄、连接句柄、语句句柄、描述符句柄。具体关系如下图:

未命名文件

【说明】

  1. 每个 ODBC 应用程序需要建立一个 ODBC 环境,分配一个环境句柄,存取数据的全局性背景,如环境状态、当前环境状态诊断、当前在环境上分配的连接句柄等。
  2. 一个环境句柄可以建立多个连接句柄,每一个连接句柄实现与一个数据源之间的连接。
  3. 在一个连接中可以建立多个语句句柄,它不只是一个 SQL 语句,还包括 SQL 语句产生的结果集以及相关的信息等。
  4. 在 ODBC 3.0 中又提出了描述符句柄的概念,它是描述 SQL 语句的参数、结果集列的元数据集合。

数据类型

ODBC 数据类型:SQL 数据类型用于数据源;C 数据类型用于应用程序的 C 代码。

应用程序可以通过 SQLGetTypeInfo 来获取不同的驱动程序对于数据类型的支持情况。

SQL 数据类型和 C 数据类型之间的转换规则:

 SQL 数据类型C 数据类型
SQL 数据类型数据源之间转换应用程序变量转送到语句参数(SQLBindparameter)
C 数据类型从结果集列中返回到应用程序变量(SQLBindcol)应用程序变量之间转换

ODBC 的工作流程

未命名文件

【例】将 KingbaseES 数据库中 Student 表的数据备份到 SQL Sever 数据库中。

该应用设计两个不同的关系数据库管理系统中的数据源,使用 ODBC 来开发应用程序,只要改变应用程序中连接函数(SQLConnect)的参数,就可以连接不同关系数据库管理系统的驱动程序,连接两个数据源。

  1. 配置数据源

    • 配置数据源有两种方法:一是运行数据源管理工具来进行配置,二是使用 Driver Manager 提供的 ConfigDsn 函数来增加、修改或删除数据源。
    • 上例中,采用第一种方法创建数据源。因为要同时用到 KingbaseES 和 SQL Server,所以分别建立两个数据源,将其名位 KingbaseES ODBC 和 SQL Server。
  2. 初始化环境

    • 没有和集体的启动程序相关联,由 Driver Manager 来进行控制,并配置环境属性。应用程序通过调用连接函数和某个数据源进行连接后,Driver Manager 才调用所连的驱动程序中的 SQLAllocHandle 来真正分配环境句柄的数据结构。
  3. 建立连接

    • 应用程序调用 SQLAllocHandle 分配连接句柄,通过 SQLConnect、SQLDriverConnect 或 SQLBrowseConnect 与数据源连接。
  4. 分配语句句柄

    • 处理任何 SQL 语句之前,应用程序还需要首先分配一个语句句柄,语句句柄还有具体的 SQL 语句以及输出的结果集等信息。
  5. 执行 SQL 语句

    • 处理 SQL 语句的两种方式:预处理(SQLPrepare、SQLExecute 适用于语句的多次执行)和直接执行(SQLExecdirect)。
    • 应用程序根据语句类型进行的处理。
    • 有结果集的语句则进行结果集处理。
    • 没有结果集的函数,可以直接利用本语句句柄继续执行新的语句或是获取行记数(本次执行所影响的行数)之后继续执行。
  6. 结果集处理

    • 应用程序可以通过 SQLNumResultCols 来获取结果集中的列数,通过 SQL DescribeCol 或是 SQLColAttribute 函数来获取结果集每一列的名称、数据类型、精度和范围。

    • ODBC 中使用游标来处理结果集数据,ODBC 中游标类型有:

      • Forward-only 游标(ODBC 的默认游标类型):只能在结果集中向前滚动,它是 ODBC 的默认游标类型。
      • 可滚动(Scroll)游标:静态、动态、码集驱动、混合型。
  7. 中止处理

    • 处理结束后,应用程序首先释放语句句柄,然后释放数据库连接并与数据库服务器断开,最后释放 ODBC 环境。

OLE DB

什么是 OLE DB

OLE DB 对象链接与嵌入式数据库,是微软提出的数据库连接访问标准。是基于组件对象模型(COM)来访问各种数据源的 ActiveX 的通用接口。

OLE DB 可以连接数据库,也可以是文本文件、Excel 表格等各种不同格式的数据存储。

OLE DB 的结构

OLE DB 中包括了消费者和提供者。

  1. 消费者:利用 OLE DB 提供的接口访问数据库数据的客户端应用程序或其他工具。

  2. 提供者:提供者是一个由 COM 组件构成的数据访问中介,位于数据库和消费者之间。

    • 服务提供者。这类提供者自身没有数据,它通过 OLE DB 接口封装服务,从下层获取数据并向上层提供数据,具有提供者和消费者双重身份。
    • 数据提供者。数据提供者自己拥有数据并通过接口形成表格形式的数据。

    未命名文件

  3. OLE DB 编程模型

    • 数据库管理任务必须由消费者访问数据,由提供者发布数据。

    • OLE DB 编程模型分类:

      • Rowset 编程模型:假定数据源中的数据比较规范,提供者以行集形式发布数据。
      • Binder 编程模型:提供者不提供标准表格式数据,OLE DB 采用 Binder 编程模型将 URL 和一个 OLE DB 对象相关联或绑定,并在必要时创建层次结构对象。

JDBC 编程

JDBC 是 Java 制定的数据库连接技术的简称、在应用程序中与 ODBC 类似,是 Java 实现数据库访问的应用程序编程接口。

  1. JDBC 编程是面向对象的接口标准,一般由具体数据库厂商提供。
  2. JDBC 编程与 ODBC 类似,为 Java 提供统一、无缝地操作各种数据库的接口。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇