如何在触发器中循环所有列名称而不对其进行硬编码

Posted

技术标签:

【中文标题】如何在触发器中循环所有列名称而不对其进行硬编码【英文标题】:How do you loop all columns names in a trigger without hard coding them 【发布时间】:2020-04-17 12:45:07 【问题描述】:

我想创建一个触发器(插入/更新)来检查记录中的所有列值(主键中的列值除外)是否为空。列数可以改变,所以我希望“循环”列名,而不是硬编码触发器中的列。下面是我的数据库方案的非常简化的示例

CREATE TABLE `specs` (
  `id` int(11) NOT NULL,
  `spec1` enum('yes','no') DEFAULT NULL,
  `spec2` enum('yes','no') DEFAULT NULL,
  `spec3` enum('yes','no') DEFAULT NULL,
  `spec4` enum('yes','no') DEFAULT NULL,
  `spec5` enum('yes','no') DEFAULT NULL,
  /* ... can be any number of columns */
  `rowEmpty` enum('yes','no') DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


insert into specs (`id`,`spec1`,`spec2`,`spec3`,`spec4`,`spec5`)
VALUES (1,null,'yes',null,null,null),(2,null,null,'no',null,null),(3,'yes','no',null,null,null),(4,null,null,null,null,null),(5,null,'yes',null,'yes','yes'),(6,null,null,null,'no',null),(7,null,null,null,null,null);

Update specs set `spec1` = 'yes' where id = 7

插入和更新触发器应将记录 ID 4 的列 rowEmpty 设置为“yes”。对于所有其他记录,rowEmpty 应设置为“no”。

如何在不硬编码的情况下循环到触发器中的所有列名称?

【问题讨论】:

'我如何在不对其进行硬编码的情况下循环到触发器中的所有列名' 通常对此的答案是从 information_schema、columns 构建一个 sql 语句并调用动态 sql 但你不能调用动态来自触发器的 sql,,, P.Salmon 所说的 (dev.mysql.com/doc/refman/5.7/en/sql-prepared-statements.html),每当您的表设计具有多个具有相同名称和递增整数的列时,它都会尖叫“糟糕的架构设计”。考虑将它们作为行而不是列。 @Nebu 。 . . “列数可以改变。”您的数据模型有问题。您将值存储在应位于单独行中的列中。 我不相信你能做到,要获得动态列,你需要 INFORMATION_SCHEMA 或动态 sql 并且两者都不能在触发器中使用。从您的应用程序进行更新 【参考方案1】:

为什么不简单地使用生成的列呢?

当然,仍然 要求您枚举所有列,但只需枚举一次,并且直接在表定义中(显然,列名可用)。这样就省去了为每个 DML 操作创建触发器的工作:

create table specs (
        id int(11) not null,
        spec1 enum('yes','no') default null,
        spec2 enum('yes','no') default null,
        spec3 enum('yes','no') default null,
        spec4 enum('yes','no') default null,
        spec5 enum('yes','no') default null,
        rowempty enum('yes','no') as (
            case when coalesce(spec1, spec2, spec3, spec4, spec5) is null
            then 'yes'
            else 'no'
        end),
        primary key (id)
) engine=innodb default charset=utf8;

【讨论】:

'列数可以改变' - 我假设 OP 意味着在任何给定时间点都可以或多或少。 Doh 没有想到这一点。我只需要在删除或添加列时重新创建生成的列,但这不是问题。 @P.Salmon 这将适用于我的场景,但我的问题可能更清楚。

以上是关于如何在触发器中循环所有列名称而不对其进行硬编码的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 中将整数添加到此正则表达式中而不对整数进行硬编码? [复制]

如何读取具有动态名称的文件,同时避免在 R 中进行硬编码?

CSVHelper 如何不对索引进行硬编码

如何在不进行硬编码的情况下在 C++ 中获取类数组的长度?

在 Android 中返回 SQLite 表的所有列

如何在 sql 查询中创建空白/硬编码列?