插入记录

版权声明:--------- 版权声明:本文为博主原创文章,转载请附上博文链接! https://blog.csdn.net/wangxw1803/article/details/85123109

数据操纵语言DML

当需要向数据库中添加、更新或删除数据时,需要执行数据库操纵语言DML。DML是SQL的核心部分,它包含如下几种常见的操作语句

  • INSERT:向表中添加行
  • UPDATE:更新存储在表中的数据
  • DELETE:删除现有的行
  • MERGE:插入所有的行到另一个具有现存记录的表,如果要插入的行的健匹配已存在行,则更新已存在的行而不是插入一个新行
  • 在操作DML语句通常一次只能操作一个表,使用INSERT或者MERGE的变体也允许同时对多个表进行插入
  • 用户必须具有在要使的DML语句的表上的权限,比如用户自己所在方案下的表
  • 如果列具有NOT NULL约束,在使用DML语句时,比如INSERT或UPDATE要为具有约束的列指定值
  • Oracle在用户显示地使用COMMIT语句时,才会将用户所做的更改保存回数据库,否则用户可以使用ROLLBACK语句撤销所做的任何修改

插入默认值和NULL值

默认值是在定义数据表时指定的值,如果未指定默认值DEFAULT选项,并且其NOT NULL没有被指定为True,那么将默认为NULL值,可以通过desc + 表明来查看表的架构定义
在使用INSERT语句插入数据时,需要注意避免一些常见的错误

  • 对于NOT NULL列缺少强制的值:比如不允许NOT NULL的列中指定的NULL值
  • 重复值违反了唯一性约束:列中已存在为一值,又输入新的唯一值
  • 违反外键约束:输入的值不匹配主外键关联关系
  • 违反CHECK约束:输入不匹配CHECK约束的表达式的值
  • 数据类型不匹配:数据类型不匹配
  • 值的宽度超过了列的限制:字符长度超出限制
    如果要插入不匹配的类型,可以为列值应用转换函数来使得列值的类型匹配,或者使用系统函数来为列提供列值

使用子查询插入多行数据

通过INSERT INTO-VALUES一次只能向表中插入一行记录 ,如果要从一个已经存在的表中插入一行或多行记录,可以在INSERT语句中使用子查询从已存在的一个或多个表中复制数据

CREATE TABLE emp_copy AS SELECT * FROM emp WHERE deptno = 20;

由于emp_copy表的结构与emp完全一样,因此既可以使用SELECT * 语句进行表数据的复制,也可以在表明后制定列明

INSERT INTO emp_copy (empno, ename, job, mgr, deptno)
	SELECT empno,ename,job,mgr,deptno
	FROM emp
	WHERE deptno = 30;

使用INSERT插入多表数据

INSERT { FIRST|ALL}
	[WHEN condition THEN ] INTO table [VALUES(...)] 
	[WHEN condition THEN ] INTO table [VALUES(...)] 
	...
	ELSE INTO table [VALUES(...)]
	subquery;

语句关键字含义如下:

  • FIRST:如果的一个WHEN子句的值为True,Oracle服务器对于给定的行执行相应的INTO子句,并且跳过后面的WHEN子句
  • ALL:Oracle服务器通过相应的WHEN条件过滤每一个插入子句,确定是否执行这插入子句
  • ELSE:如果条件都不满足,则执行ELSE中的插入子句
  • subquery:要进行多表插入的子查询
INSERT FIRST
	WHEN deptno = 10 THEN INTO emp_dept_10
	WHEN deptno = 20 THEN INTO emp_dept_20
	WHEN deptno = 30 THEN INTO emp_dept_30
	ELSE INTO emp_copy
	SELECT * FROM emp;

可以为要插入的表指定要插入的列

INSERT FIRST
	WHEN deptno = 10 THEN INTO emp_dept_10(empno, ename, sal, deptno)
							VALUES(empno, ename, sal, deptno)
	WHEN deptno = 20 THEN INTO emp_dept_20 emp_dept_10(empno, ename, sal, deptno)
							VALUES(empno, ename, sal, deptno)
	WHEN deptno = 30 THEN INTO emp_dept_30 emp_dept_10(empno, ename, sal, deptno)
							VALUES(empno, ename, sal, deptno)
	ELSE INTO emp_copy emp_dept_10(empno, ename, sal, deptno)
							VALUES(empno, ename, sal, deptno)
	SELECT * FROM emp;

更新记录

使用DML语言中的UPDATE语句可以很容易的对单行数据进行更新

UPDATE table 
SET column = value [, column = value, ...]
[WHERE condition];

使用SET column = value对旧列值赋新的列值,value可以是相应的值或对应列的子查询,WHERE子句中的condition确定要被更新的行,由列名,表达式,常数和比较操作符组成

UPDATE emp SET sal = 3000 WHERE empno = 7369;
UPDATE emp SET sal=3000, comm=200, mgr=7566 WHERE empno=7369

使用子查询更新记录

UPDATE emp x 
				SET x.sal = ( SELECT AVG (y.sal)
							FROM emp y
							WHERE y.deptno = x.deptno)
				WHERE x.deptno = 7369;
UPDATE emp
	SET sal = (SELECT sal
				FROM emp
				WHERE empno = 7782)
	WHERE empno = 7369
UPDATE emp x
	SET (x.sal, x.comm) = (SELECT AVG(y.sal), MAX(y.comm)
							FROM emp y
							WHERE y.deptno = x.deptno)
	WHERE x.deptno = 7369;
update emp_new x 
	SET (x.sal, x.comm) = (select sal, comm 
							from scott.emp y 
							where y.empno = x.empno)
	where x.deptno = 7369;
update (select x.sal sal, y.sal sal_new, x.comm comm, y.comm comm_new 
		from scott.emp x, emp_new y
		where x.empno = y.empno and x.empno = 7369)
	SET sal_new = sal,
		comm_new = comm;

第二种写法要求emp_new中具有主键列,也就是说不可以出现连个相同的empno编号,否则Oracle会提示错误。emp_new极有可能出现两条相同的记录,因为该表不存在主键列,但是可以使用Oracle的Hint。可以叫上述语句更改为使用了Hint的语句来实现更新成功

update /*+bypass_ujvc*/(select x.sal sal, y.sal sal_new, x.comm comm, y.comm comm_new 
		from scott.emp x, emp_new y
		where x.empno = y.empno and x.empno = 7369)
	SET sal_new = sal,
		comm_new = comm;

注:Hint时Oracle提供的一种SQL语法,它允许用户在SQL语句中插入相关的语法,从而影响SQL的执行方式;oracle可以使用hints:/+ BYPASS_UJVC/ 屏蔽掉队唯一性的检查。

使用MERGE合并表行

MERGE如其名字所示,提供了在多个表之间合并数据的能力,使用该语句可以有条件的更新和插入到数据库表中,在插入数据时,如果行存在,则执行update语句进行更新,如果是一个新的行,则执行insert语句进行插入
由于MERGE命令组合了INSERT和UPDATE命令,因而需要有对目标表的INSERT和UPDATE权限,以及对源表的SELECT权限

MERGE INTO table_name table_alias
USING (table|view|sub_query) alias
ONjoin condition)
WHEN MATCHED THEN
UPDATE SET 
col1 = col_val1,
col2 = col2_val
WHEN NOT MATCHED THEN
INSERT (column_list)
VALUES (column_values);

语法中的关键字含义

  • MERGE INTO子句:指定正在更新或插入的目标表
  • USING子句:指定数据源要被更新或插入的数据来源,数据来源可以是表、视图或子查询
  • ON子句:后跟条件语句,指定MERGE操作可以更新或插入
  • WHEN MATCHED|WHEN NOT MATCHED:指示当匹配时,应该执行UPDATE子句进行更新,当不匹配时,应该执行INSERT语句进行插入
    为了让emp_new与emp保持一致,对于存在的记录进行更新,对于不存在的记录进行删除,可以使用MERGE合并语法
MERGE INTO emp_new c		--目标表
	USING scott.emp e		--源表
	ON (c.EMPNO = e.empno)
	WHEN MATCHED THEN 	--当匹配时,进行UPDAET操作
		UPDATE 
			SET c.ename = e.ename,c.job = e.job, c.mgr = e.mgr,
				c.hiredate = e.hiredate, c.sal = e.sal,
				c.comm = e.comm,c.deptno = e.deptno
	WHEN NOT MATCHED THEN --当不匹配时,进行INSERT操作
		INSERT 
		VALUES (e.empno,e.ename,e.job,e.mgr,e.hiredate,e.sal,e.comm,e.deptno);

删除记录

使用DELETE语句删除单行记录时,注意以下要点

  • DELETE语句一次只能删除整行记录,不能删除某个字段
  • 与INSERT和UPDATE一样,删除一个表中的记录可能会导致与其他表的引用完整性问题
  • DELETE语句只会删除记录,不会删除表,如果要删除整个表,需使用DROP TBALE命令
  • 如果要一次性清除表中的数据,并且不许需要撤销删除,可以使用TRUNCATE一次性对表数据进行清除
DELETE [FROM] table [WHERE condition];

table指定要删除的表名称,WHERE子句中的condition表示被删除的行,由字段名、表达式、常数和比较操作符组成

DELETE FROM emp WHERE empno = 7903;

如果哟啊删除的行存在主外键约束,比如dept表的deptno被emp表的deptno所引用,要删除dept表中的某个的平台弄记录时,Oracle会触发异常
OAR-02292:违反完整约束条件 (SCOTT.PK_DEPTNO) - 已找到子记录
所以要先删除与其相关的子记录。

使用子查询删除记录

对于复杂的记录删除,可以使用子查询来删除基于另一个表的行

DELETE FROM scott.emp
	WHERE deptno = (SELECT deptno From dept 
					 WHERE dname = 'SALES')

在子查询中,查询dept表中dname为销售部员工记录,以返回的deptno作为DELETE语句的WHERE子句条件进行删除
可以在WHERE条件中应用IN或EXISTS来删除在其它表中粗内在的记录

使用TUNCATE清除数据

除了可以使用DELETE删除表中的内容外,还可以使用TRUNCATE语句,该语句会删除表中所有行,并且释放该表所使用的存储空间
注:TRUNCATE实际上并不是DML数据操纵语言的一部分,它属于DDL数据定义语言,与CREATE TABLE等语句一样,它不具有撤销功能,已经调用,表中的数据便会被彻底清除

TRUNCATE TABLE table_name

与DELETE相比,使用TRUNCATE命令速度要快一些,这是由如下3个原因决定的

  • TRUNCATE语句不会激活表删除触发器
  • TRUNCATE语句属于数据定义语言DDL语句,不会产生撤销信息
  • 如果表是主外键关系的主表,则无法清除表的内容,必须在执行TRUNCATE语句之前禁用该约束
    注:TRUNCATE属于DDL语句,因此不能被PL/SQL语句块直接调用,必须要使用动态语句调用方式
    为了能正确的清除表内容,必须首先禁用约束,然后使用TRUNCATE TABLE进行表内容的清除
ALTER TABLE dept DISABLE CONSTRAINT pk_dept CASCADE;

猜你喜欢

转载自blog.csdn.net/wangxw1803/article/details/85123109