2012-04-25 54 views
0

我有两个表,patternpattern_optimizedpattern表中的一些字段被定义为BIGINT(20) DEFAULT '-1',这对于他们保存的数据来说太大了;此外,-1用作“未设置”(零是有效值) - 否则使用其他否定值。MySQL:在BEFORE INSERT触发器中执行类型转换

pattern_optimized表为这些行使用新的数据格式,将它们定义为INT(10) UNSIGNED DEFAULT NULL。我现在想将pattern中的数据复制到pattern_optimized表中。

这将使用INSERT INTO pattern_optimized SELECT * FROM pattern很容易做到,但很明显,所有的负值超出范围了,造成这样的警告:

100 row(s) affected, 64 warning(s): 
1264 Out of range value for column 'version' at row 1 
1264 Out of range value for column 'triggered' at row 1 
... 
Records: 100 Duplicates: 0 Warnings: 357 

我最初的想法是创建一个BEFORE INSERT触发如下:

CREATE TRIGGER `negativeValueFix` BEFORE INSERT ON `pattern_optimized` 
FOR EACH ROW 
BEGIN 
    IF new.version < 0 THEN 
     SET new.version = NULL; 
    END IF; 
    -- ... 
END 

但不幸的是这并没有帮助:同样的警告弹出并曾经是-1原始表中的所有值在新表成为0(而不是NULL,这是 - 除了在触发器中实现 - 也是行的默认值)。 似乎MySQL甚至在触发器之前转换了该值。

我知道我可以使用临时表来解决这个问题,但我宁愿不这样做。 pattern表是令人不快的大,我不想为此做一个存储过程。

有没有其他方法或我错过了一些简单的点?

编辑:原始表格中有很多列遭受SIGNED问题,所以我希望能够稍微自动化。

回答

2

您可以使用case语句吗?喜欢的东西:

INSERT INTO pattern_optimized SELECT CASE version WHEN -1 THEN null ELSE version END CASE AS version FROM pattern

+0

有趣,我不知道!我想做'INSERT ... SELECT *'的原因是这些“SIGNED”字段中有很多,我希望能够引导一个完整的插入定义。 – sunside 2012-04-25 11:17:16

+0

我想你可以设置你的新表字段的默认值为一些不在传入数据范围内的值,然后运行插入。你会得到警告,-1将被转换为这个新的默认值。然后,您更新表以将这些值设置为空,然后将新表列中的默认值更改为空。但是,这似乎比转换临时表中的数据或使用内联条件更有用。此外,您必须绝对确定您使用的“临时默认”确实不在传入数据的范围内。 – 2012-04-25 12:05:31

+0

使用IF()版本和视图。谢谢! – sunside 2012-04-27 14:58:28

1

只需添加小条件SELECT语句,例如 -

INSERT INTO pattern_optimized(version) 
    SELECT IF(version < 0, NULL, version) version FROM pattern 

...添加其他字段。

+0

和@Raj一样 - 我不知道的一个重点,但是我希望能在每个领域都做到这一点。 (在更改过程中,会在旧表上插入我希望使用触发器克隆到新表的插入) – sunside 2012-04-25 11:20:37

+0

我接受了Rajs的答案,因为他首先回答+基本相同,代表较少。upvoted你的答案虽然。非常感谢! – sunside 2012-04-27 15:00:21

+0

@Markus - 确定;-) – Devart 2012-04-27 15:12:52