### 为Oracle增加系统调用接口 #### 概述 本文档主要介绍了一种早期方法,在Oracle 9i版本上实现调用动态库中的函数,从而扩展数据库的功能。随着技术的发展,这一特性在后续版本如Oracle 10g中已内建支持。本示例通过创建用户、权限分配、编写C语言程序以及在Oracle环境中部署这些程序来实现系统调用接口。 #### 创建用户及权限配置 需要创建一个专门用于此目的的用户,并赋予相应的权限: 1. **创建用户**:使用命令`create user cdx identified by "123";`创建名为`cdx`的新用户。 2. **授权**: - 授予`connect`权限:`grant connect to cdx;` - 授权创建库(即动态链接库)的权限:`grant create library to cdx;` - 授权创建过程的权限:`grant create procedure to cdx;` 3. **创建公有同义词**:创建公有同义词`cdxpack`指向`cdx.cdxpack`。 4. **调整表空间设置**:修改`cdx`用户的默认表空间为`users`,临时表空间为`temp`,并给予无限配额:`alter user cdx default tablespace users temporary tablespace temp; alter user cdx quota unlimited on users;` #### 数据记录与日志 为了记录执行情况,创建了一个表`cdx.cmdrunlog`用于存储用户名称、运行日期、命令字符串、参数字符串以及返回码等信息: ```sql create table cdx.cmdrunlog ( usr_name varchar2(50), run_date date, cmd_str varchar2(50), para_str varchar2(50), run_rtecode number(10) ); ``` #### 编写C语言程序 接下来,编写一个简单的C语言程序`extproc.c`,该程序定义了一个函数`RunSysCmd`,用于接收命令行字符串和参数字符串,并调用系统命令。具体代码如下: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> int RunSysCmd(char *str, char *parastr) { char CmdStr[300]; if (str == NULL) return 1; if (parastr != NULL) sprintf(CmdStr, "%s %s", str, parastr); else sprintf(CmdStr, "%s", str); return system(CmdStr); } ``` 编译上述C程序,生成动态链接库`extproc.dll`: ```bash cl -I ./LD -Zi extproc.c /link msvcrt.lib /node:libcmt /DLL ``` #### 部署到Oracle 使用`sqlplus`登录`cdx`用户,创建动态库`cdxlib`并指定其路径: ```sql CREATE OR REPLACE LIBRARY cdxlib IS 'e:\extproc\extproc.dll'; ``` 接着,创建包`cdxpack`,其中包含一个函数`RunSysCmd`,该函数使用外部名称`RunSysCmd`和库`cdxlib`进行声明: ```sql CREATE OR REPLACE PACKAGE cdxpack IS FUNCTION RunSysCmd(str IN CHAR, parastr IN CHAR) RETURN BINARY_INTEGER; END cdxpack; CREATE OR REPLACE PACKAGE BODY cdxpack IS FUNCTION RunSysCmd(str IN CHAR, parastr IN CHAR) RETURN BINARY_INTEGER IS EXTERNAL NAME "RunSysCmd" LIBRARY cdxlib PARAMETERS ( str BY REFERENCE, parastr BY REFERENCE ); END cdxpack; ``` #### 测试 创建测试脚本`testpack.sql`,该脚本用于调用`cdxpack.RunSysCmd`函数,并将结果输出到控制台: ```sql DECLARE str1 CHAR(50) := 'dir'; parastr1 CHAR(50) := 'e:\>e:\extproc\pack.txt'; nRetVal BINARY_INTEGER; BEGIN nRetVal := cdxpack.RunSysCmd(str1, parastr1); dbms_output.put_line('cdxpack.RunSysCmd: ' || nRetVal); END; / ``` 创建触发器`CDX.CDXTRIG`,用于在向`cdx.cmdrunlog`表插入新记录时自动执行命令并记录返回码: ```sql CREATE OR REPLACE TRIGGER CDX.CDXTRIG BEFORE INSERT ON CDX.CMDRUNLOG FOR EACH ROW DECLARE nRetVal BINARY_INTEGER; BEGIN :NEW.run_date := SYSDATE; nRetVal := cdxpack.RunSysCmd(:NEW.cmd_str, :NEW.para_str); :NEW.run_rtecode := nRetVal; END; / ``` #### 结论 以上步骤展示了如何在Oracle 9i中实现调用操作系统级别的命令,尽管这一特性在后续版本如Oracle 10g中已作为标准功能提供。这种方法对于扩展数据库功能、实现特定业务逻辑或与其他系统集成非常有用。通过这种方式,可以有效地将外部命令执行能力整合到Oracle环境中,提高应用程序的灵活性和功能性。
1. 以数据库管理员权限登录,建立必要的用户名(暂定为cdx)和全局同义名:
create user cdx identified by "123";
grant connect to cdx;
grant create library to cdx;
grant create procedure to cdx;
create public synonym cdxpack for cdx.cdxpack;
alter user cdx default tablespace users temporary tablespace temp;
alter user cdx quota unlimited on users;
2. 建立必要的日志表纪录(根据需要,这一步也可以不要)用于当向表中增加纪录时,
调用触发器进行根据合法性检查,根据结果(是否为真)判断是否调用外部命令。
create table cdx.cmdrunlog
(
usr_name varchar2(50),
run_date date,
cmd_str varchar2(50),
para_str varchar2(50),
run_rtecode number(10)
);
/
3. 编辑文件extproc.c,保存在:e:\extproc目录
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
- 粉丝: 34
- 资源: 7
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- (源码)基于ArcEngine的GIS数据处理系统.zip
- (源码)基于JavaFX和MySQL的医院挂号管理系统.zip
- (源码)基于IdentityServer4和Finbuckle.MultiTenant的多租户身份认证系统.zip
- (源码)基于Spring Boot和Vue3+ElementPlus的后台管理系统.zip
- (源码)基于C++和Qt框架的dearoot配置管理系统.zip
- (源码)基于 .NET 和 EasyHook 的虚拟文件系统.zip
- (源码)基于Python的金融文档智能分析系统.zip
- (源码)基于Java的医药管理系统.zip
- (源码)基于Java和MySQL的学生信息管理系统.zip
- (源码)基于ASP.NET Core的零售供应链管理系统.zip