0
点赞
收藏
分享

微信扫一扫

【C/C++8】天气APP:Oracle数据库安装,表操作,C语言操作Oracle数据库

狗啃月亮_Rachel 2022-04-05 阅读 72

文章目录


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(相同等级的用户放一起就是一个组,只要对组设定权限就行)。useradd -n oracle -g dba -d /oracle:增加oracle用户(这种方法创建oracle用户,会在根目录形成单独oracle文件夹与home和root文件夹平级,普通创建用户useradd y在根目录里的home目录里形成y文件夹)。

passwd oracle:修改oracle用户的密码。cat /etc/passwd:查看所有用户除root。cat /etc/group:查看所有用户组。groups 用户名:查看用户所在组。userdel (-r)用户名:删除用户(或删除home文件夹里用户名文件夹)。

Linux 中,操作系统会根据UID 来判断用户,如果id 为0则为管理员账户,可能存在多个管理员账户。每个用户都会属于一个组,意味着当创建用户的时候,系统会自动创建一个同名组作为次账户的主组。用户和组的关系以配置文件的方式关联,相关配置文件如下:
在这里插入图片描述
在这里插入图片描述
从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日期(以数据存储)转为字符串,如上格式转为如下格式。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
长事务指时间长如update一条记录在那等处理,等完后再提交,锁也属于一种资源,锁的总数有限。DBA也会定期整理碎片,windows中管理工具中也有个碎片整理。
在这里插入图片描述

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/105594808。_ooci.h中第一个类connection:数据库连接池类,第二个类sqlstatement:sql语言操作数据库类,如下rc执行结果成功为0,失败为oracle错误代码,并将其错误信息放入message,下面在_ooci.h中。
在这里插入图片描述
在这里插入图片描述
程序里每执行一条sql就会提交一次事务,因为没有多表操作,只要把数据插入这张表中就可以了,有没有事务无所谓,缺省0:启动事务。
在这里插入图片描述
如下下面两行=上面一行,conn用的哪个(不是哪种)数据库的connection类。conn指针和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没有这行的话可将createtable.cpp中警告的字符串前加上(char*)就行。还可以在声明时_ooci.h加const,_ooci.cpp中也要修改(不建议)。-Wno-unused-variable变量未使用关闭警告(如int cc;下面未使用cc变量)。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如下-g是可调试,clntsh是真正的库名,lib.so动态库命名(静态库lib.a,静态库代码在编译时被整合到程序里,编译完成静态库删了没问题)

动态库是执行到相关函数时才调用该函数库里相应函数,函数库没有整合进程序里(因为没有整合进程序,如1000个程序链接共享动态库,这样可执行文件会小很多,节省内存)

优点是动态库改变不影响程序,程序不需要重新编译,只需要重新编译动态库就行。

头路径,库路径,库名(.a/.so/.cpp),如下头文件采用-I标准写法,库文件不采用标准也写法编译也过。
在这里插入图片描述
如下全部采用标准写法。
在这里插入图片描述
如下采用原始不含头文件编译方法错误。
在这里插入图片描述
在这里插入图片描述
下面是文件:
在这里插入图片描述
如下采用ORACLE_HOME换用户时只需要添加该用户.bash_profile中export…进env,不需要改makefile。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下面是文件:
在这里插入图片描述
在这里插入图片描述
如下程序只要链接了动态库就需要LD…这个环境变量(属于linux操系环变,不属于oracle数据库环变)。
在这里插入图片描述
在这里插入图片描述

4.3 createtable.cpp

#include "_ooci.h"
int main(int argc,char *argv[])
{
//11111111111111111111111111111111111111111111111111111111.数据库连接池类
  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;
  }

//11111111111111111111111111111111111111111111111112.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))");

//111111111111111111111111111111111111111111111113.执行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。
在这里插入图片描述
如下commit失败的话也会调用m_cda结构体,goods为表名,如下(id))后面不需要分号,sqlplus里需要分号且把\去除,prepare语法和printf语法一样如下有%s(也叫动态参数)。如下execute()是有参数或无参数的重载函数,insert要提交。
在这里插入图片描述
在这里插入图片描述
如下trim(c1)去除c1的空格,最后一行不加trim是查不出下面表格。char补空格,varchar不补空格。确定长度用char(char好处快),c1 varchar2(4000)用到几个字符自动分配几个而不是一下给4000字符。CLOB:结构化数据如文本信息。BLOB:非结构化数据。
在这里插入图片描述

4.4 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[])
{
//111111111111111111111111111111111111111111111111.数据库连接池
  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;
  }
    
//111111111111111111111111111111111111111111111112.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);

//111111111111111111111111111111111111111111111113.模拟商品数据,向表中插入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.5 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[])
{
//111111111111111111111111111111111111111111111111.数据库连接池
  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;
  }
    
//111111111111111111111111111111111111111111111112.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;

//111111111111111111111111111111111111111111111113.执行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.6 updatetable.cpp

// 本程序演示更新商品表中数据
#include "_ooci.h"
int main(int argc,char *argv[])
{
//111111111111111111111111111111111111111111111111.数据库连接池
  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;
  }
    
//111111111111111111111111111111111111111111111112.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");

//111111111111111111111111111111111111111111111113.执行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.7 deletetable.cpp

// 本程序演示删除商品表中数据
#include "_ooci.h"
int main(int argc,char *argv[])
{
//111111111111111111111111111111111111111111111111.数据库连接池
  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;
  }
    
//111111111111111111111111111111111111111111111112.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;
  
 //111111111111111111111111111111111111111111113.执行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 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[])
{
//111111111111111111111111111111111111111111111111.数据库连接池
  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;
  }
    
//111111111111111111111111111111111111111111111112.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之后还有一个分号。
  
//111111111111111111111111111111111111111111111113.执行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;
}

在这里插入图片描述
在这里插入图片描述

举报

相关推荐

0 条评论