目录
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的语法.