Linux上 的 资 料 库 软 体 -- Postgres95安 装 与 应 用 (PostgreSQL Ver 6.0)



本 文 作 者 / 周 树 禾


什 麽 是 Postgres95 ??近 来 Web Server与 资 料 库 结 合 已 成 为 一 种 必 然 的 趋 势 了 , 个 个 作 业 系 统 上 的 资 料 库 软 体 顿 时 也 跟 着 热 门 了 起 来 , 例 如 一 般 常 见 的 网 路 搜 寻 引 擎 , 与 许 多 公 司 的 大 量 的 资 料 皆 想 上 网 , 甚 至 是 最 近 常 听 到 的 Intranet等 等 , 无 所 不 与 资 料 库 相 关 , 反 观 Linux上 其 实 早 在 多 年 前 已 有 许 多 能 够 透 过 网 路 来 存 取 的 资 料 库 软 体 , Postgres95就 是 其 中 之 一 。 若 是 简 单 地 说 , Postgres95 其 实 是 一 套 「 资 料 库 管 理 系 统 」 ( DataBase Management Systems, 一 般 称 做 DBMS) , 使 用 者 可 以 藉 由 SQL命 令 透 过 它 来 存 取 资 料 库 的 资 料 , 不 但 功 能 强 大 而 且 还 是 免 费 的 资 料 库 软 体 , 目 前 最 新 版 本 已 改 名 为 PostgreSQL v6.0。

Postgres95安 装 与 应 用

背 景 历 史 与 现 况

Postgres95所 使 用 的 资 料 库 称 为 Postgres, 实 际 上 正 是 Postgres95正 是 由 Postgres最 终 正 式 版 ( Ver 4.2) 演 变 而 来 的 , 而 Postgres DBMS早 在 1986年 就 开 始 发 展 了 , 其 中 经 过 了 许 多 次 的 版 本 更 新 , 最 後 於 1994年 以 4.2版 为 最 最 终 版 本 结 束 。 这 些 年 间 Postgres的 应 用 包 括 许 多 研 究 与 产 品 , 包 括 了 财 务 分 析 系 统 , 医 药 资 讯 资 料 库 , 与 地 理 资 讯 系 统 等 各 类 资 料 库 的 应 用 . 此 外 还 曾 被 几 所 大 学 当 做 教 材 , 最 後 甚 至 由 Illustra Information Technologies以 其 为 基 础 发 行 了 商 业 版 的 资 料 库 软 体 。 谈 完 了 Postgres95的 前 身 後 , 我 们 就 来 了 解 一 下 目 前 的 Postgres95吧 !

Postgres95与 Postgres有 许 多 不 同 , 它 改 变 了 一 些 内 部 的 结 构 来 改 善 约 30%至 50%的 效 能 , 除 了 bug-fixes外 还 做 了 以 下 几 点 改 良 :

1.以 SQL来 代 替 原 本 的 POSTQUEL。

2.提 供 了 一 个 新 的 程 式 ( psql) 来 掌 控 资 料 库 ( 之 後 会 介 绍 ) 。

3.增 加 了 一 个 新 的 front-end libary( libpgtcl) , 来 支 援 Tcl-based client发 展 程 式 , 还 有 一 个 简 易 的 shell( pgtclsh) 可 让 使 用 者 以 Tcl commands 与 资 料 库 沟 通 。

4.由 支 援 BSD make改 成 GNU make, 所 以 Postgres95可 以 使 用 gcc来 编 绎 。

特 色 ● 是 一 种 关 联 式 的 资 料 库 。

● 具 有 高 度 的 延 展 性 , 能 让 使 用 者 自 定 运 算 元 , 各 类 型 态 , 函 数 与 存 取 的 方 式 。

● 支 援 多 种 语 言 API, 如 C,TCL,PERL,Python等 等 。

● 另 外 有 些 可 与 Postgres95 搭 配 使 用 的 Package 可 供 使 用 , 如 下 :

1) Wdb-p95 是 一 套 提 供 Web与 Postgres95之 间 沟 通 的 一 套 介 面 程 式 。

2) Japanese Kanji Code with Postgres95 可 让 你 的 Postgres95支 援 日 文 搜 寻 与 运 算 。

● 支 援 多 种 平 台 如 Linux, Alpha, BSD, NEXTSTEP等 等 。

基 本 安 装

在 前 几 期 我 们 曾 经 稍 微 介 绍 过 archie的 用 法 , 现 在 要 找 Postgres95也 是 只 要 利 用 archie搜 寻 一 下 postgres这 个 关 键 字 就 可 以 找 到 许 多 版 本 的 了 , 或 是 直 接 到 ftp://ftp.postgreSQL.org/pub/postgresql-v6.0.tar.gz抓 回 , 而 目 前 最 近 版 本 是 PostgreSQL 6.0, 抓 回 後 请 於 /usr/src中 建 立 一 pgsql目 录 , 并 将 此 档 移 至 此 目 录 中 再 tar xvzf postgres95-1.09.tar.gz解 开 , 解 开 之 後 我 们 就 要 开 始 做 compile的 动 作 了 , 步 骤 如 下 :

% cd src

% customize

以 下 为 customize画 面

Welcome to the PostgreSQL V6.0 cutomisation utility

. You may build PostgreSQL for one of the following systems

aix IBM on AIX 3.2.5

alpha DEC Alpha AXP on OSF/1 2.0

BSD44_derived OSs derived from 4.4-lite BSD ( NetBSD, FreeBSD)

bsdi BSD/OS 2.0, 2.01, 2.1

dgux DG/UX 5.4R3.10

hpux HP PA-RISC on HP-UX 9.0

i386_solaris i386 Solaris

irix5 SGI MIPS on IRIX 5.3 or better

linux Intel x86 on Linux 1.2 and Linux ELF

nextstep Motorola MC68K or Intel x86 on NeXTSTEP 3.2

sparc_solaris SUN SPARC on Solaris 2.4

sunos4 SUN SPARC on SunOS 4.1.3

svr4 Intel x86 on Intel SVR4

ultrix4 DEC MIPS on Ultrix 4.4

Enter port name: linux

Is this an ELF system? ( y/n) [y]

Where do you wish to install Postgres [/usr/local/pgsql]?

Where are the IPCS utilities stored [/usr/bin]?

Compile C++ library? ( y/n) [n]

Compile Tcl utilities? ( y/n) [n]

Which BSD-compatible Install utility do you wish to use?

Under Irix the default will chown all your installed files

to root, so you are recommended to obtain ginstall

Enter program name: [system default] Where

Do you wish the psql program to use the GNU readline library? ( y/n) [n]

Specify C compiler: [cc] gcc

Specify any custom C compilation flags: [none]

You may choose to switch off assert checking. This will speed the

program up, but may miss some potentially fatal bugs!

Switch off assert checking ( y/n) [n]

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

若 您 跟 笔 者 一 样 是 C的 爱 好 者 , 基 本 上 只 需 要 输 入 Enter port name: linux与 Specify C compiler: [cc] gcc这 两 项 , 其 馀 按 enter以 内 定 值 即 可 。 再 来 您 可 以 先 试 着 下 make指 令 来 编 译 看 看 , 若 有 错 误 讯 息 请 先 查 看 doc目 录 中 的 FAQ-Linux 档 案 , 大 部 份 问 题 的 解 决 方 法 就 在 其 中 喔 ! 倘 若 都 有 无 法 解 决 的 问 题 发 生 时 , 请 将 Makefile.custom 删 除 , 再 修 改 Makfile.global中 的 PORTNAME= UNDEFINED改 成 PORTNAME=linux之 後 再 make试 试 看 ! 另 外 附 带 说 明 一 下 , 这 个 make的 动 作 若 在 P-133下 约 要 十 分 钟 的 时 间 , 大 家 可 以 先 继 续 看 下 一 段 。

整 体 架 构

以 上 大 略 介 绍 完 Postgres95 後 , 接 下 来 我 们 就 要 进 入 正 题 了 , 首 先 就 是 要 对 Postgres95的 整 体 运 作 架 构 有 一 番 基 本 的 认 识 , 之 後 我 们 才 能 尽 情 地 使 用 它 来 完 成 我 们 的 资 料 库 系 统 。

Postgres95设 计 是 一 种 “ process per-user” client/server model, 也 就 是 每 位 与 Postgres95 相 连 线 的 client端 使 用 者 皆 有 自 己 的 process於 Server端 执 行 , 直 到 离 线 後 process才 会 消 失 。 Server端 的 一 个 daemon程 式 叫 做 postmaster, 这 个 daemon会 依 照 /usr/local/pgsql/lib/pg_hba.conf.sample的 内 容 来 负 责 fork出 新 的 proccess来 与 新 的 连 线 沟 通 , 那 麽 我 们 该 如 何 写 出 可 以 和 postmaster沟 通 的 程 式 呢 ? 这 时 就 必 须 使 用 Postgres95提 供 的 一 套 LIBPQ的 library来 撰 写 程 式 了 。 ( 详 细 的 程 式 范 例 待 後 叙 ) 以 下 是 Postgres95基 本 运 作 的 示 意 图 :

Client Server

应 用 程 式 -$ LIBPQ < -------> postermaster

介 绍 完 了 程 式 运 作 的 过 程 後 , 该 来 说 明 一 下 Postgres95的 档 案 架 构 了 :

( 如 下 图 )

/usr/local/pgsql/

|----------- lib ( 建 立 资 料 库 时 会 使 用 到 的 一 些 预 设 设 定 档 )

|----------- bin ( 执 行 程 式 所 在 )

|----------- include ( LIBPQ library)

|----------- man ( man document)

|----------- data ( 实 际 存 放 资 料 库 目 录 )

以 上 data/pg_hba.conf是 一 个 设 网 路 存 取 资 料 库 权 限 的 设 定 档 案 , 可 修 改 其 中 内 容 来 防 止 其 他 人 来 存 取 您 的 某 些 资 料 库 , 修 改 方 式 请 参 阅 其 档 案 中 的 注 解 说 明 , 也 许 您 刚 开 始 还 没 有 data这 个 目 录 , 那 是 正 常 的 , 必 须 做 完 下 一 节 的 启 始 资 料 库 动 作 後 , 才 会 产 生 此 一 目 录 。

设 定 环 境 变 数 与 启 始 资 料 库 与postmaster

因 为 Postgres95程 式 无 法 以 root来 启 动 , 而 必 须 建 立 一 个 新 的 帐 号 来 做 为 Postgres95的 管 理 帐 号 , 以 下 笔 者 则 是 用 postgres为 此 一 帐 号 。 除 此 外 还 必 须 设 定 好 环 境 变 数 , 请 读 者 们 千 万 可 别 少 了 这 个 动 作 喔 ! 不 然 就 跟 笔 者 一 样 白 花 了 老 半 天 的 时 间 却 不 知 道 错 在 那 里 了 , 也 许 是 因 为 程 式 本 身 设 计 的 关 系 , 一 定 要 把 PATH设 定 好 後 , postmaster才 能 正 常 地 执 行 。 而 设 定 环 境 变 数 的 方 式 有 两 种 , 第 一 种 在 postgres这 个 管 理 帐 号 的 home directory中 建 立 一 .login的 档 案 , 档 案 内 容 是 set path=( /usr/local/pgsql/bin> path) 并 重 新 以 postgres来 login, 第 二 种 方 式 则 是 於 shell command下

% PATH=/usr/local/pgsql/bin:>PATH

% export PATH

如 此 便 完 成 了 环 境 变 数 的 设 定 了 。 再 来 我 们 就 是 该 做 启 始 资 料 库 的 动 作 了 , 不 过 首 先 请 确 定 /usr/local/pgsql目 录 中 的 所 有 档 案 与 目 录 的 owner是 否 为 postgres, 若 不 是 请 下

% cd /usr/local

% chown -R postgres /usr/local/pgsql

来 更 改 owner为 postgres, 更 改 完 後 才 开 始 下 面 指 令 以 启 始 资 料 库 ,

%initdb--pglib=/usr/local/pgsql/lib--pgdata=/usr/local/pgsql/dataupostgres

^^^^^^^^^^ 为 此 一 新 建 立 之 资 料 库 之 owner 帐 号 若 您 的 环 境 变 数 与 各 项 设 定 正 确 , 应 该 不 会 看 到 任 何 错 误 讯 息 , 此 时 程 式 正 在 帮 您 做 启 始 资 料 库 的 工 作 , 当 资 料 库 启 始 完 成 之 後 , 您 就 可 以 %postmaster-D/usr/local/pgsql/data> & pm.log & 来 启 动 您 的 postmaster daemon了 , 您 可 以 下 指 令 查 看 是 否 仍 在 执 行 , % ps aux|grep postmaster 或 是 cat pm.log看 看 是 否 有 错 误 讯 息 产 生 。

资 料 库 使 用 者 管 理

当 我 们 启 始 化 完 成 一 个 资 料 库 时 , 我 们 必 须 设 定 有 那 些 使 用 者 可 以 来 存 取 我 们 的 资 料 库 , 这 时 就 使 用 createuser指 令 来 新 增 一 个 资 料 库 的 使 用 者 , 范 例 如 下 :

% createuser

Enter name of user to add ---> skytree

Enter user’ s postgres ID or RETURN to use unix user ID: 0 ->

Is user “ skytree” allowed to create databases ( y/n) y

Is user “ skytree” allowed to add users? ( y/n) y

createuser: skytree was successfully added

资 料 库 语 言 -SQL

什 麽 是 SQL ?

为 了 一 些 不 曾 使 用 过 资 料 库 的 读 者 能 够 看 懂 接 下 来 的 内 容 , 笔 者 就 在 此 为 SQL做 一 番 简 单 的 介 绍 , SQL( Structured Query Language) 是 一 种 为 了 与 资 料 库 做 沟 通 所 设 计 的 一 种 查 询 语 言 ( 实 际 上 不 仅 有 查 询 功 能 而 已 ) , 这 套 语 言 有 很 简 单 的 语 法 与 格 式 , 使 用 者 可 以 用 SQL对 资 料 库 里 的 资 料 做 新 增 , 修 改 , 删 除 , 条 件 查 询 等 各 种 资 料 库 的 输 出 入 动 作 。

支 援 到 SQL的 版 本

Postgres95支 援 SQL-92( SQL的 一 种 标 准 ) , 但 是 缺 少 一 些 功 能 , 最 明 显 的 两 样 差 别 就 是 : 一 ) 不 支 援 巢 状 的 subquery 二 ) 在 GROUP BY 里 不 支 援 HAVING子 句 。

支 援 SQL 命 令 列 表

ABORT TRANSACTION, ALTER TABLE, BEGIN TRANSACTION,CHANGE ACL, CLOSE, COPY, CREATE AGGREGATE, CREATE DATABASE, CREATE FUNCTION, CREATE INDEX, CREATE OPERATOR, CREATE RULE, CREATE TABLE, CREATE TYPE, CREATE VERSION,CREATE VIEW, DECLARE, DELETE, DROP AGGREGATE, DROP DATABASE,DROP FUNCTION, DROP INDEX, DROP OPERATOR, DROP RULE, DROP TABLE, DROP TYPE, DROP VIEW, END TRANSACTION,EXTEND INDEX,FETCH, GRANT,INSERT, LOAD,PURGE, REVOKE,SELECT, UPDATE,VACUUM.

基 本 的 资 料 库 观 念

接 着 要 讲 的 是 关 於 一 些 资 料 库 的 基 本 观 念 , 好 几 年 都 没 变 过 的 观 念 , 大 略 的 架 构 如 下 图 所 示 :

/usr/local/pgsql/data

|

|-- database1

| |----- table1

| | |---- record1

| | | |----- field1

| | | |----- field2

| | | |----- etc.

| | |----- record2

| | |----- etc.

| |----- table2

| |----- etc.

|-- database2

|-- etc.

简 单 地 说 就 是 , 我 们 所 建 立 的 一 个 database 里 包 含 了 一 个 以 上 的 table, 而 table可 以 想 像 成 是 一 张 张 的 报 表 纪 录 , 这 张 报 表 实 际 上 是 由 许 多 笔 资 料 ( record) 所 构 成 的 , 而 每 一 笔 record可 能 会 包 含 了 一 个 以 上 的 资 料 栏 位 ( field) 。 建 立 你 的 第 一 个 database

好 不 容 易 看 到 这 , 先 休 息 一 下 喝 口 水 吧 ! 接 下 来 我 们 就 要 开 始 首 度 建 立 我 们 的 database 罗 !

% createdb mydb

建 立 好 後 并 不 会 有 什 麽 讯 息 回 应 , 接 下 来 我 们 下 指 令

% psql mydb

Welcome to the POSTGRESQL interactive sql monitor:

Please read the file COPYRIGHT for copyright terms of POSTGRESQL

type \? for help on slash commands

type \q to quit

type \g or terminate with semicolon to execute query

You are currently connected to the database:mydb

mydb=>

就 可 以 直 接 与 我 们 刚 建 立 好 的 database做 沟 通 罗 ! 你 可 以 下 SQL命 令 来 直 接 存 取 mydb的 资 料 , 记 得 以 \g或 是 ; 结 尾 才 会 开 始 执 行 喔 ! 另 外 可 下 \h来 查 看 SQL命 令 列 表 , \q即 离 开 psql. 现 在 我 们 可 以 来 下 些 SQL命 令 来 做 些 测 试 , 看 看 我 们 架 好 的 postmaster是 否 可 以 正 常 运 作 了 :

mydb=> CREATE TABLE message (

mydb-> username varchar( 20) ,

mydb-> age int,

mydb-> say varchar( 255)

mydb-> ) ;

以 上 SQL命 令 会 建 立 一 个 名 叫 message的 table( 报 表 ) , 而 这 份 报 表 中 的 栏 位 共 有 叁 项 , 分 别 是

1.username最 大 长 度 为 20个 字 元 ,

2.age为 一 整 数 ,

3.say最 大 长 度 为 255个 字 元 , 建 立 好 table之 後 , 我 们 就 可 以 开 始 输 入 一 笔 笔 的 资 料 了 :

mydb=> INSERT INTO message

mydb-> VALUES( ‘ skytree’ ,20,’ Hello,world!

I am skytree!’ )

mydb-> ;

这 里 的 INSERT INTO是 SQL命 令 , 意 思 就 是 加 入 一 笔 资 料 到 message这 个 table之 中 , 而 VALUES後 括 号 中 的 内 容 则 是 代 表 每 个 栏 位 的 值 , 以 逗 号 来 分 隔 各 栏 位 , 栏 位 的 型 态 若 是 字 串 请 以 ‘ ’ 括 起 来 , 若 是 数 值 则 不 用 。 这 样 我 们 建 立 好 的 message table中 就 有 一 笔 资 料 了 , 那 麽 建 立 好 的 资 料 该 如 何 查 询 呢 ?

mydb=> SELECT * FROM message WHERE

username=‘ skytree’

mydb-> ;

结 果 :

username|age|say

--------+---+--------------------------

skytree | 20|Hello,world! I am skytree!

( 1 row)

在 SQL命 令 之 中 , 是 以 SELECT命 令 来 查 询 资 料 栏 位 的 。 上 面 的 命 令 意 思 是 「 从 message中 搜 寻 出 所 有 username是 skytree的 每 一 笔 资 料 , 再 将 符 合 这 项 条 件 的 所 有 栏 位 都 抓 出 来 」 , 星 号 ( *) 就 是 表 示 所 有 栏 位 , 下 完 命 令 之 後 就 会 产 生 一 份 结 果 的 列 表 . 学 会 了 新 增 与 查 询 资 料 , 当 然 不 能 忘 了 删 除 资 料 的 功 能 罗 !

mydb=> DELETE FROM message WHERE

username=’ skytree’

mydb-> ;

意 思 是 「 从 message中 搜 寻 出 所 有 username 是 skytree的 所 有 资 料 , 并 且 将 这 些 笔 资 料 删 除 」 , 执 行 完 後 可 以 下

mydb=> SELECT * FROM message

mydb-> ;

来 查 看 message中 的 所 有 资 料 , 因 为 之 前 我 们 只 加 入 了 一 笔 资 料 , 而 刚 刚 又 将 这 笔 资 料 给 删 除 了 , 所 以 结 果 应 该 如 下 :

username|age|say

--------+---+---

( 0 rows)

其 实 SQL还 有 许 多 功 能 , 有 兴 趣 的 读 者 可 以 自 行 研 究 看 看 , 以 上 这 几 种 SQL命 令 是 最 常 用 到 的 了 。

C,C++,Perl,Tcl,Python API

psql的 功 能 主 要 在 於 可 以 直 接 与 资 料 库 沟 通 , 做 管 理 的 工 作 , 但 是 若 我 们 需 要 透 过 其 他 的 方 式 来 存 取 资 料 库 时 , 就 必 须 自 行 设 计 应 用 程 式 来 呼 叫 Postgres95所 提 供 的 一 些 API了 , 例 如 : 透 过 CGI 程 式 来 存 取 资 料 库 , 那 麽 API又 是 什 麽 呢 ?

API( Application Programing Interface) 翻 成 中 文 就 是 「 应 用 程 式 设 计 介 面 」 , 简 单 地 说 就 是 一 套 提 供 与 其 系 统 沟 通 的 函 式 库 , 可 让 程 式 设 计 师 来 直 接 取 用 , 减 少 程 式 设 计 师 开 发 程 式 的 时 间 与 复 杂 度 。 而 Postgres95本 身 提 供 了 许 多 不 同 程 式 语 言 的 API可 供 我 们 利 用 , 以 下 将 介 绍 C API 的 呼 叫 与 说 明 :

首 先 要 先 介 绍 一 些 环 境 变 数 :

PGHOST = 伺 服 器 的 名 称

PGOPTION = 给 POSTGRES backend 程 式 的 参 数

PGPORT = 与 POSTGRES backend 程 式 连 线 的 内 设 port PGTTY = 由 POSTGRES backend 程 式 所 传 来 的 除 错 讯 息 , 可 为 一 个 档 案 或 是tty

PGDATABASE = 内 定 的 POSTGRES database name

接 着 是 这 套 C API中 所 提 供 的 各 项 函 数 的 使 用 与 介 绍 ,

一 . 与 Server连 线 相 关 函 数

PQsetdb

语 法 : PGconn *PQsetdb( char *pghost,char *pgport, char *pgoptions,char *pgtty, char *dbName) ;

功 能 : 与 Server建 立 连 线

说 明 : 若 是 以 上 传 入 的 各 项 值 皆 为 null, 则 会 先 去 搜 寻 上 面 所 介 绍 的 环 境 变 数 来 代 换 , 若 是 连 环 境 变 数 都 未 设 定 , 则 将 会 使 用 系 统 本 身 的 预 设 值 了 。 PQdb

语 法 : char *PQdb( PGconn *conn) ;

功 能 : 传 回 目 前 连 线 中 所 使 用 的 database name

Pqhost

语 法 : char *PQhost( PGconn *conn) ;

功 能 : 传 回 目 前 正 在 连 线 中 的 主 机 名 称

Pqoptions 语 法 : char *PQoptions( PGconn *conn) ;

功 能 : 传 回 此 一 连 线 所 使 用 的 pgoption 值

Pqport

语 法 : char *PQport( PGconn *conn) ;

功 能 : 传 回 此 一 连 线 所 使 用 的 pgport值

Pqtty

语 法 : char *PQtty( PGconn *conn) ;

功 能 : 传 回 此 一 连 线 所 使 用 的 pgtty值

Pqstatus

语 法 : ConnStatusType *PQstatus( PGconn *conn) ;

功 能 : 传 回 目 前 连 线 的 状 态

说 明 : 传 回 值 有 两 种 , CONNECTION_OK或 是CONNECTION_BAD。

PQerrorMessage

语 法 : char*Pqerr orMessage( PGconn*conn);

功 能 : 传 回 此 一 连 线 中 所 产 生 的 错 录 讯 息

Pqfinish

语 法 : void PQfinish( PGconn *conn) ;

功 能 : 关 闭 连 线

说 明 : 除 了 关 闭 连 线 外 , 还 会 将 连 线 所 占 用 之 记 忆 体 释 放 出 来 。

Pqreset

语 法 : void PQreset( PGconn *conn) ;

功 能 : 重 新 连 线

Pqtrace

语 法 : void PQtrace( PGconn *conn,FILE*debug_port) ;

功 能 : 追 踪 目 前 连 线 中 程 式 与 Server间 的 讯 息 传 送 , 供 除 错 用 。

说 明 : 这 些 讯 息 将 被 输 出 到 debug_port filestream中 , 可 被 记 录 到 档 案 之 中 。

Pquntrace

语 法 : void PQuntrace( PGconn *conn) ;

功 能 : 停 止 追 踪 目 前 连 线 中 程 式 与 Server间 的 讯 息 传 送

二 . 执 行 查 询 的 函 数

Pqexec

语 法 : PGresult *PQexec( PGconn *conn,char*query) ;

功 能 : 将 传 送 一 个 SQL命 令 给 Server, 并 得 到 一 个 查 询 的 结 果 。

说 明 : 传 回 的 结 果 将 存 放 在 一 个 PGresult型 态 的 结 构 之 中 , 若 传 回 的 结 果 为 null可 再 以 PQerrormessage来 取 得 更 详 细 的 错 误 讯 息 。

PQresultStatus

语 法 : ExecStatusType PQresultStatus( PGresult *res) ;

功 能 : 传 回 目 前 查 询 的 状 态

说 明 : 传 回 值 有 以 下 几 种 - PGRES_EMPTY_QUERY,PGRES_COMMAND_OK,/*

此 一 查 询 为 一 单 纯 的 命 令 */PGRES_TUP-LES_OK, /* 查 询 成 功 */PGRES_COPY_OUT,PGRES_COPY_IN,PGRES_BAD_RESPONSE, /* 未 知 的 错 误 回 应 */PGRES_NONFATAL_ERROR,PGRES_FATAL_ERROR若 是 传 回 值 为 PGRES_TUPLES_OK, 将 可 以 使 用 以 下 的 函 数 来 分 析 res的 资 料 结 构 , 以 得 到 真 正 需 要 的 资 料 。

Pqntuples

语 法 : int PQntuples( PGresult *res) ;

功 能 : 传 回 res中 有 几 笔 资 料 Pqnfields

语 法 : int PQnfields( PGresult *res) ;

功 能 : 传 回 res 中 有 多 少 栏 位 ( field)

Pqfname

语 法 : char *PQfname( PGresult *res,int field_index) ;

功 能 : 依 照 所 传 入 的 field_index值 , 传 回 相 对 应 的 栏 位 名 称 ( field name)

说 明 : field_index值 由 0开 始 。

Pqfnumber

语 法 : int PQfnumber( PGresult *res,char*field_name) ;

功 能 : 传 回 field_name的 field_index值 , 由 文 字 转 数 字

PQftype

语 法 : Oid PQftype( PGresult *res,int field_index) ;

功 能 : 传 回 field_index所 指 栏 位 的 型 态 (field type)

Pqfsize

语 法 : int2 PQfsize( PGresult *res,int field_index) ;

功 能 : 传 回 field_index所 指 栏 位 的 资 料 大 小 , 单 位 为bytes

说 明 : 若 传 回 值 为 -1, 代 表 此 一 栏 位 的 大 小 为 不 定 长 度 。

Pqgetvalue

语 法 : char*PQgetvalue( PGresult *res,inttup_num,int field_num) ;

功 能 : 传 回 第 tup_num笔 , 第 field_num个 栏 位 里 的 资 料

Pqgetlength

语 法 : int PQgetlength( PGresult *res,int tup_num,int field_num) ;

功 能 : 传 回 第 tup_num笔 , 第 field_num个 栏 位 里 的 资 料 长 度

PQcmdStatus

语 法 : char*PQcmdStatus( PGresult *res) ;

功 能 : 传 回 最 後 一 个 查 询 动 作 的 命 令 状 态

PQprintTuples

语 法 : void PQprintTuples( PGresult* res, FILE* fout, /*output stream*/ int print AttName,/*是 否 显 示 出 field name*/int terseOutput, /*是 否 显 示 出 界 限 的 符 号 */int width /* 栏 位 的 长 度 , 0 代 表 不 定 长 度 */ ) ; 功 能 : 显 示 出 所 有 查 询 到 的 资 料 , 就 如 同 psql程 式 所 显 示 的 结 果 一 样 。

Pqclear

语 法 : void PQclear( PQresult *res) ;

功 能 : 将 res所 指 到 的 PQresult结 构 释 放 , 当 所 有 查 询 到 的 结 果 不 再 使 用 时 , 都 应 该 将 其 释 放 。

以 上 为 C API基 本 的 功 能 介 绍 , 实 际 上 还 有 其 他 一 些 函 数 尚 未 说 明 , 一 般 初 学 者 应 先 学 会 以 上 功 能 後 , 再 更 学 习 其 他 较 深 入 的 函 数 使 用 。 看 完 了 基 本 的 C API介 绍 後 , 当 然 应 该 要 有 个 实 际 范 例 让 我 们 了 解 程 式 的 基 本 撰 写 架 构 与 API函 数 的 实 际 运 用 :

这 个 范 例 程 式 位 於 /usr/src/pgsql/src/test/exampiles 之 中

/*

* testlibpq.c

* Test the C version of LIBPQ, the POSTGRES frontend library.

*

*

*/

#include < stdio.h>

#include “ libpq-fe.h”

void

exit_nicely( PGconn* conn)

{

PQfinish( conn) ; /* 结 束 连 线 并 释 放 PGconn 结 构 所 占 的 记 忆 体 */

exit( 1) ;

}

main( )

{

char *pghost, *pgport, *pgoptions, *pgtty;

char* dbName;

int nFields;

int i,j;

#ifdef DEBUG

FILE *debug;

#endif /* DEBUG */

PGconn* conn; /* 宣 告 conn 为 一 个 PGconn 结 构 的 指 标 */

PGresult* res; /* 宣 告 res 为 一 个 PGresult 结 构 的 指 标 */

pghost = NULL; /* host name of the backend server */

pgport = NULL; /* port of the backend server */

pgoptions = NULL; /* special options to start up the backend server */

pgtty = NULL; /* debugging tty for the backend server */

dbName = “ template1” ;

/* 由 此 开 始 建 立 一 个 新 的 连 线 */

conn = PQsetdb( pghost, pgport, pgoptions, pgtty, dbName) ;

/* 检 查 刚 刚 所 建 立 的 连 线 状 态 是 否 正 常 */

if ( PQstatus( conn) == CONNECTION_BAD) {

fprintf( stderr,” Connection to database ‘ %s’ failed.\n” , dbName) ; fprintf( stderr,” %s” ,PQerrorMessage( conn) ) ;

exit_nicely( conn) ;

}

#ifdef DEBUG

debug = fopen( “ /tmp/trace.out” ,” w” ) ;

PQtrace( conn, debug) ;

#endif /* DEBUG */

/* 开 始 与 资 料 库 沟 通 */

res = PQexec( conn,” BEGIN” ) ;

if ( PQresultStatus( res) != PGRES_COMMAND_OK) {

fprintf( stderr,” BEGIN command failed\n” ) ;

PQclear( res) ;

exit_nicely( conn) ;

}

/* 释 放 res 记 忆 体 空 间 */

PQclear( res) ;

/* fetch instances from the pg_database, the system catalog of databases*/

res = PQexec( conn,” DECLARE myportal CURSOR FOR select * frompg_database” ) ;

if ( PQresultStatus( res) != PGRES_COMMAND_OK) {

fprintf( stderr,” DECLARE CURSOR command failed\n” ) ;

PQclear( res) ;

exit_nicely( conn) ;

}

PQclear( res) ;

res = PQexec( conn,” FETCH ALL in myportal” ) ;

if ( PQresultStatus( res) != PGRES_TUPLES_OK) {

fprintf( stderr,” FETCH ALL command didn’ t return tuples properly\n” ) ;

PQclear( res) ;

exit_nicely( conn) ;

}

/* 列 印 出 栏 位 的 名 称 */

nFields = PQnfields( res) ;

for ( i=0; i < nFields; i++) {

printf( “ %-15s” ,PQfname( res,i) ) ;

}

printf( “ \n\n” ) ;

/* 列 印 出 栏 位 的 资 料 内 容 */

for ( i=0; i < PQntuples( res) ; i++) {

for ( j=0 ; j < nFields; j++) {

printf( “ %-15s” , PQgetvalue( res,i,j) ) ;

}

printf( “ \n” ) ;

}

PQclear( res) ;

/* close the portal */

res = PQexec( conn, “ CLOSE myportal” ) ;

PQclear( res) ;

/* 结 束 与 资 料 库 的 沟 通 */

res = PQexec( conn, “ END” ) ;

PQclear( res) ;

/* 关 闭 连 线 并 释 放 连 线 所 占 用 的 记 忆 体 */

PQfinish( conn) ;

#ifdef DEBUG

fclose( debug) ;

#endif /* DEBUG */

exit( 0) ;

}

因 为 我 们 有 呼 叫 C API, 所 以 必 须 link libpq.a这 个 档 案 , 程 式 才 能 编 译 完 成 , 请 先 做 下 列 步 骤 来 完 成 编 译 ,

% cp /usr/src/pgsql/src/libpq/libpq.a /usr/local/pgsql/include

% cp /usr/src/pgsql/src/test/examples/testlibpq.c /usr/local/pgsql/include

% cd /usr/local/pgsql/include

% gcc -o test testlibpq.c libpq.a

编 译 出 来 的 程 式 为 test% ./test

执 行 程 式 结 果 如 下 :

datname datdba datpath

template1 510 template1

mydb 510 mydb

初 学 者 可 以 试 着 来 修 改 这 个 程 式 , 多 多 尝 试 , 相 信 可 以 对 Postgres95更 为 熟 悉 的 !

结 语

以 上 的 介 绍 其 实 都 只 是 入 门 的 观 念 而 已 , 仍 有 许 多 Postgres95强 大 的 功 能 笔 者 尚 未 介 绍 , 例 如 可 以 自 定 Query Fonction等 等 , 也 许 以 後 有 机 会 再 来 详 细 加 以 说 明 , 另 外 值 得 一 提 的 是 , Postgres95 是 由 许 多 自 愿 投 入 心 血 的 人 自 动 组 成 团 队 研 究 发 展 的 , 在 Linux世 界 中 这 类 型 的 合 作 是 造 成 Linux 如 此 多 元 化 的 主 力 , 然 而 这 类 型 的 team work在 国 内 仍 不 多 见 , 大 部 分 玩 家 仍 是 单 打 独 斗 , 希 望 国 内 能 够 有 越 来 越 多 的 人 都 能 加 入 Linux的 行 列 , 为 这 套 开 放 的 作 业 系 统 灌 入 新 血 。

备 注 : 笔 者 是 站 在 初 学 者 的 角 度 来 写 这 篇 文 章 , 可 能 高 手 们 会 觉 得 笔 者 罗 唆 , 不 过 笔 者 是 希 望 刚 入 门 的 Linux使 用 者 能 够 多 了 解 一 些 观 念 问 题 , 有 句 话 说 : 「 万 事 起 头 难 」 , 在 Linux的 世 界 中 更 是 如 此 , 笔 者 见 到 不 少 人 刚 灌 完 Linux後 没 几 天 就 砍 掉 了 , 原 因 是 不 会 用 或 是 不 知 道 有 什 麽 用 , 而 且 懂 Linux的 人 又 不 像 Windows95那 麽 多 , 遇 到 问 题 又 无 法 解 决 , 实 在 是 满 可 惜 的 , 所 以 笔 者 文 章 中 的 许 多 步 骤 都 会 尽 量 详 细 的 列 出 来 , 希 望 尽 管 初 学 者 ( 其 实 笔 者 也 是 初 学 者 啦 ! ) 也 能 够 至 少 完 成 基 本 的 安 装 与 简 单 的 应 用 , 不 会 因 为 刚 开 始 的 一 点 点 小 困 难 就 放 弃 了 学 习 Linux的 机 会 , 不 过 最 後 还 是 希 望 读 者 们 能 够 学 会 自 行 解 决 问 题 的 能 力 , 因 为 笔 者 觉 得 这 才 是 学 习 Linux最 大 的 收 获 。 这 一 点 是 笔 者 加 入 网 推 会 後 由 学 长 们 传 承 下 来 的 观 念 , 在 此 与 大 家 分 享 !

( 作 者E-Mail: s844074@moon.yzit.edu.tw)