【发布时间】:2016-11-21 23:16:59
【问题描述】:
谁能告诉我为什么会这样。最初的问题总是要复杂得多,但我创建了一个简单的测试用例来重现该问题。首先你需要一个像这样的表:
CREATE TABLE `test` (
`test_a` int(11) unsigned NOT NULL AUTO_INCREMENT,
`test_b` int(11) DEFAULT NULL,
PRIMARY KEY (`test_a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
然后您需要尝试使用此查询更改表:
ALTER TABLE `test`
CHANGE COLUMN `test_b` `new_test_b` INT(11) NOT NULL AFTER `test_a`,
CHANGE COLUMN `test_a` `new_test_a` INT(11) NOT NULL AUTO_INCREMENT FIRST;
你会得到这个结果:
Unknown column 'test_a' in 'test'
我不明白。当您单独进行每个更改时效果很好,但是如果您一起进行更改,则会爆炸。
附录...
在研究了一下之后,我想出了一些事情。我猜可能编译器(或预处理器或其他东西)正在以相反的顺序评估逗号分隔的alter语句,因此在它得到test_b之前更改了test_a列名(这将使'AFTER test_a'部分没有意义。这在测试中被证明是错误的,因为如果你像这样颠倒语句的顺序:
ALTER TABLE `test
CHANGE COLUMN `test_a` `new_test_a` INT(11) NOT NULL AUTO_INCREMENT FIRST,
CHANGE COLUMN `test_b` `new_test_b` INT(11) NOT NULL AFTER `test_a`;
您最终会得到相同的结果。
接下来我假设某些类型的操作在这样的语句中具有优先级。我假设所有 CHANGE COLUMN 操作必须在任何列排序操作之前发生,例如 'AFTER test_a' 如果是这种情况,那么在排序操作中引用新列名是有意义的,如下所示:
ALTER TABLE `test`
CHANGE COLUMN `test_b` `new_test_b` INT(11) NOT NULL AFTER `new_test_a`,
CHANGE COLUMN `test_a` `new_test_a` INT(11) NOT NULL AUTO_INCREMENT FIRST;
这行得通。所以这一定是答案。我想我的问题现在已经演变为各种操作的优先顺序是什么。
请注意,抱歉,我不会将任何当前答案标记为正确,因为它们实际上并没有回答问题,它们只是提供替代方法来做同样的事情(或说明显而易见的事情)。
【问题讨论】:
-
这可能是因为它首先重命名 testa 因为在第一个 alter 语句中存在对 test a 的依赖,然后尝试在 testa 之后修改 testb 。但是由于 testa 现在已重命名,因此出现错误。但是您需要检查 alter 的文档以 100% 确定。
-
这是最接近我认为的答案,因此赞成
标签: mysql primary-key alter-table