嵌入式SQL(英文: Embedded SQL)是一种将SQL语句直接写入C语言COBOLFORTRANAda编程语言源代码中的方法。藉此方法,可使得应用程式能夠存取以及處理資料。在这一方法中,将SQL文嵌入的目标源码的语言称为宿主语言

在1986年发布的SQL86标准中定义了对于COBOL、FORTRAN及PI/L等语言的嵌入式SQL的规范。在1989年发布的SQL89规范中,定义了对于C语言的嵌入式SQL的规范。一些大型的数据库厂商发布的数据库产品中,都提供了对于嵌入式SQL的支持。比如OracleDB2等。

嵌入式SQL的工作原理

编辑

提供对于嵌入式SQL的支持,需要数据库厂商除了提供DBMS之外,还必须提供一些工具。为了实现对于嵌入式SQL的支持,技术上必须解决以下4个问题[1]

  1. 宿主语言的编译器不可能识别和接受SQL文,需要解决如何将SQL的宿主语言源代码编译成可执行码。
  2. 宿主语言的应用程序如何与DBMS之间传递数据和消息。
  3. 如何把对数据的查询结果逐次赋值给宿主语言程序中的变量以供其处理。
  4. 数据库的数据类型与宿主语言的数据类型有时不完全对应或等价,如何解决必要的数据类型转换问题。
 
嵌入式SQL源码的处理流程

为了解决上述这些问题,数据库厂商需要提供一个嵌入式SQL的预编译器,把包含有嵌入式SQL文的宿主语言源码转换成纯宿主语言的代码。这样一来,源码即可使用宿主语言对应的编译器进行编译。通常情况下,经过嵌入式SQL的预编译之后,原有的嵌入式SQL会被转换成一系列函数调用。因此,数据库厂商还需要提供一些列函数库,以确保链接器能够把代码中的函数调用与对应的实现链接起来。

嵌入式SQL的扩展语法

编辑

嵌入式SQL中除了可以执行标准SQL文之外,为了对应嵌入的需要,还增加了一些额外的语法成分。主要包含以下内容:

  • 宿主变量使用声明的语法
  • 数据库访问的语法
  • 事务控制的语法
  • 游标操作的语法

示例代码

编辑

以下展示了用于连接PostgreSQL数据库并执行一次数据查询的嵌入式SQL源码(宿主语言为C语言):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

EXEC SQL BEGIN DECLARE SECTION;
int var_c1;
char var_c2[21] = { 0x00 };
EXEC SQL END DECLARE SECTION;

int main(int argc, char* argv[])
{
    /* 步骤1: 建立连接 */
    EXEC SQL WHENEVER SQLERROR SQLPRINT;   /* 声明异常发生时的处理动作统一为打印消息 */
    EXEC SQL CONNECT TO postgres@localhost:5432 USER postgres/xxxx;   /* 指定连接的目标数据库,用户名,密码 */  
     
    /* 步骤2: 利用游标执行查询 */
    EXEC SQL DECLARE foo_bar CURSOR FOR SELECT c1, c2 FROM tb1;    /* 声明一个游标使之用于执行SELECT文 */
    EXEC SQL OPEN foo_bar;                                         /* 打开游标从而使SELECT文被执行 */
    EXEC SQL FETCH foo_bar INTO :var_c1, :var_c2;                  /* 获取一行数据 */
    
    printf("C1: %d, C2: %s\n", var_c1, var_c2);
 
    EXEC SQL CLOSE foo_bar;                                        /* 关闭所打开的游标 */

    /* 步骤3: 关闭连接 */
    EXEC SQL DISCONNECT CURRENT;                   

    return 0;
}


Cygwin平台上,利用PostgreSQL 7.4.5所自带的嵌入式SQL的预编译器ECPG(版本号 3.1.1)进行预编译,生成的纯C语言代码如下所示:

/* Processed by ecpg (3.1.1) */
/* These include files are added by the preprocessor */
#include <ecpgtype.h>
#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
#line 1 "ESQL_CONNECT.pgc"
/* End of automatic include section */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* exec sql begin declare section */

#line 6 "ESQL_CONNECT.pgc"
 int  var_c1   ;
 
#line 7 "ESQL_CONNECT.pgc"
 char  var_c2 [ 21 ]  = { 0x00 } ;
/* exec sql end declare section */
#line 8 "ESQL_CONNECT.pgc"

int main(int argc, char* argv[])
{
    /* 步骤1: 建立连接 */
    /* exec sql whenever sqlerror  sqlprint ; */

#line 13 "ESQL_CONNECT.pgc"
 
    { ECPGconnect(__LINE__, 0, "postgres@localhost:5432" , "postgres" , "asdf1234" , NULL, 0); 
#line 14 "ESQL_CONNECT.pgc"

if (sqlca.sqlcode < 0) sqlprint();}
#line 14 "ESQL_CONNECT.pgc"    
    /* 步骤2: 利用游标执行查询 */
    /* declare foo_bar  cursor  for select  c1  , c2   from tb1    */
#line 17 "ESQL_CONNECT.pgc"

    { ECPGdo(__LINE__, 0, 1, NULL, "declare foo_bar  cursor  for select  c1  , c2   from tb1   ", ECPGt_EOIT, ECPGt_EORT);
#line 18 "ESQL_CONNECT.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 18 "ESQL_CONNECT.pgc"

    { ECPGdo(__LINE__, 0, 1, NULL, "fetch foo_bar", ECPGt_EOIT, 
    ECPGt_int,&(var_c1),(long)1,(long)1,sizeof(int), 
    ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
    ECPGt_char,(var_c2),(long)21,(long)1,21*sizeof(char), 
    ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 19 "ESQL_CONNECT.pgc"

if (sqlca.sqlcode < 0) sqlprint();}
#line 19 "ESQL_CONNECT.pgc"

    printf("C1: %d, C2: %s\n", var_c1, var_c2);
 
    { ECPGdo(__LINE__, 0, 1, NULL, "close foo_bar", ECPGt_EOIT, ECPGt_EORT);
#line 23 "ESQL_CONNECT.pgc"

if (sqlca.sqlcode < 0) sqlprint();}
#line 23 "ESQL_CONNECT.pgc"


    /* 步骤3: 关闭连接 */
    { ECPGdisconnect(__LINE__, "CURRENT");
#line 26 "ESQL_CONNECT.pgc"

if (sqlca.sqlcode < 0) sqlprint();}
#line 26 "ESQL_CONNECT.pgc"
    return 0;
}


生成后的代码中所调用的ECPGconnect等函数,由安装PostgreSQL所自带的ECPG(本例中为libecpg.so)提供具体的实现,供链接器将其与上述C语言代码编译生成的目标文件进行链接。

支持嵌入式SQL的数据库产品

编辑

以下列出支持嵌入式SQL的数据库产品以及各自支持的宿主语言

Oracle Database

编辑
Ada
Pro*Ada在Oracle 7.3的版本中被加入产品族,并且在Oracle 8中被替换为SQL*Module。但在此之后就一直没有更新[2]。SQL*Module支持Ada 83.
C/C++
Pro*C 在Oracle 8 时被替换成了Pro*C/C++。之后Pro*C/C++ 到Oracle Database 11g仍都在被支持。
COBOL
Pro*COBOL到Oracle Database 11g仍都在被支持。
Fortran
Pro*FORTRAN 在Oracle 8之后的Oracle版本中就不再被更新,但Bug修正仍在维护中[3]
Pascal
Pro*Pascal在Oracle 8之后的Oracle版本中就不再被更新[3]
PI/L
Pro*PL/I 自Oracle 8之后就不再被更新,但文档中仍然有记述[3]

IBM DB2

编辑

IBM DB2的版本9中提供了对于C/C++,COBOL,Java等宿主语言的嵌入式SQL的支持。

PostgreSQL

编辑
C/C++
PostgreSQL 自版本6.3起就提供了对于C/C++的嵌入式SQL的支持,以ECPG组件的形式存在。

参见

编辑

注释

编辑
  1. ^ 王能斌. 《数据库系统教程(上册)》. 电子工业出版社. 2002年8月: 77页. ISBN 7-5053-7827-9. 
  2. ^ Ada Support in Version 8. Oracle9i Database Migration, Release 2 (9.2), Chapter 5. Compatibility and Interoperability. Oracle. [2008-07-14]. (原始内容存档于2010-05-05). 
  3. ^ 3.0 3.1 3.2 Language Alternatives. Pro*COBOL Precompiler Programmer's Guide, Release 8.0, Chapter 1. Introduction. Oracle. [2008-07-14]. (原始内容存档于2010-03-04). 

📚 Artikel Terkait di Wikipedia

AmigaOS

4.0-4.1)开发。而进来的发行的 AmigaOS 4 则要求使用PowerPC微处理器。 AmigaOS 基于名为Exec (Amiga)(英语:Exec)的抢占式多任务处理内核。此内核包含一组抽象的 Amiga 的硬件,一个名为 AmigaDOS 的磁盘操作系统,一个名为 Intuition

台灣地理

Exec. Yuan (2014),第43頁. Reported by Taiwan's National Geographic Information System Steering Committee (NGISSC 互联网档案馆的存檔,存档日期21 November 2008.) Exec.

Google

2008-03-04 [2011-07-17]. (原始内容存档于2008-03-09).  Moritz, Scott. Top Google exec jumps to Facebook. Fortune. 2008-03-04 [2011-07-17]. (原始内容存档于2008-04-13)

夏威夷州州长列表

1984,第105-106頁. U.S. Senate Exec. Journal. 56th Cong., 1st sess., 4 May 1900, 481 (页面存档备份,存于互联网档案馆). Accessed February 21, 2023. U.S. Senate Exec. Journal. 56th Cong

Bash

生成标准输出(文件描述符1)的拷贝文件描述符6 exec 6>&1 # 打开文件"test.data"以供写入 exec 1>test.data # 产生一些内容 echo "data:data:data" # 关闭文件"test.data" exec 1>&- # 使标准输出指向FD 6(重置标准输出) exec 1>&6 # 关闭FD6

O2 (电信品牌)

O2 Xda O2 Xda II O2 Xda IIi O2 Xda III O2 Xda IIs O2 Xda Neo O2 Xda Exec O2 Xda Orbit O2 Xda Nova O2 Xda Star O2 Xda Diamond O2 Xda Trion O2 Xda Stellar

Pkg-config

这是一个用于 libpng 的 .pc 文件的样例: prefix=/usr/local exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${exec_prefix}/include Name: libpng Description:

Kexec

kexec(kernel execution,类似于Unix或Linux的系统调用exec(英语:Exec_(system_call)))是Linux内核的一种机制,它允许从当前运行的内核启动新内核。kexec会跳过由系统固件(BIOS或UEFI)执行的引导加载程序阶段和硬件初始化阶段,直接将新内核