【C/C++】项目_3_Oracle数据库安装,表操作,事务及C语言操作Oracle数据库(_ooci.h,_ooci.cpp)

@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用户exitctrl+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:关系数据库管理系统,实例名就是SID
在这里插入图片描述

2.表操作: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或其它


在这里插入图片描述

在这里插入图片描述
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容