INSERT INTO ... SELECT 如果目标列具有生成的列

ali*_*lik 7 mysql insert-select virtual-column

有一些表:

CREATE TABLE `asource` (
  `id` int(10) unsigned NOT NULL DEFAULT '0'
);

CREATE TABLE `adestination` (
  `id` int(10) unsigned NOT NULL DEFAULT '0',
  `generated` tinyint(1) GENERATED ALWAYS AS (id = 2) STORED NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

我从asourceto复制一行adestination

INSERT INTO adestination 
SELECT asource.* 
FROM asource;
Run Code Online (Sandbox Code Playgroud)

以上产生一个错误:

Error Code: 1136. Column count doesn't match value count at row 1
Run Code Online (Sandbox Code Playgroud)

好的,要求我提及生成的查询很奇怪。但是好的,我将该列添加到查询中:

INSERT INTO adestination 
SELECT asource.*, NULL AS `generated`
FROM asource;
Run Code Online (Sandbox Code Playgroud)

这在 5.7.10 中运行良好。但是,它会在 5.7.11 中生成错误(由于修复

Error Code: 3105. The value specified for generated column 'generated' in table 'adestination' is not allowed.
Run Code Online (Sandbox Code Playgroud)

好的,下次试试:

INSERT INTO adestination 
SELECT asource.*, 1 AS `generated`
FROM asource;
Run Code Online (Sandbox Code Playgroud)

但还是同样的错误。我尝试了 0、TRUE、FALSE,但错误仍然存​​在。

DEFAULT 值被声明为唯一允许的值(specsdocs)。但是,以下会生成语法错误(那里不支持 DEFAULT):

INSERT INTO adestination 
SELECT asource.*, DEFAULT AS `generated`
FROM asource;
Run Code Online (Sandbox Code Playgroud)

那么,如何使用 INSERT INTO ... SELECT 将一行从一个表复制到另一个表,如果目标表添加了一些列,其中一些列是 GENERATED ?

调用此查询的代码是通用的,并且不知道特定表具有哪些列。它只知道目标表有哪些额外的列。源表是活动表,目标表是源表的历史版本。它有几个额外的列,例如用户 ID 进行了更改,更改的类型(插入、更新、删除)等。

Bri*_*ica 5

可悲的是,这就是 MySQL 现在“符合 SQL 标准”的工作方式。

生成的列在更新、插入等中可以接受的唯一值是DEFAULT,或者另一个选项是完全省略该列。

我的穷人解决这些问题的方法是在我处理数据时禁用生成的列(例如导入转储),然后返回并添加生成的列表达式。


sca*_*dge 1

您必须声明列

Insert into adestination (id, generated) 
select id, 1 
from asource; 
Run Code Online (Sandbox Code Playgroud)