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)