亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > PostgreSQL > 正文

PostgreSQL7.0手冊-接口-52. ecpg - 在 C 里嵌入 SQL

2019-09-08 23:34:15
字體:
來源:轉載
供稿:網友
第五十二章. ecpg - 在 C 里嵌入 SQL
內容 
為什么要嵌入 SQL? 
概念 
如何使用 ecpg 
局限 
從其他 RDBMS 移植 
安裝 
寄語開發者 
這里描寫 Postgres 里在 C 軟件包里嵌入 SQL.這部分是由 Linus Tolke?。ㄗg注:是不是叫 Linus 的都是計算機天才?)和 Michael Meskes 寫的. 
注意:你可以象 PostgreSQL 其他部分那樣拷貝和使用這些內容.
為什么要嵌入 SQL?
嵌入使用 SQL 比其他操作 SQL 查詢的方法有一些小小的優勢.它關心所有你的C 程序里面變量信息的往返.許多 RDBMS 軟件包支持這種嵌入的語言. 
有一個 ANSI 的標準描述嵌入的語言應該怎樣工作.ecpg 被設計成盡可能地符合這個標準.因此這就有可能把為其他 RDBMS 軟件包書寫的嵌入式 SQL 程序移植到 Postgres 上來并因此而推動自由軟件的精神的發展.

--------------------------------------------------------------------------------

概念
你在你的 C 程序里面用一些特殊的 SQL 東西來編寫程序.對于定義可以在 SQL 語句里面使用的變量,你需要把它們放到一個特殊的定義段里面.你用一些特殊的語法來表達 SQL 查詢. 
在編譯之前,你用嵌入的 SQLC 預編譯器對你的文件進行預處理,由這個預編譯器把你使用的 SQL 語句轉換成把變量作為參數的函數調用.不管是作為輸入到 SQL 語句里面的變量還是將包含返回結果的變量都被傳到函數調用里. 

然后你編譯你的程序,在鏈接時,你的程序會與一個包含所用函數的特殊的庫鏈接.這些函數(實際上大多是一個單一的函數)從參數里取得信息,用通常的方法(libpq)執行 SQL 查詢并且把結果放回到聲明為輸出的參數里. 

這樣你運行你的程序時當控制到達 SQL 語句時,SQL 語句對數據庫進行操作因而你可以對結果進行繼續處理.


--------------------------------------------------------------------------------  
--------------------------------------------------------------------------------

如何使用 ecpg
本節討論如何使用 ecpg 工具. 
預編譯器
預編譯器叫 ecpg.在安裝過后它存放在 Postgres bin/ 目錄下面.

ecpg 庫叫做 libecpg.a 或 libecpg.so.另外,該庫用了 libpq 庫與 Postgres 服務器通訊,所以你要將你的程序與這兩個庫鏈接: -lecpg -lpq. 
庫里面有一些方法是"隱藏"的,但是有時候這些方法可能提供非常有用的信息. 

ECPGdebug(int on, FILE *stream) 如果第一個參數不為零則打開調試信息.調試信息記錄在 stream. 大多數 SQL 語句把它的參數和結果記錄日志. 
最重要的一個 (ECPGdo)(函數)記錄它的所有展開的字符串,也就是說,帶有插入的所有變量的字符串和從Postgres 服務器來的結果.這個對搜索你的 SQL 語句的錯誤是非常有用的. 

ECPGstatus() 這個方法/函數在我們與一個數據庫聯接后返回 TRUE 并且如果沒有聯接返回 FALSE?。?

錯誤控制
要想檢測從 Postgres 服務器來得錯誤,你要包含如下一行 
      exec sql include sqlca;
到你的文件的包含段里.這樣做將會定義一個結構和一個象下面一樣名為 sqlca 的變量: 
struct sqlca
{
 char sqlcaid[8];
 long sqlabc;
 long sqlcode;
 struct
 {
  int sqlerrml;
  char sqlerrmc[70];
 } sqlerrm;
 char sqlerrp[8];
 long sqlerrd[6];
 /* 0: empty                                         */
 /* 1: OID of processed tuple if applicable          */
 /* 2: number of rows processed in an INSERT, UPDATE */
 /*    or DELETE statement                           */
 /* 3: empty                                         */
 /* 4: empty                                         */
 /* 5: empty                                         */
 char sqlwarn[8];
 /* 0: set to 'W' if at least one other is 'W'       */
 /* 1: if 'W' at least one character string          */
 /*    value was truncated when it was               */
 /*    stored into a host variable.                  */
 /* 2: empty                                         */
 /* 3: empty                                         */
 /* 4: empty                                         */
 /* 5: empty                                         */
 /* 6: empty                                         */
 /* 7: empty                                         */
 char sqlext[8];
} sqlca;
如果最后一個SQL 語句發生了錯誤,那么 sqlca.sqlcode 將是非零值.如果 sqlca.sqlcode 小于 0 那么就是發生了某種嚴重的錯誤,象數據庫定義與查詢定義不一致等.如果大于 0 則是通常的錯誤,象表不包括所要求的行等. 
sqlca.sqlerrm.sqlerrmc 將包含一個字符串描述該錯誤.該字符串以源文件的行號結尾?!?

可能發生的錯誤列表: 
  
-12, Out of memory in line %d. 
通常不出現這個錯誤。這是你的虛擬內存耗盡的標志?!?
-200, Unsupported type %s on line %d. 
通常不出現這個錯誤.這表明預編譯器生成了一些庫(函數)不認得的東西.可能你運行的預編譯器和當前庫不兼容. 
-201, Too many arguments line %d. 
這意味著 Postgres 返回了比我們的匹配變量更多的參數.可能你漏了幾個INTO :var1,:var2-列表里的宿主變量. 
-202, Too few arguments line %d. 
這意味著 Postgres 返回了比我們的對應宿主變量要少的參數.可能你多輸入了幾個INTO :var1,:var2-列表里的宿主變量. 
-203, Too many matches line %d. 
這意味著查詢返回了多個行,但你聲明的變量不是數組.你執行的 SELECT 可能不是唯一的. 
-204, Not correctly formatted int type: %s line %d. 
這意味著宿主變量是一個 int 類型并且 Postgres 數據庫里的字段是另一種類型,包含著一個不能轉換成一個 int 類型的數值.庫(函數)使用 strtol 做此類轉換. 
-205, Not correctly formatted unsigned type: %s line %d. 
這意味著宿主變量是一個 unsigned int(無符號整數)類型而Postgres 數據庫里的字段是另外一種類型并且包含一個不能轉換成unsigned int 的數值.庫(函數)使用 strtoul 做這類轉換. 
-206, Not correctly formatted floating point type: %s line %d. 
這意味著宿主變量是一個 float?。ǜ↑c)類型而 Postgres 數據庫里的字段是另外一種類型并且包含一個不能轉換成float 的數值.庫(函數)使用 strtod 做這類轉換. 
-207, Unable to convert %s to bool on line %d. 
這意味著宿主變量是一個 bool?。ú紶枺╊愋?,而 Postgres 數據庫里的字段值既不是 't' 也不是 'f'?!?
-208, Empty query line %d. 
Postgres 返回 PGRES_EMPTY_QUERY,可能的原因是該查詢實際上是空的?!?
-220, No such connection %s in line %d. 
程序試圖訪問一個不存在的聯接。 
-221, Not connected in line %d. 
程序試圖訪問一個存在的,但是沒有打開的聯接?!?
-230, Invalid statement name %s in line %d. 
你試圖使用的語句還沒準備好?!?
-400, Postgres error: %s line %d. 
某種 Postgres 錯誤。該消息包含來自 Postgres 后端的信息。 
-401, Error in transaction processing line %d. 
Postgres 給我們的信號,表明我們無法開始,提交或者回卷該事務?!?
-402, connect: could not open database %s. 
與數據庫的聯接無法工作?!?
100, Data not found line %d. 
這是一個"正常的"錯誤,告訴你你正在查詢的東西找不到或者我們已經越過了游標的范圍?!?

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

局限
一些永遠不會包括進來的東西以及用這個概念為什么或什么東西是沒法做到的. 
  
Oracle 的單任務能力?。╯ingle tasking possibility) 
  
  

Oracle 在 AIX 3 上的版本 7.0 利用了 OS 支持的在共享內存段上的鎖技術并且允許應用設計者用一種所謂的單任務方式鏈接一個應用.這時的體系結構就不是每個應用進程對應一個客戶端進程,而是數據庫部分和應用部分都在同一個進程上跑.在 oracle 的后期版本上這個特性不再被支持. 

這需要對Postgres 的訪問模式進行完全重新設計而且這些努力與獲得的性能提高不相稱.


--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

從其他 RDBMS 軟件包移植
ecpg 的設計遵循 SQL 標準。所以從一個標準的 RDBMS 移植(應用)應該不是問題。糟糕的是現實世界里并沒有所謂的標準的 RDBMS。所以 ecpg 同樣試圖去理解那些與標準不沖突的語法擴展?!?
下面的列表顯示了所有以知的不兼容的地方。如果你發現一個沒有列出來的不兼容點,請告之 Michael Meskes。不過要注意的是,我們只是列出那些其他 RDBMS 的預編譯器和 ecpg 不兼容的東西,而沒有列出ecpg 里有而其他 RDBMS 沒有的特性?!?

FETCH 命令的語法 
標準的 FETCH 命令的語法是: 
  
  

FETCH [direction] [amount] IN|FROM cursor name. 

不過,ORACLE 并不使用關鍵字 IN 和/或 FROM。我們沒有辦法增加這個特性,因為那樣會導致分析沖突。


--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

安裝
自版本 0.5 起 ecpg 就和 Postgres 一起發布.所以缺省安裝時你就可以得到編譯好并且安裝好了的預編譯器, 庫和頭文件.

--------------------------------------------------------------------------------  
--------------------------------------------------------------------------------

寄語開發者
本節是寫給那些希望開發 ecpg 接口的人的.這里描述了這些接口是怎樣工作的.本節的目的是給那些想認識一些內部機制的人提供一些信息,而"如何使用"那一章應該描述了所有通常的問題.所以,在深入 ecpg 內部之前請先讀一下本節.如果你對 ecpg 如何工作不感興趣,請略過本節. 
ToDo 列表
這個版本的預編譯器有一些缺陷: 
  
庫函數 
to_date 等不存在。不過 Postgres 本身有一些很好的轉換過程。所以你可能不會想要這些(函數)?!?
  
結構和聯合 
結構和聯合必須在定義段里定義。 
缺失的語句 
下面的語句到目前為止還沒有實現: 
exec sql allocate 
exec sql deallocate 
SQLSTATE 
 
信息 'no data found' 
一個 exec sql insert select from 語句的 "no data" 錯誤信息應該是 100。 
sqlwarn[6] 
如果一個 SET DESCRIPTOR 語句里聲明的 PRECISION 或 SCALE 值被忽略,sqlwarn[6] 應該是 'W'. 
 
預編譯器
首先寫到輸出的四行是 ecpg 的一貫做法.這些是兩行注釋和兩行用于庫接口必須的包含行. 
然后預編譯器對文件處理一遍,一邊讀輸入文件,一邊輸出到輸出文件.通常它只是把不加分析的把所有東西輸出到輸出文件里去. 

當處理到 EXEC SQL 語句時,預編譯器對之進行處理并根據語句做相應的改變.EXEC SQL 語句可以是下列之一: 

定義段 
  
  

定義段以 

exec sql begin declare section;
開頭,以 
exec sql end declare section;
結束.在定義段里只允許變量定義.這個段里定義的每個變量同時也放到一個以變量名和對應類型為索引的變量列表里頭. 
特別是結構(struct)或者聯合(union)的定義同樣必須在定義段里面列出。否則ecpg 就不能處理這些類型,因為它不知道定義(是什么)?!?

定義同時也輸出到文件里把這些變量作為通常的 C-變量. 

特殊的類型 VARCHAR 和 VARCHAR2 的每個變量都被轉換成一個命名結構.一個下面這樣的定義: 
  

VARCHAR var[180];
被轉換成 
struct varchar_var { int len; char arr[180]; } var;
包含語句 
  
  

一個包含語句看起來象: 

exec sql include filename;
注意這個與下面這行 
#include 
是不一樣的。被包含的文件由 ecpg 本身分析。因此聲明的頭文件被包括在生成的 C 代碼里。這樣你也能夠在一個頭文件里聲明 EXEC SQL 語句?!?
聯接語句 
  
  

一個聯接語句看起來象: 

exec sql connect to connection target;
它創建與指定數據庫的聯接?!?
connection target (聯接目標)可以用下面的方法聲明: 
  

dbname[@server][:port][as connection name][user user name] 
tcp:postgresql://server[:port][/dbname][as connection name][user user name] 
unix:postgresql://server[:port][/dbname][as connection name][user user name] 
character variable[as connection name][user user name] 
character string[as connection name][user] 
default 
user 
 
也有不同的方法聲明用戶名: 
userid 
userid/password 
userid identified by password 
userid using password 
 
最后的 userid 和 password。每個都可以是一個文本常量,一個字符變量或者一個字符串?!?
  
斷開語句 
  
  
  
  
  
  
  
  

一個斷開語句看起來象: 

exec sql disconnect [connection target];
它關閉與指定數據庫的聯接?!?
connection target 可以用下面方法聲明: 

connection name 
default 
current 
all 
 
打開游標語句 
  
  
  
  
  
  
  
  

一個打開游標語句看起來象: 

exec sql open cursor;
它被忽略因而不拷貝到輸出文件. 
提交語句 
  
  
  
  
  
  

一個提交語句看起來象 

exec sql commit;
它被轉換成輸出 
ECPGcommit(__LINE__);
回卷語句 
  
  
  
  
  
  

一個回卷語句看起來象 

exec sql rollback;
它被轉換成如下輸出 
ECPGrollback(__LINE__);
其他語句 
  
其他 SQL 語句是其他以 exec sql 開頭并且以 ; 結尾的語句.所有兩者之間的東西都被認為是一個 SQL 語句并做變量替換分析. 
  
  
  
  
  
  

當一個符號以冒號(:)開頭時,就會發生變量替換.然后就會到前面定義段里(生成)的變量列表里找出該名稱的變量,然后根據該變量是用于輸入還是輸出,把指向該變量的指針寫到輸出里供函數訪問使用. 

對 SQL 請求里的每個變量,函數都得到另外十個參數: 
   
 作為特殊符號的類型?!?
指向數值或指針的指針?!?
如果變量是 varchar 或者 char,變量的尺寸。 
數組里的元素個數(對數組抓?。!?
數組里下一個元素的偏移量(對數組抓?。?
做為特殊符號的標識器變量的類型?!?
一個指向標識器變量值或者標識器變量指針的指針。 
0. 
標識器數組里的元素個數(對數組抓?。!?
標識器數組里下一個元素的偏移量(對數組抓取)?!?


一個完整的例子
下面是一個完整的描述預編譯器對文件 foo.pgc 的輸出的例子: 
exec sql begin declare section;
int index;
int result;
exec sql end declare section;
...
exec sql select res into :result from mytable where index = :index;
被解釋成: 
/* Processed by ecpg (2.6.0) */
/* These two include files are added by the preprocessor */
#include ;
#include ;

/* exec sql begin declare section */

#line 1 "foo.pgc"

 int index;
 int result;
/* exec sql end declare section */
...
ECPGdo(__LINE__, NULL, "select  res  from mytable where index = ?     ",
        ECPGt_int,&(index),1L,1L,sizeof(int),
        ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
        ECPGt_int,&(result),1L,1L,sizeof(int),
        ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 147 "foo.pgc"


(本手冊里的縮進是為可讀性追加的,可不是預編譯器能干的事.) 

在庫里面最重要的函數是 ECPGdo 函數.它有可變的參數.希望我們不會碰到那些對變參數個數的函數的參數個數有限制的機器.這些參數個數很容易多達 50 個. 
這些參數是: 
  
一個行號 
這是一個只用于錯誤信息里的表明原始出錯行的行號. 
一個字符串 
這是聲明的 SQL 請求。這個請求將用輸入變量修改,也就是說用那些編譯時未知但要輸入到請求里的變量修改.這里變量應該包含 “;” 放到字符串里. 
輸入變量 
象預編譯器節里描述的那樣,每個輸入變量換成十個參數. 
ECPGt_EOIT 
一個 enum (枚舉)表明輸入變量(列表)的結尾. 
輸出變量 
象預編譯器節里描述的那樣,每個輸入變量換成十個參數.這些變量將由函數填充. 
ECPGt_EORT 
一個 enum?。杜e)表明變量(列表)的結尾. 
所有 SQL 語句都在一次事務中執行,除非你進行了一次事務提交(commit).要獲取這樣的自動事務,第一個語句和/或事務提交或回卷后的第一個(語句)總是打開一個事務.要關閉這個缺省的特性,可以在命令行上使用 '-t' 選項?!?
待續:描述其他入口的位置.


-------------------------------------------------------------------------------
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩精品免费观看| 国产精品视频不卡| 国产精品嫩草影院久久久| 久久人人爽人人| 亚洲伊人一本大道中文字幕| 日韩黄色av网站| 55夜色66夜色国产精品视频| 亚洲第一区在线| 日韩欧美高清视频| 亚洲成人激情小说| 精品久久久精品| 96pao国产成视频永久免费| 国产亚洲精品久久久久久牛牛| 91大神福利视频在线| 免费成人高清视频| 日韩中文字幕在线视频| 亚洲欧美精品中文字幕在线| 九九精品在线视频| 伊人久久精品视频| 日韩美女免费观看| 久久99国产精品久久久久久久久| 91精品视频免费看| 国产精品啪视频| 91亚洲精品在线| 91视频8mav| 亚洲国产成人精品女人久久久| 中文字幕免费精品一区| 成人精品视频在线| 91免费版网站入口| 中文字幕视频在线免费欧美日韩综合在线看| 亚洲精品视频久久| 欧美丰满老妇厨房牲生活| 精品在线欧美视频| 日韩视频免费中文字幕| 色综合视频一区中文字幕| 欧美性感美女h网站在线观看免费| www.美女亚洲精品| 国产美女久久精品| 亚洲男人av在线| 欧美成人激情图片网| 精品日本美女福利在线观看| 一本色道久久综合亚洲精品小说| 欧美一级高清免费| 久操成人在线视频| 日韩女优人人人人射在线视频| 国产精品极品在线| 久久久之久亚州精品露出| 国产精品日韩久久久久| 成人免费看吃奶视频网站| 日韩电影中文字幕av| 欧美日韩一区二区免费视频| 久久精品美女视频网站| 国产精品jvid在线观看蜜臀| 91免费国产视频| 色久欧美在线视频观看| 欧美国产日韩xxxxx| 国产视频丨精品|在线观看| 亚洲三级黄色在线观看| 日韩美女av在线免费观看| 精品久久久久久久久国产字幕| 中文字幕日韩欧美在线| 色综合天天狠天天透天天伊人| 成人免费网视频| 欧美洲成人男女午夜视频| 精品国产一区二区三区久久狼5月| 国产精品美女午夜av| 久久久亚洲精品视频| 欧美裸体xxxx| 日本aⅴ大伊香蕉精品视频| 国产成人a亚洲精品| 欧美日韩第一视频| 久久理论片午夜琪琪电影网| 日韩中文字幕在线精品| 日韩欧美大尺度| 欧美日韩国产色| 丝袜亚洲另类欧美重口| 97热精品视频官网| 国产精品久久久久影院日本| 综合久久五月天| 欧美精品日韩www.p站| 国产小视频国产精品| 91亚洲精品视频| 国产精品免费久久久| 国产精品夜间视频香蕉| 欧美高清第一页| 亚洲精品在线不卡| 亚洲аv电影天堂网| 在线不卡国产精品| 国产精品视频地址| 自拍偷拍亚洲精品| 欧美激情精品久久久久久大尺度| 中文字幕一精品亚洲无线一区| 亚洲精品自拍偷拍| 亚洲色图欧美制服丝袜另类第一页| 国产成人精品在线视频| 欧美另类69精品久久久久9999| 91超碰caoporn97人人| 91精品国产色综合久久不卡98口| 欧美激情一级精品国产| 亚洲福利在线视频| 亚洲国产精久久久久久久| 欧美中文字幕在线观看| 精品中文视频在线| 国产精品美女免费| 亚洲国产成人爱av在线播放| 91中文在线观看| 91极品视频在线| 亚洲人成在线播放| 亚洲视频视频在线| 色无极亚洲影院| 亚洲女人天堂成人av在线| 91久久精品在线| 精品国产一区二区三区久久狼黑人| 91免费电影网站| 欧美一区二三区| 一区二区av在线| 精品人伦一区二区三区蜜桃免费| 亚洲欧美国产精品久久久久久久| 欧美精品一本久久男人的天堂| 精品日本高清在线播放| 国产91色在线| 久久综合色影院| 久久免费视频在线观看| 亚洲自拍偷拍一区| 奇米4444一区二区三区| 日韩美女写真福利在线观看| 亚洲香蕉伊综合在人在线视看| 欧美日韩xxxxx| 中文字幕免费精品一区高清| 日韩av色综合| 亚洲日本aⅴ片在线观看香蕉| 欧美高清理论片| 久久理论片午夜琪琪电影网| 91av在线精品| 久久久久免费视频| 亚洲欧洲国产精品| 久久精品视频导航| 992tv成人免费影院| 中文字幕无线精品亚洲乱码一区| 亚洲国语精品自产拍在线观看| 欧美三级欧美成人高清www| 日韩中文字幕网站| 成人福利视频网| 亚洲精品在线视频| 色哟哟亚洲精品一区二区| 亚洲xxxx妇黄裸体| 欧美激情视频网站| 亚洲视频电影图片偷拍一区| 国产一区二区三区在线视频| 在线a欧美视频| 欧美性在线视频| 亚洲色图偷窥自拍| 一区二区在线视频| 亚洲社区在线观看| 午夜精品99久久免费| 伊人一区二区三区久久精品| 国产91av在线| 久久999免费视频| 亚洲在线视频观看| 亚洲欧美制服丝袜| 日韩成人高清在线| 国产成人精品在线播放| 精品国产一区二区三区久久狼5月| 91九色精品视频|