有关CSV文件的介绍见https://baike.so.com/doc/5126285-5355574.html ,如果您对CSV有一定了解,请直接往下看!
因为PL/SQL连接oracle出了些问题,至今没有解决,眼看要交作业了,就先用sqlplus来导入数据了,
如果用PL/SQL如何导入,请见其他博友的文章:https://blog.csdn.net/ShenJiancomputer/article/details/8112088
以下是通过外部表来实现在sqlplus中导入数据的内容:
首先总结下步骤:
1、准备一个外部文件,这里放的是我们需要插入表中的数据(建议先备份,以免数据被破坏,我就碰到这样的问题)说明:我的外部文件格式为 以逗号分隔的csv文件,当然,你也可以保存为其他格式的,但是在创建外部表的时候就要对应好了。(或者不是这种格式的可以在Excel->另存为那里修改)
2、创建目录对象,第一步的外部文件就放在这个目录下(当前用户若无创建目录对象的权限,请先授权,具体方法请往下看)
3、创建一个外部表,用于读取外部表中的数据(在创建外部表时,字段的数量、各个字段的数据类型都要与外部文件中的数据格式一一对应;并且不能为表中的各个字段指定主键约束、unique约束、not null约束等。外部表是个只读表,只能读取外部文件、不能向外部表添加、更新和删除数据、也不能在外部表上建立索引)。
4、用 select * from 外部表名 查询外部表中的数据
5、创建一个内部表,这个就是在数据库中我们需要创建的表,直接将外部表中的数据复制到内部表中,这样便将外部文件中的数据插入到数据库并可以对它进行增删查改了(复制时注意外部表和内部表的列以及类型、长度的对应关系!)
在开始前需强调的是:外部表不要加任何约束(主键、外键、唯一约束等全都不行),否则会报错:
1.我们需要一个外部文件db_student.csv,这里放着我们要导入的数据,部分内容如下(数据是老师给的,我也不知道涉不涉及别人的隐私,统一打一下码吧)
2.创建一个目录对象
CREATE OR REPLACE DIRECTORY external_student AS 'D:\oraclefinalexam\external';
external_student :文件系统目录D:\oraclefinalexam\external的别名,这是我们要访问的数据文件db_student所在的目录
好吧,权限不够,我们连接到system用户,为staffuser(当前用户)授权
怎么授权呢?这还得问oracle
select distinct privilege from dba_sys_privs where privilege like '%DIRECTORY%';
第一项是删除目录的,第二项是创建目录的,现在就来授予staffuser用户创建目录的权限(可以顺便把删除目录的也给了):
回到staffuser用户,接着创建目录对象
3.创建外部表:
建表之前得先看下我们的数据呀
第一列为学号eg: 第二列专业编号 第三列姓名
第四列性别,第五列出生日期,第六列为空列,对应班级号
第七列家庭住址,第八列邮政编码,第九列通讯地址
第十列电话,第十一列应该是邮箱地址的,文件中没有给出
然后对照一下我预先在oracle中建好的表有哪些字段(我们称之为内部表吧)
接着我们来创建外部表:
默认情况下,允许出现的错误个数为0,所以错误内容为“以达到拒绝限制值”
在将源数据文件中的数据类型转换为表定义的列数据类型的时候,有时候会出现错误,例如指定的分隔符不符合要求(eg:在外部文件中的字段分隔符为英文逗号(,),而创建外部表的时候却指定分隔符为中文逗号,这就会导致数据类型出错,在创建外部表时,可以指定一些子句来对外部表进行处理,如reject limit,badfile(或 nobadfile),logfile(或nologfile)等)
解决方法:在末尾加一句 REJECT LIMIT UNLIMITED;
CREATE TABLE ext_student (
register_no VARCHAR2(12),
major_no VARCHAR2(10), --db_major的外键
s_name CHAR(8),
s_gender CHAR(2),
s_dateofbirth DATE,
s_class NUMBER(1),
s_address VARCHAR2(50),
s_postcode VARCHAR2(6),
s_mail_address VARCHAR2(50),
s_tele VARCHAR2(15)
--s_email VARCHAR2(30)
) ORGANIZATION EXTERNAL (
TYPE oracle_loader
DEFAULT DIRECTORY external_student
ACCESS PARAMETERS (
FIELDS TERMINATED BY ','
MISSING FIELD VALUES ARE null)
LOCATION('db_student.csv')
) REJECT LIMIT UNLIMITED;
4.使用select语句查询外部表中的数据:
emmmmm,虽然不再提示错误,但是返回0行数据,这是因为虽然不限制可以出现错误的个数,但如果数据类型转换失败,源文件数据还是无法被读取到表的相应列中;
在我们数据中,日期格式如下,我们建表时用的是DATE类型,但是oracle对插入DATE类型的数据格式有严格要求https://blog.csdn.net/beyondlpf/article/details/6959139,这样是无法直接插进去的,我的解决方法是修改数据类型
修改字段类型DATE为VARCHAR2,长度20
把内部表的也改一下:
依然还是未选定行?因为我的学号的长度为12,但是我们外部文件的学号这一列中,每一个值都多了一个空格,所以长度应该为13
修改长度(内部表可以不改,复制数据的时候直接用trim函数去掉空格即可)
看下这回还会有啥问题:
数据是出来了,但是不太好看,用set linesize 1000 设置一下每行输出字符数为1000 (自己觉得舒服就行),再来查:
5.OK,接下来要考虑如何将这些数据复制到内部表里面了!
--db_student是内部表,是一个待插入数据的空表
--ext_student是我们的外部表,这里放的是我们要复制到db_student中的数据
insert into db_student (register_no,major_no,s_name,s_gender,s_dateofbirth,s_class,s_address,s_postcode,s_mail_address,s_tele)
select trim(register_no),major_no,s_name,s_gender,s_dateofbirth,s_class,s_address,s_postcode,s_mail_address,s_tele from ext_student ;
报错:
ORA-29913: 执行 ODCIEXTTABLEFETCH 调出时出错
ORA-00001: 违反唯一约束条件 (STAFFUSER.SYS_C0011113)
打开CSV文件发现有大量重复数据,可能数据被破坏了,重新复制一份源数据进来,覆盖掉它
完成!