我知道,这绝对是一种不好的做法,但这是以前的开发人员废弃的项目,我需要继续使用相同的结构。
基本上,有一个表格每年都必须通过添加新列来编辑,例如:year_2023、year_2024、year_2025、year_2026等等,并且已经有人处理它了。
这绝对是一个糟糕的方法,随着时间的推移,大量的列会堵塞表,但我需要创建一个依赖于所有这些列(如果它们存在或不存在)的函数。
让我们举一个实际的例子。我知道我可以简单地做:
SELECT *
FROM table
WHERE year_2023 != '0000-00-00'
OR year_2024 != '0000-00-00'
OR year_2025 != '0000-00-00'
OR year_2026 = != '0000-00-00'
要选择在当前状态下在此类列中设置了日期的所有列,但明年我不想通过添加来编辑此查询:
... OR year_2027 = != '0000-00-00'
所以我的问题是,有没有办法循环遍历年份列,并最终在找到第一个不存在的列后停止循环?
如果year_2027(尚)不存在,则无需继续迭代所有年份,因此无需检查year_2028等,因为它们也不存在。
您可以通过
获取列名称SELECT `COLUMN_NAME`
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA`='yourdatabasename'
AND `TABLE_NAME`='yourtablename';
要动态查询 SQL 中的列,特别是当列具有像year_XXXX这样的结构化命名约定时,您可以在提供有关数据库模式的元数据的系统表或视图的帮助下使用动态 SQL。
对于 MySQL,您可以查询 information_schema.columns 表来获取有关特定表中的列的信息。以下是如何构建动态 SQL 查询来实现您想要的结果的示例:
-- Constructing the dynamic SQL query
SET @sql = CONCAT('SELECT * FROM your_table WHERE ');
-- Get the maximum year present in your table columns
SELECT MAX(SUBSTRING_INDEX(column_name, '_', -1)) INTO @max_year
FROM information_schema.columns
WHERE table_schema = 'your_database' -- replace 'your_database' with your database name
AND table_name = 'your_table'; -- replace 'your_table' with your table name
-- Loop through the years and construct the WHERE clause
SET @year = 2023; -- Starting year
WHILE @year <= @max_year DO
SET @sql = CONCAT(@sql, 'year_', @year, ' != \'0000-00-00\' OR ');
SET @year = @year + 1;
END WHILE;
-- Remove the last 'OR' from the query
SET @sql = LEFT(@sql, LENGTH(@sql) - 3);
-- Execute the dynamic SQL query
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
此脚本动态构造一个 SQL 查询,以从表中选择任何year_XXXX 列具有非零日期值的行。它检索表列中存在的最大年份,然后为从 2023 年到表中找到的最大年份的所有年份动态构建 WHERE 子句。