目录
表的插入、更新、删除、合并操作
7.4.1 插入新的记录
7.4.2 插入含自增列的记录
7.4.3 插入新的多条记录
7.4.4 同时往多个表插入记录
7.4.5 通过其它表插入
7.4.6 通过多表关联插入
7.4.7 通过视图插入
7.4.8 插入手工数据
7.4.9 插入默认值
7.4.10 仅复制表结构
7.4.11 更新表的记录
7.4.12 通过表关联更新表
7.4.13 通过表关联更新多个字段
7.4.14 通过表关联更新多个表多个字段
7.4.15 按照默认值更新表
7.4.16 删除表中所有记录
7.4.17 按照条件删除表中记录
7.4.18 清空表中记录
7.4.19 通过表关联删除记录
7.4.20 通过表关联删除多张表
7.4.21 合并表中数据
7.4 表的插入、更新、删除、合并操作
注:数据集和表结构见 SQL基础操作_1_检索数据
7.4.1 插入新的记录
需求:向dept表中插入部门编号为50,部门名称为Production,部门位置为Shanghai的数据.
解决方法:这里通过INSERT INTO TableName VALUES (…)
Mysql、Sql server、Oracle:
INSERT INTO dept VALUES (50,'Production','Shanghai');
注:这里表dept的定义没有自增字段,如果有请详见下面的解决方案.
7.4.2 插入含自增列的记录
需求:向dept表中插入部门编号为50,部门名称为Production,部门位置为Shanghai的数据.
解决方法:这里通过INSERT INTO TableName VALUES (…),这里表dept的deptno字段定义的是自增.
MySql:
INSERT INTO dept VALUES (50,'Production','Shanghai');
Mysql虽然在字段定义时约束了自增,但是在插入自增数据时依然可以显示的插入,只要自增字段的值不和已有的数据重复即可.
如果插入的重复的自增字段数据,则会有类似如下的报错:
Duplicate entry '50' for key'PRIMARY'
SQL Server:
INSERT INTO dept VALUES (50,'Production','Shanghai');
消息 8101,级别 16,状态 1,第 2 行
仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'dept'中的标识列指定显式值。
问题原因:
dept表的deptno字段设置了自增模式,而默认默认情况下对自增字段的插入是数据库自己维护的,所以当用户手动指定时则会抛出该异常.
create table dept(
deptno int IDENTITY(1,1) NOT NULL,
dname varchar(15),
loc varchar(50),
primary key(deptno)
);
解决该问题有3种办法:
1) 修改表结构的定义,去掉表的自增属性。不建议。
2) 只插入除自增外的其他字段,让数据库自行维护自增字段。建议。
3) 通过打开表的IDENTITY_INSERT开关,显示插入指定的自增字段。建议.
其中第三种方法的实现代码见下:
SET IDENTITY_INSERT dept ON;
GO
INSERT INTO dept(deptno,dname,loc) VALUES (50,'Production','Shanghai')
SET IDENTITY_INSERT dept OFF;
GO
Oracle:
Oracle里对于自增字段的维护麻烦点,因为它没有对应的关键字.不过我们可以通过内置的数据库对象sequence来实现.具体实现见下:
create sequence dept_autoinc
minvalue 50
maxvalue 9999999999999999999999999999
startwith 50
incrementby 10
nocache;
INSERT INTO dept VALUES (dept_autoinc.nextval,'Production','Shanghai');
DEPTNO | DNAME | LOC |
10 | ACCOUNTING | NEW YORK |
20 | RESEARCH | DALLAS |
30 | SALES | CHICAGO |
40 | OPERATIONS | BOSTON |
50 | Production | Shanghai |
7.4.3 插入新的多条记录
需求:向dept表中插入部门编号为50,部门名称为Production,部门位置为Shanghai和部门编号为60,部门名称为Programming,部门位置为Beijing的数据.
解决方法:这里通过INSERT INTO TableName VALUES (…),(…),(…)
Sql server 、Mysql:
INSERT INTO dept VALUES (50,'Production','Shanghai'), (60,'Programming','Beijing');
Oracle:
INSERT ALL INTO dept VALUES (50,'Production','Shanghai')
INTO dept VALUES (60,'Programming','Beijing')
select 1 from dual;
7.4.4 同时往多个表插入记录
需求:从dept表里插入数据到3张表,当loc是NEW YORK和BOSTON时向dept_east表中插入,当当loc是CHICAGO时向dept_mid表中插入,其它情况往dept_west表中插入.
解决方法:这里通过INSERT ALL WHEN Condition THEN INTO TABLENAME VALUES (…)的方式.
Oracle:
CREATE TABLE dept_east
(DEPTNO NUMBER(2),
DNAME VARCHAR2(14),
LOC VARCHAR2(13));
CREATE TABLE dept_mid
(DEPTNO NUMBER(2),
DNAME VARCHAR2(14),
LOC VARCHAR2(13));
CREATE TABLE dept_west
(DEPTNO NUMBER(2),
DNAME VARCHAR2(14),
LOC VARCHAR2(13));
INSERT ALL
WHEN loc IN ('NEW YORK','BOSTON') THEN
INTO dept_east(deptno,dname,loc) VALUES (deptno,dname,loc)
WHEN loc IN ('CHICAGO') THEN
INTO dept_mid(deptno,dname,loc) VALUES (deptno,dname,loc)
ELSE
INTO dept_west (deptno,dname,loc) VALUES (deptno,dname,loc)
SELECT deptno,dname,loc FROM dept
我们可以通过如下的SQL,清晰的看到分散到3个表的数据:
SELECT A.*,'dept_east' AS TableSource FROM dept_east A
UNION ALL
SELECT A.*,'dept_mid' AS TableSource FROM dept_mid A
UNION ALL
SELECT A.*,'dept_west' AS TableSource FROM dept_west A;
DEPTNO | DNAME | LOC | TABLESOURCE |
10 | ACCOUNTING | NEW YORK | dept_east |
40 | OPERATIONS | BOSTON | dept_east |
30 | SALES | CHICAGO | dept_mid |
20 | RESEARCH | DALLAS | dept_west |
注: 截止目前,仅oracle支持该语法.
7.4.5 通过其它表插入
需求:向dept表中插入部门编号为50,部门名称为Production,部门位置为Shanghai的数据.这里需要指定通过SELECT其它表的方式插入
解决方法:这里通过INSERT INTO TableName SELECT ColumnName FROM TableName …
如果我们想将一个表或则多个表的数据插入到另外一张新的表,也可以通过INSERT INTO TableName SELECT的方式.
Sql server 、Mysql:
CREATE TABLE temp(
deptno varchar(50) NULL,
deptname varchar(50) NULL,
loc varchar(50) NULL,
empno varchar(50) NULL,
ename varchar(50) NULL,
sal int NULL
);
Oracle:
CREATE TABLE temp(
deptno varchar2(50) NULL,
deptname varchar2(50) NULL,
loc varchar2(50) NULL,
empno varchar2(50) NULL,
ename varchar2(50) NULL,
sal int NULL
);
Sql server 、Mysql、Oracle:
INSERT INTO temp(deptno,deptname,loc)
SELECT deptno,dname,loc
FROM dept
WHERE dname in ('SALES','OPERATIONS')
7.4.6 通过多表关联插入
需求:通过dept和emp表向temp表中部门名称为RESEARCH何ACCOUNTING0的数据.这里temp表的字段来自dept表和emp表.
解决方法:这里通过INSERT INTO TableName SELECT ColumnName FROM TableA JOIN TableB …
Sql server 、Oracle、Mysql:
INSERT INTO temp(deptno,deptname,loc,empno,ename)
SELECT A.deptno,A.dname,A.loc,B.EMPNO,B.ename
FROM dept A
JOIN emp B
ON A.DEPTNO = B.Deptno
WHERE A.dname in ('RESEARCH','ACCOUNTING')
ORDER BY A.deptno;
--或者
INSERT INTO temp(deptno,deptname,loc,empno,ename)
SELECT A.deptno,A.dname,A.loc,B.EMPNO,B.ename
FROM dept A,emp B
WHERE A.DEPTNO = B.Deptno
AND A.dname IN ('RESEARCH','ACCOUNTING')
ORDER BY A.deptno;
7.4.7 通过视图插入
需求:向dept表中插入部门编号为60,部门名称为Testing,部门位置为Guangzhou的数据.这里需要指定通过借助视图的方式插入.
解决方法:这里需要先建立一张视图,然后往视图里插入数据.
Sql server、Mysql、Oracle:
CREATE VIEW v_deptAS
SELECT deptno,deptname,loc FROM temp;
INSERT INTOv_dept VALUES (60,'Testing','Guangzhou');
SELECT * FROM temp;
执行结果:
deptno | deptname | loc | empno | ename |
50 | Production | Nanjing | 7369 | SMITH |
60 | Testing | Guangzhou | NULL | NULL |
7.4.8 插入手工数据
需求:向dept表中插入部门编号为50,部门名称为Production,部门位置为Shanghai和部门编号为60,部门名称为Programming,部门位置为Beijing的数据.
解决方法:这里通过INSERT INTO TableName SELECT value1,value2 UNION ALL SELECT … 的方式来事项该功能.
Mysql、Sql server:
INSERT INTO dept(deptno,dname,loc)
SELECT 50,'Production','Shanghai'
UNION ALL
SELECT 60,'Programming','Beijing';
注:这里假设SQL Server里的dept表已经开启SET IDENTITY_INSERT dept ON或者deptno不是自增字段.
Oracle:
INSERT INTO dept(deptno,dname,loc)
SELECT 50,'Production','Shanghai' FROM DUAL
UNION ALL
SELECT 60,'Programming','Beijing' FROM DUAL;
7.4.9 插入默认值
需求:指定dept表loc字段的默认值是Beijing,并向该表中插入部门编号为50,部门名称为Production的数据.
解决方法:这里需要DDL的里知识,即对表dept在loc这列新增个默认值的约束.当我们不去插入loc这列时数据库会自动补充默认约束里定义的值.
SQL Server:
ALTER TABLE dept add CONSTRAINT DF_dept_loc DEFAULT 'Beijing'FOR loc;
SET IDENTITY_INSERT dept ON;
GO
INSERT INTO dept(deptno,dname) VALUES (50,'Production');
SET IDENTITY_INSERT dept OFF;
GO
SELECT * FROM dept WHERE deptno=50;
执行结果:
deptno | dname | loc |
50 | Production | Beijing |
注:
1) 上述的insert语句,loc这列并没有显示维护,是数据库里的默认约束自动插入的.
2) 如果你的表里每一列都直接或间接定义了默认值,那么可以通过如下语句插入一个默认值:
INSERT INTO TableName DEFAULT VALUES;
完整例子见下:
IF OBJECT_ID('dbo.T1','U') IS NOT NULL
DROP TABLE dbo.T1;
GO
CREATE TABLE dbo.T1
(column_1 AS 'Computedcolumn ' + column_2,
column_2 varchar(30)
CONSTRAINT default_name DEFAULT ('my column default'),
column_3 rowversion,
column_4 varchar(40)NULL
);
GO
INSERT INTO T1 DEFAULT VALUES;
执行结果:
column_1 | column_2 | column_3 | column_4 |
Computed column my column default | my column default | 0x00000000000007D5 | NULL |
Mysql:
alter table dept alter loc set default 'Beijing';
INSERT INTO dept(deptno,dname) VALUES(50,'Production');
SELECT * FROM dept WHERE deptno=50;
deptno | dname | loc |
50 | Production | Beijing |
Oracle:
ALTER TABLE DEPT MODIFY LOC DEFAULT 'Beijing';
INSERT INTO dept(deptno,dname) VALUES (50,'Production');
SELECT * FROM dept WHERE deptno=50;
执行结果:
deptno | dname | loc |
50 | Production | Beijing |
7.4.10 仅复制表结构
需求:快速新建一个和dept结构一样的表dept_new,仅需要字段定义一致,不需要数据.
解决方法:这里通过SELECT * FROM TableName WHERE 1=0的方式仅拷贝到表结构,而没有数据.
Oracle、Mysql:
CREATE TABLE dept_new AS
SELECT * FROM dept
WHERE 1= 2;
Sql server:
SELECT * INTO dept_new FROM dept WHERE 1=0;
注: 如果想既复制表又复制数据,则不需要加WHERE 1=0的限制条件即可.
7.4.11 更新表的记录
需求:更新dept表里deptno为50的记录对应的loc字段为Nanjing
解决方法:这里通过UPDATE TableName SET ColName=.. WHERE …的方式来更新数据.
Oracle、Mysql、Sql server:
UPDATE dept
SET loc='Nanjing'
WHERE deptno=50;
注:
1) 如果想更新表中某个或某几个字段的所有记录,只要不加WHERE条件过滤即可.
2) 如果想更新多个字段,直接在SET后面跟字段等于相应的值即可.
7.4.12 通过表关联更新表
需求:更新emp表里的sal字段的值为temp表里的sal乘以1.5,这些员工号同时出现在在temp表中.
解决方法:这里通过UPDATE TableName SET ColName=..FROM TABLENAME1 A JOIN TABLENAME2 B … WHERE …的方式来更新数据.
Sql server:
TUNCATE TABLE temp;
INSERT INTO temp(deptno,deptname,loc,empno,ename,sal)
SELECT 50,'Production','Nanjing',7369,'SMITH',1000
BEGIN TRAN
SELECT empno,ename,sal FROM emp WHERE empno=7369;
UPDATE A
SET A.sal= B.sal*1.5
FROM emp A
JOIN temp B
ON A.empno= B.empno
SELECT empno,ename,sal FROM emp WHERE empno=7369;
ROLLBACK TRAN
执行更新前:
empno | ename | sal |
7369 | SMITH | 800.00 |
执行更新后:
empno | ename | sal |
7369 | SMITH | 1500.00 |
注:
这里的join方式也可以写成如下的形式:
UPDATE A
SET A.sal= B.sal*1.5
FROM emp A,temp B
WHERE A.empno= B.empno
Mysql:
TRUNCATE TABLE temp;
INSERT INTO temp(deptno,deptname,loc,empno,ename,sal)
SELECT 50,'Production','Nanjing',7369,'SMITH',1000
UPDATE emp A
INNER JOIN fridge.temp B
ON A.empno= B.empno
SET A.sal= B.sal*1.5
或者:
UPDATE emp,temp
SET emp.sal=temp.sal*1.5
WHERE emp.empno=temp.empno;
Oracle:
TRUNCATE TABLE temp;
INSERT INTO temp(deptno,deptname,loc,empno,ename,sal)
SELECT 50,'Production','Nanjing',7369,'SMITH',1000 FROM DUAL;
update emp a
set sal=(select b.sal*1.5from temp b whereb.empno=a.empno)
where exists (select1
from temp b
where b.empno=a.empno
)
SELECT empno,ename,sal FROM emp WHERE empno=7369;
结果跟上述相同.
7.4.13 通过表关联更新多个字段
需求:更新emp表里的sal字段的值为temp表里的sal乘以1.5,同时更新ename为temp表里的值, 匹配条件是两个表的deptno..
解决方法:这里通过UPDATE TableName SET ColName=..FROM TABLENAME1 A JOIN TABLENAME2 B … WHERE …的方式来更新数据.
Oracle:
TRUNCATE TABLE temp;
INSERT INTO temp(deptno,deptname,loc,empno,ename,sal)
SELECT 50,'Production','Nanjing',7369,'SMITH2',1000 FROM DUAL;
update emp a
set (sal,ename)=(select b.sal*1.5,b.enamefrom temp bwhereb.empno=a.empno)
where exists (select1
from temp b
where b.empno=a.empno
)
SELECT empno,ename,sal FROM emp WHERE empno=7369;
执行更新前:
Empno | ename | sal |
7369 | SMITH | 800.00 |
SELECT empno,ename,sal FROM emp WHERE empno=7369;
执行更新后:
empno | ename | sal |
7369 | SMITH2 | 1500.00 |
Sql Server:
TRUNCATE TABLE temp;
INSERT INTO temp(deptno,deptname,loc,empno,ename,sal)
SELECT 50,'Production','Nanjing',7369,'SMITH2',1000
BEGIN TRAN
SELECT empno,ename,sal FROM emp WHERE empno=7369;
UPDATE emp
SET emp.sal=b.sal*1.5,emp.ename=b.ename from emp a,temp b
WHERE a.empno= b.empno
UPDATE emp
SET emp.sal=b.sal*1.5,emp.ename=b.ename from emp a
JOIN temp b
ON a.empno= b.empno
SELECT empno,ename,sal FROM emp WHERE empno=7369;
ROLLBACK
执行更新前:
Empno | ename | sal |
7369 | SMITH | 800.00 |
执行更新后:
empno | ename | sal |
7369 | SMITH2 | 1500.00 |
Mysql:
BEGIN;
SELECT empno,ename,sal FROM emp WHERE empno=7369;
UPDATE emp a,temp b
SET a.sal=b.sal*1.5 ,a.ename=b.ename
WHERE a.empno= b.empno;
UPDATE emp a
INNER JOIN temp b
ON a.empno= b.empno
SET a.sal=b.sal*1.5 ,a.ename=b.ename;
SELECT empno,ename,sal FROM emp WHERE empno=7369;
ROLLBACK;
执行结果相同.
举一反三:这里多表关联时用到的是join(inner join),当然你也可以通过left join、right join以及不等值连接。
7.4.14 通过表关联更新多个表多个字段
更新emp表里的sal字段的值为temp表里的sal乘以1.5,同时更新temp表里ename为emp表里的值,匹配条件是两个表的deptno.
Mysql:
TRUNCATE TABLE temp;
INSERT INTO temp(deptno,deptname,loc,empno,ename,sal)
SELECT50,'Production','Nanjing',7369,'SMITH2',1000
BEGIN;
SELECT empno,ename,sal,'From_emp' as Table_Name FROM emp WHERE empno=7369
UNION
SELECT empno,ename,sal,'From_temp' as Table_Name FROM temp WHERE empno=7369;
UPDATE emp a,temp b
SET a.sal=b.sal*1.5 ,b.ename=a.ename
WHERE a.empno= b.empno;
UPDATE emp a
INNERJOIN temp b
ON a.empno= b.empno
SET a.sal=b.sal*1.5 ,b.ename=a.ename;
SELECT empno,ename,sal,'From_emp' as Table_Name FROM emp WHERE empno=7369
UNION
SELECT empno,ename,sal,'From_temp' as Table_Name FROM temp WHERE empno=7369;
ROLLBACK;
执行更新前:
empno | ename | sal | Table_Name |
7369 | SMITH | 800.00 | From_emp |
7369 | SMITH2 | 1000.00 | From_temp |
执行更新后:
empno | ename | sal | Table_Name |
7369 | SMITH | 1500.00 | From_emp |
7369 | SMITH | 1000.00 | From_temp |
注:Oracle和SQL Server里暂未发现该语法.
7.4.15 按照默认值更新表
需求:更新deptno对应是50的dept表的loc字段成默认值.
解决方法:这里通过UPDATE TableName SET ColName=DEFAULT …的方式来更新数据.
SQL Server:
BEGIN TRAN
SELECT * FROM dept WHERE deptno= 50;
UPDATE dept
SET loc = DEFAULT
WHERE deptno= 50;
SELECT * FROM dept WHERE deptno= 50;
ROLLBACK TRAN
MySQL:
BEGIN;
SELECT * FROM dept WHERE deptno=40;
UPDATE dept
SET loc=default
WHERE deptno=40;
SELECT * FROM dept WHERE deptno=40;
ROLLBACK;
Oracle:
SELECT * FROM dept WHERE deptno=40;
UPDATE dept
SET loc=default
WHERE deptno=40;
SELECT * FROM dept WHERE deptno=40;
ROLLBACK;
执行更新前:
deptno | dname | loc |
50 | Production | Nanjing |
执行更新后:
deptno | dname | loc |
50 | Production | Beijing |
7.4.16 删除表中所有记录
需求:删除dept表里的所有记录,但后期可通过数据库日志恢复.
解决方法:这里通过DELETE FROM TableName的方式来删除数据.
Oracle、Mysql、Sql server:
DELETE FROM dept;
DELETE * FROM dept;
7.4.17 按照条件删除表中记录
需求:删除dept表里deptno为50的记录,但后期可通过数据库日志恢复.
解决方法:这里通过DELETE FROM TableName WHERE Columname= …的方式来删除数据.
Oracle、Mysql、Sql server:
DELETE FROM dept WHERE deptno=50;
DELETE FROM dept WHERE deptno IN (50);
7.4.18 清空表中记录
需求:删除dept表里deptno为50的记录,但数据不可再恢复.
解决方法:这里通过TRUNCATE TABLE TableName方式来删除数据.
Oracle、Mysql、Sql server:
TRUNCATE TABLE dept;
7.4.19 通过表关联删除记录
需求:删除dept表里deptno和temp相同的记录,但数据可再恢复.
解决方法:这里通过DELETE FROM tableNAME A JOIN tableName B …方式来删除数据.
Sql server:
BEGIN TRAN
SELECT * FROM dept;
DELETE FROM dept
FROM dept A
JOIN temp B
ON A.deptno= B.deptno
SELECT * FROM dept;
ROLLBACK TRAN
Mysql:
BEGIN;
SELECT * FROM dept A;
-- JOIN temp B
-- ON A.deptno = B.deptno
DELETE A FROM dept A
INNER JOIN temp B
ON A.deptno= B.deptno AND B.deptno=40;
--或者见下
DELETE dept FROM dept,temp
WHERE dept.deptno= temp.deptno AND temp.deptno=40;
SELECT * FROM dept;
ROLLBACK;
不难发现,这里dept表里deptno=40的记录被删除了.
deptno | dname | loc |
10 | ACCOUNTING | NEW YORK |
20 | RESEARCH | DALLAS |
30 | SALES | CHICAGO |
50 | Production | Beijing |
Oracle:
INSERT INTO dept VALUES(50,'Production','Nanjing');
INSERT INTO temp(deptno,deptname,loc,empno,ename,sal)
SELECT 50,'Production','Nanjing',7369,'SMITH2',1000 FROM DUAL;
DELETE FROM dept WHERE EXISTS (SELECT 1 FROM TEMP WHERE dept.deptno = temp.deptno)
执行结果:
DEPTNO | DNAME | LOC |
10 | ACCOUNTING | NEW YORK |
20 | RESEARCH | DALLAS |
30 | SALES | CHICAGO |
40 | OPERATIONS | BOSTON |
7.4.20 通过表关联删除多张表
需求:删除dept表里deptno和temp相同的记录,但数据不可再恢复.
解决方法:这里通过DELETE FROM A,B FROM tableNAME A JOIN tableName B ON …方式来删除数据.
INSERT INTO dept VALUES(50,'Production','Nanjing');
INSERT INTO temp(deptno,deptname,loc,empno,ename,sal)
SELECT 50,'Production','Nanjing',7369,'SMITH2',1000;
BEGIN;
SELECT deptno,dname,loc,'tab_dept' as Table_Name FROM dept WHERE deptno=50
UNION ALL
SELECT deptno,deptname,loc,'tab_temp' as Table_Name FROM temp WHERE deptno=50;
DELETE A,B FROM dept A
INNER JOIN temp B
ON A.deptno= B.deptno AND B.deptno=50;
SELECT deptno,dname,loc,'tab_dept' as Table_Name FROM dept WHERE deptno=50
UNION ALL
SELECT deptno,deptname,loc,'tab_temp' as Table_Name FROM temp WHERE deptno=50;
ROLLBACK;
执行之前:
deptno | dname | loc | Table_Name |
50 | Production | Nanjing | tab_dept |
50 | Production | Nanjing | tab_temp |
执行之后, temp和dept这两张表里deptno为50的记录均被删除:
deptno | dname | loc | Table_Name |
注: SQL Server、Oracle目前未见相关语法。
7.4.21 合并表中数据
需求:如果emp_temp表中的员工存在于emp中,则将他们的提成(comm字段)更新为1000;
对于提成已经更新为1000的员工,如果他们的工资(SAL字段)少于2000,则从emp_temp表里删除他们;
其它情况从EMP表里取员工编号(EMPNO字段)、员工名称(ENAME字段)、部门号(DEPTNO字段)插入到emp_temp中.
Oracle:
CREATE TABLE emp_temp AS
SELECT deptno,empno,ename,comm FROM emp
WHERE empno IN (7782,7839,7934);
SELECT et.empno,et.ename,et.deptno,et.comm,emp.sal
FROM emp_temp et
JOIN emp
ON et.empno = emp.empno;
MERGE INTO emp_tempet
USING(SELECTempno,ename,deptno,comm,SAL FROM emp) emp
ON(et.empno = emp.empno)
WHEN MATCHED THEN
UPDATE SET et.comm=1000
DELETE WHERE (SAL<2000)
WHEN NOTMATCHED THEN
INSERT(et.empno,et.ename,et.deptno,et.comm)
VALUES(emp.empno,emp.ename,emp.deptno,emp.comm);
SELECT et.empno,et.ename,et.deptno,et.comm,emp.sal
FROM emp_tempet
JOIN emp
ON et.empno= emp.empno;
执行前:
EMPNO | ENAME | DEPTNO | COMM | SAL |
7782 | CLARK | 10 | 2450.00 | |
7839 | KING | 10 | 5000.00 | |
7934 | MILLER | 10 | 1300.00 |
执行后,emp_temp表里员工编号为7782和7839的comm被更新成了1000,而7934这条记录被删除了,其它情况的数据从emp表里插入了过来.
EMPNO | ENAME | DEPTNO | COMM | SAL |
7369 | SMITH | 20 | 1500.00 | |
7499 | ALLEN | 30 | 300.00 | 1600.00 |
7521 | WARD | 30 | 500.00 | 1250.00 |
7566 | JONES | 20 | 2975.00 | |
7654 | MARTIN | 30 | 1400.00 | 1250.00 |
7698 | BLAKE | 30 | 2850.00 | |
7782 | CLARK | 10 | 1000.00 | 2450.00 |
7788 | SCOTT | 20 | 3000.00 | |
7839 | KING | 10 | 1000.00 | 5000.00 |
7844 | TURNER | 30 | 0.00 | 1500.00 |
7876 | ADAMS | 20 | 1100.00 | |
7900 | JAMES | 30 | 950.00 | |
7902 | FORD | 20 | 3000.00 |
SqlServer:
CREATE TABLE emp_temp(
deptno int NULL,
empno int NOT NULL,
ename varchar(15)NULL,
comm decimal(7, 2)NULL
)
INSERT INTO emp_temp
SELECT deptno,empno,ename,comm FROM emp
WHERE empno IN (7782,7839,7934);
BEGIN TRAN
SELECT et.empno,et.ename,et.deptno,et.comm,emp.sal
FROM emp_temp et
JOIN emp
ON et.empno= emp.empno;
MERGE INTO emp_temp et
USING(SELECT empno,ename,deptno,comm,SAL FROM emp) emp
ON (et.empno= emp.empno)
WHEN MATCHEDAND SAL< 2000THEN
DELETE WHEN MATCHED THEN
UPDATE SET et.comm = 1000
WHEN NOTMATCHED THEN
INSERT VALUES(emp.deptno,emp.empno,emp.ename,emp.comm);
SELECT et.empno,et.ename,et.deptno,et.comm,emp.sal
FROM emp_temp et
JOIN emp
ON et.empno= emp.empno;
ROLLBACK TRAN
执行前:
empno | ename | deptno | comm | sal |
7782 | CLARK | 10 | NULL | 2450.00 |
7839 | KING | 10 | NULL | 5000.00 |
7934 | MILLER | 10 | NULL | 1300.0 |
执行Merge into之后:
empno | ename | deptno | comm | sal |
7782 | CLARK | 10 | 1000.00 | 2450.00 |
7839 | KING | 10 | 1000.00 | 5000.00 |
7369 | SMITH | 20 | NULL | 800.00 |
7499 | ALLEN | 30 | 300.00 | 1600.00 |
7521 | WARD | 30 | 500.00 | 1250.00 |
7566 | JONES | 20 | NULL | 2975.00 |
7654 | MARTIN | 30 | 1400.00 | 1250.00 |
7698 | BLAKE | 30 | NULL | 2850.00 |
7788 | SCOTT | 20 | NULL | 3000.00 |
7844 | TURNER | 30 | 0.00 | 1500.00 |
7876 | ADAMS | 20 | NULL | 1100.00 |
7900 | JAMES | 30 | NULL | 950.00 |
7902 | FORD | 20 | NULL | 3000.00 |
注:
1) 这里SQL Server和Oracle的mergeinto语法还是有差异的.SQL Server里如下代码:
WHEN MATCHEDAND SAL< 2000 THEN
DELETE
要写在前面,如果和UPDATE互换了位置,则会报如下错:
消息 5324,级别 16,状态 1,第 11 行
在 MERGE 语句中,带搜索条件的 'WHEN MATCHED' 子句不能出现在不带搜索条件的 'WHENMATCHED' 子句后。
2) 目前Mysql并没有有merge into的语法.