@TOC
1.安装:swap,find
1.1 创建swap交换区
grep MemTotal /proc/meminfo (安装Oracle物理内存要求1024MB以上)
grep SwapTotal /proc/meminfo (下面是交换区要求)
下面为添加交换区大小,此方法不限于centos,linux均适用,以下命令均需在root帐号下操作:
(1)
先用free -m查看一下swap的大小(2)
使用dd命令创建/home/swap这么一个分区文件。
dd if=/dev/zero of=/home/swap bs=1024 count=2048000
(3)
接着再把这个分区变成swap分区。
/sbin/mkswap /home/swap
(4)
再接着使用这个swap分区。使其成为有效状态。
/sbin/swapon /home/swap
(5)
现在再用free -m命令查看一下内存和swap分区大小,就发现增加了2048M的空间了。创建的是2048,显示1999。(6)
修改/etc/fstab文件,让CentOS操作系统在每次重启时自动加载/home/swap交换区。
vi /etc/fstab,/home/swap swap swap defaults 0 0
(上面执行错可以删除交换分区,对了不用删)
停止正在使用的swap分区:#swapoff /home/swap
删除swap分区文件:#rm /home/swap
删除或注释在/etc/fstab文件开机自动挂载/swap1的命令
1.2 安装依赖包及改系统核心参数
yum install -y binutils* compat-libstdc* elfutils-libelf* gcc* glibc* ksh* libaio* libgcc* libstdc* make* sysstat* libXp* glibc-kernheaders
yum install -y ksh binutils compat-libstdc++-33 elfutils-libelf elfutils-libelf-devel gcc gcc-c++ glibc glibc-common glibc-devel libaio libaio-devel libgcc libstdc++ libstdc++-devel make numactl sysstat libXp unixODBC unixODBC-devel
(修改系统核心参数,关闭一些系统对数据库的限制)
1.
修改/etc/sysctl.conf文件
vi /etc/sysctl.conf
在文件最后增加以下行。
fs.file-max = 6815744
fs.aio-max-nr = 1048576
kernel.shmall = 2097152
kernel.shmmax= 2147483648
kernel.shmmni= 4096
kernel.sem = 250 32000100 128
net.ipv4.ip_local_port_range= 9000 65500
net.core.rmem_default= 262144
net.core.rmem_max= 4194304
net.core.wmem_default = 262144
net.core.wmem_max= 1048576
注意,kernel.shmmax参数的值为操作系统内存的一半,单位是字节。例如,装服务器的总物理内存如果是1024MB,那么kernel.shmmax的值应该是512乘1024乘1024=536870912,即kernel.shmmax = 536870912,其它的参数照抄。
2.
修改/etc/security/limits.conf文件
vi /etc/security/limits.conf
修改操作系统对oracle用户资源的限制。在该文件中添加如下行:
oracle soft nproc 2047
oracle hard nproc 16384
oracle soft nofile 1024
oracle hard nofile 65536
oracle hard stack 10240
3.
修改/etc/pam.d/login文件
添加如下的行到/etc/pam.d/login文件
vi /etc/pam.d/login
session required /lib/security/pam_limits.so
4.
修改/etc/profile文件
添加如下的行到/etc/profile文件
vi /etc/profile
if [ $USER = "oracle" ]; then
if [ $SHELL = "/bin/ksh" ]; then
ulimit -p 16384
ulimit -n 65536
else
ulimit -u 16384 -n 65536
fi
fi
5.
关闭 selinux
vi /etc/selinux/config,修改成 selinux=disabled
6.
关闭图形界面
vi /etc/inittab,把最后一行运行级别改为3,没有的话就不执行这一步
7.
重启服务器 #init 6 或 reboot
1.3 创建oracle用户和组及解压缩包
以下命令都在root用户执行:增加dba组:#groupadd dba(相同等级的用户放一起就是一个组,只要对组设定权限就行)
增加oracle用户:#useradd -n oracle -g dba -d /oracle(这种方法创建oracle用户,会在根目录形成单独oracle文件夹与home和root文件夹平级,普通创建用户useradd y在根目录里的home目录里形成y文件夹)
修改oracle用户的密码:#passwd oracle
cat /etc/passwd:查看所有用户除root
cat /etc/group:查看所有用户组
groups 用户名:查看用户所在组
userdel (-r)用户名:删除用户(或删除home文件夹里用户名文件夹)
从win本地上传oracle11g1.tgz压缩包到linux的tmp目录。用oracle用户登录,从根目录
下开始解开压缩包
链接:https://pan.baidu.com/s/1Ywtv8zzRGzSCpwu9PyPobQ 提取码:ebk7 。#cd / #tar zxvf /tmp/oracle11g.tgz
解压缩包后,一定要退出oracle用户
exit
或ctrl+d
,否则oracle用户的环境变量不会生效。oracle11gR2.tgz解压后,会生成/oracle/.bash_profile文件,包括了Oracle数据库的安装参数,内容如下
export ORACLE_BASE=/oracle/base
export ORACLE_HOME=/oracle/home
export ORACLE_SID=snorcl11g
export NLS_LANG='Simplified Chinese_China.ZHS16GBK'
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/usr/lib
export PATH=$PATH:$HOME/bin:$ORACLE_HOME/bin:.
1.4 数据库的启动和关闭
用oracle用户登录,执行lsnrctl start
启动网络监听服务,执行dbstart
启动数据库系统。
用oracle用户登录,执行lsnrctl stop
关闭网络监听服务,执行dbshut
关闭数据库系统。lsnrctl status
,在关服务器操作系统之前,一定要关闭数据库,否则数据库损坏的概率超过50%。
Oracle数据库的启动和关闭配置成系统服务:在操作系统启动/关闭时自动启动/关闭Oracle实例和监听,以下都在root用户操作:
1.
启动数据库实例的SQL脚本:vi /oracle/home/bin/dbstart
sqlplus / as sysdba <<EOF
startup;
EOF
chmod +x /oracle/home/bin/dbstart
2.
vi /oracle/home/bin/dbrestart
sqlplus / as sysdba <<EOF
shutdown immediate;
startup;
EOF
chmod +x /oracle/home/bin/dbrestart
3.
vi /oracle/home/bin/dbshut
sqlplus / as sysdba <<EOF
shutdown immediate;
EOF
chmod +x /oracle/home/bin/dbshut
4.
vi /usr/lib/systemd/system/oracle.service(/usr/lib文件夹里有一些.so文件,/systemd/system/oracle.service是自己创建的)
[Unit]
Description=Oracle RDBMS
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/su - oracle -c "/oracle/home/bin/dbstart >> /tmp/oracle.log"
ExecReload=/usr/bin/su - oracle -c "/oracle/home/bin/dbrestart >> /tmp/oracle.log"
ExecStop=/usr/bin/su - oracle -c "/oracle/home/bin/dbshut >> /tmp/oracle.log"
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
vi /usr/lib/systemd/system/lsnrctl.service
[Unit]
Description=Oracle RDBMS
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/su - oracle -c "/oracle/home/bin/lsnrctl start >> /tmp/lsnrctl.log"
ExecReload=/usr/bin/su - oracle -c "/oracle/home/bin/lsnrctl reload >> /tmp/lsnrctl.log"
ExecStop=/usr/bin/su - oracle -c "/oracle/home/bin/lsnrctl stop >> /tmp/lsnrctl.log"
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
5.
如下命令可不执行
systemctl daemon-reload # 重新加载服务配置文件
systemctl start oracle # 启动oracle服务。
systemctl restart oracle # 重启oracle服务。
systemctl stop oracle # 关闭oracle服务。
systemctl start lsnrctl # 启动lsnrctl服务。
systemctl restart lsnrctl # 重启lsnrctl服务。
systemctl stop lsnrctl # 关闭lsnrctl服务。
6.
systemctl enable oracle # 把Oracle实例服务设置为开机自启动。
systemctl enable lsnrctl # 把Oracle监听服务设置为开机自启动。
7.
Oracle实例启动的日志在/tmp/oracle.log文件中。监听的启动日成在/tmp/lsnrctl.log文件中。只有通过systemctl启动/关闭Oracle实例和监听才会写日志,手工执行脚本不写日志。
1.5 sqlplus命令行登录数据库
用oracle用户登录,执行sqlplus scott/tiger
,以scott用户的身份登录数据库。防火墙放开1521端口sqlplus登录数据库,centos7和centos6的防火墙设置不同,centos7采用以下方法:systemctl restart firewalld.service设完端口前后防火墙都重启下,firewall-cmd --list-ports查下放开的端口
#firewall-cmd --zone=public --add-port=1521/tcp --permanent
启动监听:lsnrctl status
,如下关闭防火墙:sqlplus中实现命令的上翻下翻功能:https://centos.pkgs.org/ 下载rlwrap-0.37.tar或百度云链接:https://pan.baidu.com/s/1CgO-_To-QLdl1CJJM-ZrBA 提取码:k6cu。root用户执行:tar -zxvf rlwrap-0.37.tar.gz,cd rlwrap-0.37/,yum install -y libtermcap-devel,yum -y install readline*, ./configure,make,make install,
rlwrap -v
,which rlwrap,su - oracle ,vi .bash_profile(root用户vi ~/.bash_profile不行),文件最后加上如下两行(=号前后无空格,英文单引号)alias sqlplus='rlwrap sqlplus'
alias rman='rlwrap rman'
source .bash_profile并重新打开oracle用户窗口
1.6 plsql客户端登录数据库
1.客户端环境
:https://www.oracle.com/technetwork/database/enterprise-edition/downloads/112010-win64soft-094461.html?ssSourceSiteId=otncn
win64_11gR2_client链接:https://pan.baidu.com/s/1xLzrXAZm3xM-szds1IoQFw,提取码:mlo8 ,解压后点击set up应用程序进行安装
2.客户端界面
:链接:https://pan.baidu.com/s/1H9WIojcMbyqTBZe_goO-1Q 提取码:fp2u ,点击直接安装,桌面显示如下粉色图标3.客户端参数配置文件
:D:\app\w\product\11.2.0\client_1\network\admin\tnsnames.ora(可以搜索tnsnames.ora)
snorcl11g_138 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.149.138)(PORT = 1521))
)
(CONNECT_DATA =
(SID = snorcl11g)
(SERVER = DEDICATED)
)
)
如上是客户端如下是服务端,参数内容与上相同
snorcl11g_138:是随便起的,远程连接需打开监听lsnrctl start
RDBMS:
关系数据库管理系统,实例名就是SID2.表操作:tnsping,commit
关键字比如编号,不能是姓名,因为可能有重名
2.1 建create
如果id用number,前面的0会被省去。C语言中字符串结尾要空字符结束,数据库中不要
2.2 增insert
主键不能为空,null为空,0就是数字0
2.3 删delete
上面为删除表,下面为删除表中数据
2.4 改update
2.5 查select
不在同一网段内(局域网内)称远程,ssh客户端和sqldeveloper客户端都存在不操作会断开(TCP连接)。因为日期在oracle里实质是个整数,显示书写是字符串。to_data转为整数
数据库中置为空为null不为0(或者给' ')。C语言中0和null一样(C中字符串可为空,整数没办法为空)
select * from tab;(F8运行如下)
升序后面加asc,默认升序不写
to_data:字符串日期转为
oracle日期(以数据存储)
to_char:
oracle日期(以数据存储)
转为字符串,如上格式转为如下格式3.Oracle的事务:truncate table,alter table
3.1 持有锁
提交事务和运行不一样,如下放到缓冲区,自己session可以看到,别人看不到。commit后存入数据库持久化后别人看到
如下sqldeveloper这个session执行下面这行命令(持有),在sqlplus命令行里执行也是这行但值不同也是不行,因为sqldeveloper没有提交,这一行被锁住了。如果两个session交叉执行命令,会出现死锁现象
如上1条提交一次会产生事务开销,效率低。1000条提交一次刚刚好。太多条会受不了
drop也不产生事务
3.2 sql语言
grant授权,revoke取消授权
4.C语言操作Oracle:trim,rc,库/头文件
4.1 oci
C/C++操作数据库有两种方法:1.Pro*C(在C/C++中嵌入SQL语句),2.OCI(用C语言调用oracle库函数)。关于封装好的OCI代码见文章:https://blog.csdn.net/weixin_43435675/article/details/94630371。_ooci.h
中第一个类connection
:数据库连接池类,第二个类sqlstatement
:sql语言操作数据库类,如下rc执行结果成功为0,失败为oracle错误代码,并将其错误信息放入message
,下面在_ooci.h中
程序里每执行一条sql就会提交一次事务,因为没有多表操作,只要把数据插入这张表中就可以了,有没有事务无所谓,缺省0:启动事务
如下下面两行=上面一行,conn用的哪个(不是哪种)数据库的connection类,conn指针和conn类实例同名
4.2 makefile
#oracle头文件路径 #-I指定头文件的搜索目录/oracle/home/rdbms/public。装了oracle数据库的主机,不管这主机上任何用户名字,都有/oracle/home/rdbms/public这路径
ORAINCL = -I$(ORACLE_HOME)/rdbms/public
# oracle库文件路径 #-L指定库文件的搜索目录/oracle/home/lib
ORALIB = -L$(ORACLE_HOME)/lib -L.
# oracle的oci库 #-l指定链接库名libclntsh.so
ORALIBS = -lclntsh
CFLAGS = -g -Wno-write-strings -Wno-unused-variable
all: createtable inserttable selecttable updatetable deletetable execplsql
createtable:createtable.cpp _ooci.h _ooci.cpp
g++ $(CFLAGS) -o createtable createtable.cpp $(ORAINCL) $(ORALIB) $(ORALIBS) _ooci.cpp
inserttable:inserttable.cpp _ooci.h _ooci.cpp
g++ $(CFLAGS) -o inserttable inserttable.cpp $(ORAINCL) $(ORALIB) $(ORALIBS) _ooci.cpp
selecttable:selecttable.cpp _ooci.h _ooci.cpp
g++ $(CFLAGS) -o selecttable selecttable.cpp $(ORAINCL) $(ORALIB) $(ORALIBS) _ooci.cpp
updatetable:updatetable.cpp _ooci.h _ooci.cpp
g++ $(CFLAGS) -o updatetable updatetable.cpp $(ORAINCL) $(ORALIB) $(ORALIBS) _ooci.cpp
deletetable:deletetable.cpp _ooci.h _ooci.cpp
g++ $(CFLAGS) -o deletetable deletetable.cpp $(ORAINCL) $(ORALIB) $(ORALIBS) _ooci.cpp
execplsql:execplsql.cpp _ooci.h _ooci.cpp
g++ $(CFLAGS) -o execplsql execplsql.cpp $(ORAINCL) $(ORALIB) $(ORALIBS) _ooci.cpp
-Wno-write-string
没有这行的话可以则将警告的字符串前加上(char*)就行。还可以在声明时加const,.cpp中也要修改(不建议)。-Wno-unused-variable
变量未使用
下面是
头
文件:下面是
库
文件:4.3 createtable.cpp
#include "_ooci.h"
int main(int argc,char *argv[])
{
///////////////////////////////////////////////////////1.数据库连接池类
connection conn;
// 连接数据库,返回值0-成功,其它-失败
// 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
if (conn.connecttodb("scott/tiger@snorcl11g_138","Simplified Chinese_China.ZHS16GBK") != 0)
{
printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
}
///////////////////////////////////////////////////2.SQL语言操作类
sqlstatement stmt(&conn);
// 准备创建表的SQL,商品表:商品编号id,商品名称name,价格sal,入库时间btime,商品说明memo,商品图片pic
// prepare方法不需要判断返回值
stmt.prepare("\
create table goods(id number(10),\
name varchar2(30),\
sal number(10,2),\
btime date,\
memo clob,\
pic blob,\
primary key (id))");
////////////////////////////////////3.执行SQL语句,一定要判断返回值,0-成功,其它-失败
if (stmt.execute() != 0)
{
printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
}
printf("create table goods ok.\n");
return 0;
}
setenv/putenv设置环境变量,下面这个类也是可以兼容windows
如下若调用connection或sqlstatement两个类错误时的错误代码时和sqlplus或sqldevelopment错误代码一样
如下commit失败的话也会调用m_cda结构体,goods为表名,如下(id))后面不需要分号,sqlplus里需要分号且把\去除,prepare语法和printf语法一样如下有%s。如下execute()是有参数或无参数的重载函数,insert要提交
4.4 oracle数据类型
如下trim(c1)去除c1的空格,最后一行不加trim是查不出下面表格。char补空格,varchar不补空格
4.5 inserttable.cpp
// 本程序演示向商品表中插入10条记录。
#include "_ooci.h"
// 定义用于操作数据的结构,与表中的字段对应
struct st_GOODS //结构体值与数据库中表即与createtable.cpp中表对应
{
long id; // 商品编号,用long数据类型对应oracle无小数的number
char name[31]; // 商品名称,用char对应oracle的varchar2,注意,表中字段的长度是30,char定义的长度是31,要留C语言的结束符
double sal; // 商品价格,用double数据类型对应oracle有小数的number
char btime[20]; // 入库时间,用char对应oracle的date,格式可以在SQL语句中指定,本程序将指定为yyyy-mm-dd hh24:mi:ss
} stgoods;
int main(int argc,char *argv[])
{
///////////////////////////////////////////////////////////////1.数据库连接池
connection conn;
// 连接数据库,返回值0-成功,其它-失败
// 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
if (conn.connecttodb("scott/tiger@snorcl11g_138","Simplified Chinese_China.ZHS16GBK") != 0)
{
printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
}
//////////////////////////////////////////////////////////2.SQL语言操作类
sqlstatement stmt(&conn);
// 准备插入数据的SQL,不需要判断返回值
stmt.prepare("\
insert into goods(id,name,sal,btime) \
values(:1,:2,:3,to_date(:4,'yyyy-mm-dd hh24:mi:ss'))");
//to_date(:4,'yyyy-mm-dd hh24:mi:ss')可为null
//goods(id,name,sal,btime)字段在createtable.cpp已创建
// 为SQL语句绑定输入变量的地址,行
stmt.bindin(1,&stgoods.id);//bindin中的1对应上面:1
stmt.bindin(2, stgoods.name,30); //30为长度,char是这样绑定
stmt.bindin(3,&stgoods.sal); //此时stgoods.id结构体变量们还未赋值
stmt.bindin(4, stgoods.btime,19);
///////////////////////////////////////////3.模拟商品数据,向表中插入10条测试信息
for (int ii=1;ii<=10;ii++)
{
// 结构体变量初始化
memset(&stgoods,0,sizeof(stgoods));
// 为结构体的变量赋值
stgoods.id=ii;
sprintf(stgoods.name,"商品名称%02d",ii);
stgoods.sal=ii*2.11;
strcpy(stgoods.btime,"2018-03-01 12:25:31");
// 每次指定变量的值后,执行SQL语句,一定要判断返回值,0-成功,其它-失败。
if (stmt.execute() != 0) //每执行一次把变量值插入表,返回结构体m_cda.rc
{
printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
}
printf("insert ok(id=%d,rpc=%ld).\n",ii,stmt.m_cda.rpc); //rpc为行数
}
printf("insert table goods ok.\n");
// 提交数据库事务,不提交的话程序退出,缺省回滚事务
conn.commit();
return 0;
}
select count(*) from
下图因为id唯一,所以不能重复插入。错误信息与上面一行对应
truncate table goods删除表中全部数据,但是不产生事务。若注释//conn.commit();则insert后查询无记录,如下开启自动提交
make后./inserttable
4.6 selecttable.cpp
//本程序演示从商品表中查询数据
#include "_ooci.h"
// 定义用于查询数据的结构,与表中的字段对应
struct st_GOODS //和inserttable.cpp中结构体一样
{
long id; // 商品编号,用long数据类型对应oracle无小数的number
char name[31]; // 商品名称,用char对应oracle的varchar2,注意,表中字段的长度是30,char定义的长度是31,要留C语言的结束符
double sal; // 商品价格,用double数据类型对应oracle有小数的number
char btime[20]; // 入库时间,用char对应oracle的date,格式可以在SQL语句中指定,本程序将指定为yyyy-mm-dd hh24:mi:ss
} stgoods;
int main(int argc,char *argv[])
{
///////////////////////////////////////////////////////////////////1.数据库连接池
connection conn;
// 连接数据库,返回值0-成功,其它-失败
// 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中
if (conn.connecttodb("scott/tiger@snorcl11g_138","Simplified Chinese_China.ZHS16GBK") != 0)
{
printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
}
///////////////////////////////////////////////////////////////2.SQL语言操作类
sqlstatement stmt(&conn);
int iminid,imaxid;
// 准备查询数据的SQL,不需要判断返回值
stmt.prepare("\
select id,name,sal,to_char(btime,'yyyy-mm-dd hh24:mi:ss') from goods where id>:1 and id<:2");
//id,name,sal,to_char(btime,'yyyy-mm-dd hh24:mi:ss')是输出变量
//id>:1 and id<:2是输入变量
// 为SQL语句绑定输入变量的地址
stmt.bindin(1,&iminid);
stmt.bindin(2,&imaxid);
// 为SQL语句绑定输出变量的地址
// stgoods.id这些变量在inserttable已经赋过值
stmt.bindout(1,&stgoods.id);
stmt.bindout(2, stgoods.name,30);
stmt.bindout(3,&stgoods.sal);
stmt.bindout(4, stgoods.btime,19);
// 手工指定id的范围为1到5,执行一次查询 //inserttable已插入10条记录
iminid=1;
imaxid=5;
/////////////////////////////////////////////////3.执行SQL语句,一定要判断返回值,0-成功,其它-失败
if (stmt.execute() != 0)
{
printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
}
//上面执行完sql语句就得到一个结果集,怎么获取这结果集呢?用next方法
while (1)
{
// 先把结构体变量初始化,然后才获取记录
memset(&stgoods,0,sizeof(stgoods));
// 获取一条记录,一定要判断返回值,0-成功,1403-无记录,其它-失败
// 在实际应用中,除了0和1403,其它的情况极少出现。
if (stmt.next() !=0) break;//每next一次就从结果集里拿一条数据
// 把获取到的记录的值打印出来
printf("id=%ld,name=%s,sal=%.02f,btime=%s\n",stgoods.id,stgoods.name,stgoods.sal,stgoods.btime);
}
// 请注意,stmt.m_cda.rpc变量非常重要,它保存了SQL被执行后影响的记录数。
printf("本次查询了goods表%ld条记录。\n",stmt.m_cda.rpc);
return 0;
}
记住下面1405或1406不报错,在未强制为0前打印出。stmt.m_cda.rpc是影响记录的行数
如下delete要提交
如下id=3时是1405,_ooci.cpp中在未强制为0前打印出
4.7 updatetable.cpp
// 本程序演示更新商品表中数据
#include "_ooci.h"
int main(int argc,char *argv[])
{
////////////////////////////////////////////////////1.数据库连接池
connection conn;
// 连接数据库,返回值0-成功,其它-失败
// 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
if (conn.connecttodb("scott/tiger@snorcl11g_138","Simplified Chinese_China.ZHS16GBK") != 0)
{
printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
}
///////////////////////////////////////////////2.SQL语言操作类
sqlstatement stmt(&conn);
int iminid,imaxid;
char strbtime[20];
// 准备更新数据的SQL,不需要判断返回值
stmt.prepare("\
update goods set btime=to_date(:1,'yyyy-mm-dd hh24:mi:ss') where id>:2 and id<:3");
// 为SQL语句绑定输入变量的地址
stmt.bindin(1, strbtime,19); //1对应上面:1
stmt.bindin(2,&iminid); //2对应上面:2
stmt.bindin(3,&imaxid);
// 手工指定id的范围为1到5,btime为2017-12-20 09:45:30,执行一次更新
iminid=1;
imaxid=5;
memset(strbtime,0,sizeof(strbtime));
strcpy(strbtime,"2017-12-20 09:45:30");
/////////////////////////////////////////3.执行SQL语句,一定要判断返回值,0-成功,其它-失败。
if (stmt.execute() != 0)
{
printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
}
// 请注意,stmt.m_cda.rpc变量非常重要,它保存了SQL被执行后影响的记录数。
printf("本次更新了goods表%ld条记录。\n",stmt.m_cda.rpc);
// 提交事务
conn.commit();
return 0;
}
4.8 deletetable.cpp
// 本程序演示删除商品表中数据
#include "_ooci.h"
int main(int argc,char *argv[])
{
//////////////////////////////////////////////////1.数据库连接池
connection conn;
// 连接数据库,返回值0-成功,其它-失败
// 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
if (conn.connecttodb("scott/tiger@snorcl11g_138","Simplified Chinese_China.ZHS16GBK") != 0)
{
printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
}
///////////////////////////////////////////////2.SQL语言操作类
sqlstatement stmt(&conn);
int iminid,imaxid;
// 准备删除数据的SQL,不需要判断返回值
stmt.prepare("delete from goods where id>:1 and id<:2");
// 为SQL语句绑定输入变量的地址
stmt.bindin(1,&iminid);
stmt.bindin(2,&imaxid);
// 手工指定id的范围为1到5
iminid=1;
imaxid=5;
///////////////////////////////////////3.执行SQL语句,一定要判断返回值,0-成功,其它-失败
if (stmt.execute() != 0)
{
printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
}
// 请注意,stmt.m_cda.rpc变量非常重要,它保存了SQL被执行后影响的记录数。
printf("本次从goods表中删除了%ld条记录。\n",stmt.m_cda.rpc);
// 提交事务
conn.commit();
return 0;
}
4.9 execplsql.cpp
下面是oracle存储(CREATE.....)过程(PL/SQL过程)语法,其实就是批处理,sql语句集合
// execplsql.cpp:其中sql:删除全部记录并插入一行
// 本程序演示如何执行一个PL/SQL过程
// 在这里说一下我个人的意见,我从不在Oracle数据库中创建PL/SQL过程,也很少使用触发器,原因如下:
// 1、在Oracle数据库中创建PL/SQL过程,程序的调试很麻烦;
// 2、维护工作很麻烦,因为程序员要花时间去了解数据库中的存储过程;
// 3、在封装的oci中,对oracle的操作已经是简单的事情,没必要去折腾存储过程;
// 在oci中也很少用PL/SQL语句,也是因为复杂的PL/SQL调试麻烦。
#include "_ooci.h"
int main(int argc,char *argv[])
{
///////////////////////////////////////////////////1.数据库连接池
connection conn;
// 连接数据库,返回值0-成功,其它-失败
// 失败代码在conn.m_cda.rc中,失败描述在conn.m_cda.message中。
if (conn.connecttodb("scott/tiger@snorcl11g_138","Simplified Chinese_China.ZHS16GBK") != 0)
{
printf("connect database failed.\n%s\n",conn.m_cda.message); return -1;
}
//////////////////////////////////////////////2.SQL语言操作类
sqlstatement stmt(&conn);
// 准备删除记录的PL/SQL,不需要判断返回值
// 本PL/SQL先删除goods表中的全部记录,再插入一条记录
stmt.prepare("\
BEGIN\
delete from goods;\
insert into goods(id,name,sal,btime)\
values(:1,'过程商品',55.65,to_date('2018-01-02 13:00:55','yyyy-mm-dd hh24:mi:ss'));\
END;");
//上面2条sql语句,:1是为了绑定变量,:1换成100就没有下面两行了
int id=100;
stmt.bindin(1,&id);
// 注意,PL/SQL中的每条SQL需要用分号结束,END之后还有一个分号。
/////////////////////////////////3.执行SQL语句,一定要判断返回值,0-成功,其它-失败
if (stmt.execute() != 0)
{
printf("stmt.execute() failed.\n%s\n%s\n",stmt.m_sql,stmt.m_cda.message); return -1;
}
printf("exec PL/SQL ok.\n");
// 提交事务
conn.commit();
return 0;
}
4.10 慎用char类型
所以设为char(5)肯定固定长度为5,不会是4或其它