【SQL开发实战技巧】系列(八):聊聊如何插入数据时比约束更灵活的限制数据插入以及怎么一个insert语句同时插入多张表

简介: 插入数据、阻止对某几列插入的实现、复制表的定义和数据以及注意事项、比创建约束功能更强大!用 WITH CHECK OPTION限制数据录入、如何一个insert将数据同时插入多个表【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。但是!ORA - 01723 : 不允许长度为 0 的列。

前言

本篇文章讲解的主要内容是:插入数据、阻止对某几列插入的实现、复制表的定义和数据以及注意事项、比创建约束功能更强大!用 WITH CHECK OPTION限制数据录入、如何一个insert将数据同时插入多个表
【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。


一、插入数据

先创建一个测试表,然后插入一条数据

create table test(
aa varchar2(20) default 'aa',
bb varchar2(20) default 'bb',
cc varchar2(20) default 'cc',
dd date default sysdate
);
insert into test(aa,bb,cc) values(default,null,'zyd');
 SQL> select * from test;

AA                   BB                   CC                   DD
-------------------- -------------------- -------------------- -----------
aa                                        zyd                  2023-2-7 16

注意以下几点:

  1. 如果INSERT语句中没有含默认值的列,则会添加默认值,如dd列。
  2. 如果包含有默认值的列,需要用DEFAULT关键字,才会添加默认值,如aa列。
  3. 如果已显示设定了NULL或其他值,则不会再生成默认值,如bb列。
  4. 建立表时,有时明明设定了默认值,可生成的数据还是NULL,原因在于我们在代码中不知不觉地加入了NULL。

二、阻止对某几列插入

这种需求我们可以创建一个视图,视图中暴露出来可以变更的列,然后DML操作均基于此视图来做,看下面这个案例:

SQL> insert into vtest values('a','b',sysdate);

1 row inserted


SQL> select * from vtest;

AA                   BB                   DD
-------------------- -------------------- -----------
aa                                        2023-2-7 16
a                    b                    2023-2-7 16

SQL> insert into vtest values('c',default,sysdate);
insert into vtest values('c',default,sysdate)

ORA-32575: 对于正在修改的视图, 不支持显式列默认设置

ok,看上面的操作我们可以通过视图实现需求,但是视图这种方式有个弊端就是通过VIEW新增数据,不能再使用关键字DEFAULT

三、复制表的定义和数据以及注意事项

我们可以用以下语句复制表 TEST:

create table  test2 as select * from test;

也可以先复制表的定义,再新增数据:

create table test3 as select * from test where 1=2;
insert into test3 select * from test;

但是!看下面这个操作:

SQL> create table test4 as
  2  select '1' as aa, null bb, '' cc, sysdate dd from test;
create table test4 as
select '1' as aa, null bb, '' cc, sysdate dd from test

ORA-01723: 不允许长度为 0 的列

当我们CTAS操作的时候,如果你的字段中包含null时候,会创建失败,因为你没有指定这个列的数据类型, oracle咋个推断你的数据类型呢?

四、比创建约束功能更强大!用 WITH CHECK OPTION限制数据录入

当约束条件比较简单时,可以直接加在表中,如工资必须>0:

SQL> alter table emp add constraints ck_sal check(sal > 0);
Table altered

但有些复杂或特殊的约束条件是不能这样放在表里的,如雇佣日期大于当前日期

SQL> alter table emp add constraints ck_hiredate check(hiredate>sysdate);

ORA-02436: 日期或系统变量在 CHECK 约束条件中指定错误

这时我们可以使用加了WITH CHECK OPTION关键字的VIEW来达到目的。下面的示例中,我们限制了不符合内联视图条件的数据(SYSDATE+1)

SQL> insert into (
  2  select * from test where dd<=sysdate with check option
  3  )
  4  select 'a1','b1','c1',sysdate
  5  from dual;

1 row inserted


SQL> select * from test;

AA                   BB                   CC                   DD
-------------------- -------------------- -------------------- -----------
aa                                        zyd                  2023-2-7 16
a                    b                    cc                   2023-2-7 16
a1                   b1                   c1                   2023-2-7 17


SQL> rollback;

Rollback complete


SQL> select * from test;

AA                   BB                   CC                   DD
-------------------- -------------------- -------------------- -----------
aa                                        zyd                  2023-2-7 16
a                    b                    cc                   2023-2-7 16

SQL> 
SQL> insert into (
  2  select * from test where dd<=sysdate with check option
  3  )
  4  select 'a1','b1','c1',sysdate+1
  5  from dual;
insert into (
select * from test where dd<=sysdate with check option
)
select 'a1','b1','c1',sysdate+1
from dual

ORA-01402: 视图 WITH CHECK OPTION where 子句违规

因为里面有关键字WITH CHECK OPTION,所以INSERT的数据不符合其中的条件(hiredate<=SYSDATE)时,就不允许利用INSERT。
当规则较复杂,无法用约束实现时,这种限制方式就比较有用。

五、如何一个insert将数据同时插入多个表

多表插入语句分为以下四种:

  • 无条件INSERT
  • 有条件INSERT ALL
  • 转置INSERT
  • 有条件INSERT FIRST

接下来先创建两个临时表

create table empa as select empno,ename,job from emp where 1=2;
create table empb as select empno,ename,deptno from emp where 1=2;
  • 无条件INSERT
INSERT ALL
into empa(empno,ename,job)VALUES(empno,ename,job)
into empb(empno,ename,deptno)VALUES(empno,ename,deptno)
SELECT empno,ename,job,deptno FROM emp WHERE deptno in (10,20);
16 rows inserted

SQL> select * from empa;

EMPNO ENAME      JOB
----- ---------- ---------
 7369 SMITH      CLERK
 7566 JONES      MANAGER
 7782 CLARK      MANAGER
 7788 SCOTT      ANALYST
 7839 KING       PRESIDENT
 7876 ADAMS      CLERK
 7902 FORD       ANALYST
 7934 MILLER     CLERK

8 rows selected


SQL> select * from empb;

EMPNO ENAME      DEPTNO
----- ---------- ------
 7369 SMITH          20
 7566 JONES          20
 7782 CLARK          10
 7788 SCOTT          20
 7839 KING           10
 7876 ADAMS          20
 7902 FORD           20
 7934 MILLER         10

8 rows selected


SQL> rollback;

Rollback complete

因为没有加条件,所以会同时向两个表中插入数据,且两个表中插入的条数一样。

  • 有条件 INSERT ALL
INSERT ALL
when job in('SALESMAN','MANAGER') then 
into empa(empno,ename,job)VALUES(empno,ename,job)
when deptno in('20','30')then
into empb(empno,ename,deptno)VALUES(empno,ename,deptno)
SELECT empno,ename,job,deptno FROM emp WHERE deptno in (10,20);
7 rows inserted


SQL> select * from empa;

EMPNO ENAME      JOB
----- ---------- ---------
 7566 JONES      MANAGER
 7782 CLARK      MANAGER

SQL> select * from empb;

EMPNO ENAME      DEPTNO
----- ---------- ------
 7369 SMITH          20
 7566 JONES          20
 7788 SCOTT          20
 7876 ADAMS          20
 7902 FORD           20

SQL> rollback;

Rollback complete

当增加条件后,就会按条件插入。如EMPNO=7654等数据在两个表中都有。

  • INSERT FIRST就不一样
INSERT FIRST
when job in('SALESMAN','MANAGER') then 
into empa(empno,ename,job)VALUES(empno,ename,job)
when deptno in('20','30')then
into empb(empno,ename,deptno)VALUES(empno,ename,deptno)
SELECT empno,ename,job,deptno FROM emp WHERE deptno in (10,20);

6 rows inserted


SQL> select * from empa;

EMPNO ENAME      JOB
----- ---------- ---------
 7566 JONES      MANAGER
 7782 CLARK      MANAGER

SQL> select * from empb;

EMPNO ENAME      DEPTNO
----- ---------- ------
 7369 SMITH          20
 7788 SCOTT          20
 7876 ADAMS          20
 7902 FORD           20

SQL> rollback;

INSERT FIRST语句中,当第一个表符合条件后,第二个表将不再插入对应的行,表empb中不再有与表empa相同的数据EMPN0=7654,这就是INSERT FIRSTINSERT ALL的不同之处。

  • 转置INSERT与其说是一个分类,不如算作"INSERT ALL"的一个用法。

创建一个临时表

create table deptb(
dname varchar2(200),
remark  varchar2(200)
);
insert all 
into deptb values(aa,'aa')
into deptb values(bb,'bb')
into deptb values(cc,'cc')
select * from (select 'zhaoyd' aa,'zhaoyandong' bb ,'赵延东'cc from dual 
);
SQL> select * from deptb;

DNAME                                                                            REMARK
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
zhaoyd                                                                           aa
zhaoyandong                                                                      bb
赵延东                                                                           cc

可以看到,转置INSERT的实质就是把不同列的数据插入到同一表的不同行中。


总结

本章主要是介绍关于insert的一系列常用操作。

相关文章
|
4月前
|
SQL 人工智能 JSON
Flink 2.1 SQL:解锁实时数据与AI集成,实现可扩展流处理
简介:本文整理自阿里云高级技术专家李麟在Flink Forward Asia 2025新加坡站的分享,介绍了Flink 2.1 SQL在实时数据处理与AI融合方面的关键进展,包括AI函数集成、Join优化及未来发展方向,助力构建高效实时AI管道。
807 43
|
4月前
|
SQL 人工智能 JSON
Flink 2.1 SQL:解锁实时数据与AI集成,实现可扩展流处理
本文整理自阿里云的高级技术专家、Apache Flink PMC 成员李麟老师在 Flink Forward Asia 2025 新加坡[1]站 —— 实时 AI 专场中的分享。将带来关于 Flink 2.1 版本中 SQL 在实时数据处理和 AI 方面进展的话题。
294 0
Flink 2.1 SQL:解锁实时数据与AI集成,实现可扩展流处理
|
5月前
|
SQL
SQL如何只让特定列中只显示一行数据
SQL如何只让特定列中只显示一行数据
|
5月前
|
SQL
SQL中如何删除指定查询出来的数据
SQL中如何删除指定查询出来的数据
|
5月前
|
SQL 关系型数据库 MySQL
SQL如何对不同表的数据进行更新
本文介绍了如何将表A的Col1数据更新到表B的Col1中,分别提供了Microsoft SQL和MySQL的实现方法,并探讨了多表合并后更新的优化方式,如使用MERGE语句提升效率。适用于数据库数据同步与批量更新场景。
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
538 13
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。
361 9
|
SQL 存储 网络安全
关系数据库SQLserver 安装 SQL Server
【7月更文挑战第26天】
260 6
|
SQL Oracle 关系型数据库
MySQL、SQL Server和Oracle数据库安装部署教程
数据库的安装部署教程因不同的数据库管理系统(DBMS)而异,以下将以MySQL、SQL Server和Oracle为例,分别概述其安装部署的基本步骤。请注意,由于软件版本和操作系统的不同,具体步骤可能会有所变化。
1180 3