上线新功能,如何兼容旧数据?
sql 将一张表的字段复制到另一张表
我们在上线新功能后,有时修改了后台字段,需要兼容旧数据,得将一张表的字段复制到另一张表。
存在以下两种情况:
一、查询一张表B的字段,插入另一张表A。
格式如下:
INSERT INTO 表A(字段a1,字段a2) SELECT 字段b1,字段b2 FROM 表B WHERE 字段b1=具体值;
示例:
INSERT INTO t_taxtype(fpkid,fid,fdataid) SELECT fpkid,fid,ftaxtype FROM t_risk WHERE ftaxtype='1';
如果字段需要计算后再复制,示例如下:
INSERT INTO t_taxtype(fpkid,fid,fdataid) SELECT friskid+1000000000 AS fpkid,fid,ftaxtype FROM t_risk WHERE ftaxtype='1';
二、查询一张表B的字段,更新另一张表A
可以使用UPDATE SET SELECT。
这个其实就叫做"多表关联更新"。
假设A和B的关联关系为 B.字段b2=A.字段a2,格式如下:
UPDATE 表A A SET A.字段a1 = (SELECT B.字段b1 FROM 表B B WHERE B.字段b2=A.字段a2) ;
示例如下:
UPDATE t_variable A SET A.fvariable_number = (SELECT B.felement_id FROM t_element B WHERE B.fnumber=A.felement_number);
这样格式,在一般情况下可以生效。但是如果表B中满足条件的数据不存在,那么就在更新表A时可能会出错。
假设表A的字段a1需要更新,但是又不能为空,如果没有过滤掉表B字段b1中为null的数据,那么UPDATE时会报错"Column '字段a' cannot be null"。
更健壮的做法,可以判断表B中的数据是否存在,再去更新表A。
格式为UPDATE SET WHERE EXISTS,如下:
UPDATE 表A A
SET A.字段a1 = (SELECT B.字段b1 FROM 表B B WHERE B.字段b2=A.字段a2)
WHERE EXISTS ( SELECT 1 FROM 表B B WHERE B.字段b2=A.字段a2);
这样可以从表B取出一行记录,检查WHERE条件,如果满足,则进行更新,即执行SET,若不满足,则取下一条记录,再检查WHERE条件,循环往复。
示例如下:
UPDATE t_variable A
SET A.fvariable_number = ( SELECT B.felement_id FROM t_element B WHERE B.fnumber = A.felement_number )
WHERE EXISTS ( SELECT 1 FROM t_element B WHERE B.fnumber = A.felement_number );
UPDATE多表
想要查询一张表B的字段,更新另一张表A,也可以使用UPDATE多表。
在查询表B的字段时,要过滤掉为空/为null的数据,在Mysql中可以如下处理(Oracle不可以UPDATE多表):
将子查询的结果作为表C,并通过表C进行查询,最后UPDATE数据。
格式为:
UPDATE 表A A,
( SELECT B.字段b1 AS 字段c1
FROM 表B B
JOIN 表A A
ON A.字段a1 = B.字段b2) 表C
SET A.字段a2 = C.字段c1
WHERE C.字段c1 IS NOT NULL AND TRIM( C.字段c1 ) != '';
示例如下:
UPDATE t_variable v,
( SELECT e.fname AS fname
FROM t_element e
JOIN t_variable v
ON e.fnumber = v.felement_number ) n
SET v.fvariable_number = n.fname
WHERE n.fname IS NOT NULL AND TRIM( n.fname ) != '';
查询表B和表C的字段,更新另一张表A
如果是三张表,示例如下:
UPDATE t_variable v
SET v.fnumber = (
SELECT t.fname
FROM t_element_detail t
JOIN t_element e ON e.fid = t.fid
WHERE e.fnumber = v.felement_number);
注意,在Mysql中,不能先select出同一表中的某些值,在同一语句中update这个表。
否则会报错:You can't specify target table '表名' for update in FROM clause。
以下这种写法是错误的:
UPDATE t_variable v
SET v.fnumber=
(
SELECT t.fname
FROM t_variable v,t_element e ,t_element_detail t
WHERE e.fnumber=v.felement_number AND e.fid=t.fid
)