无法将存储列添加到 MariaDB 10.7.3,臭名昭著 "Error Code 1901"

Can't add a STORED column to MariaDB 10.7.3, Infamous "Error Code 1901"

我正在尝试将 GENERATED ALWAYS 列添加到 table,这会将两个字符解码为 DATE

它包含一个函数(返回 DATE),但当表达式被内联时,它的行为方式相同。该函数在 SELECT 中运行良好。我已经检查了我的字符集和排序规则的一致性。

sql_mode 是“ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION”

这是 table 架构。请注意,我有一个 Location 生成的列,它工作正常。

CREATE TABLE `Photo_Gear_Date_Codes` (
  `ID` varchar(4) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL DEFAULT '....',
  `Location` varchar(253) GENERATED ALWAYS AS (case left(`ID`,2) when 'TN' then 'Tatsuno, Hyogo' else 'Unknown' end) STORED,
  `Note` varchar(1022) COLLATE latin1_general_ci DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci

这是我为简化事情而定义的函数,尽管我在内联这段代码时遇到了同样的错误:

CREATE DEFINER=`root`@`127.0.0.1`
FUNCTION `Date_from_OM_date_code`(id3 char(1), id4 char(1))
RETURNS date
DETERMINISTIC
COMMENT 'Decode the last two digits of a four-character OM date code.'
RETURN CONVERT(
    concat(
      case ID3
        when '1' then '1971'
        when '2' then '1972'
        when '3' then '1973'
        when '4' then '1974'
        when '5' then '1975'
        when '6' then '1976'
        when '7' then '1977'
        when '8' then '1978'
        when '9' then '1979'
        when '0' then '1980'
        when 'A' then '1981'
        when 'B' then '1982'
        when 'C' then '1983'
        when 'D' then '1984'
        when 'E' then '1985'
        when 'F' then '1986'
        when 'G' then '1987'
        when 'H' then '1988'
        when 'I' then '1989'
        when 'J' then '1990'
        when 'K' then '1991'
        when 'L' then '1992'
        when 'M' then '1993'
        when 'N' then '1994'
        when 'O' then '1995'
        when 'P' then '1996'
        when 'Q' then '1997'
        when 'R' then '1998'
        when 'S' then '1999'
        when 'T' then '2000'
        when 'U' then '2001'
        when 'V' then '2002'
        when 'W' then '2003'
        when 'X' then '2004'
        when 'Y' then '2005'
        when 'Z' then '2006'
        end,
      case ID4
        when '1' then '-01-00'
        when '2' then '-02-00'
        when '3' then '-03-00'
        when '4' then '-04-00'
        when '5' then '-05-00'
        when '6' then '-06-00'
        when '7' then '-07-00'
        when '8' then '-08-00'
        when '9' then '-09-00'
        when 'A' then '-10-00'
        when 'B' then '-11-00'
        when 'C' then '-12-00'
        when 'X' then '-10-00'
        when 'Y' then '-11-00'
        when 'Z' then '-12-00'
        end), DATE);

以下是我尝试添加生成的列的方式:

USE `Personal`;
ALTER TABLE `Photo_Gear_Date_Codes` ADD COLUMN `Date` DATE AS 
  (Date_from_OM_date_code(SUBSTR(`ID`,3,1), RIGHT(`ID`,1))) STORED;
SELECT ID,
  `Location`,
  Date_from_OM_date_code(SUBSTR(`ID`,3,1), RIGHT(`ID`,1)) `Date`
  FROM Photo_Gear_Date_Codes

当我执行这三个语句时,第二个抛出 1901 错误代码:

Function or expression 'Date_from_OM_date_code()' cannot be used in the GENERATED ALWAYS AS clause of Date

Error code 1901.

但我继续解决错误,SELECT 工作正常!

ID Location Date
S7Y Unknown 1977-11-00
TND1 Tatsuno, Hyogo 1984-01-00
TND4 Tatsuno, Hyogo 1984-04-00
TNGB Tatsuno, Hyogo 1987-11-00
TNH9 Tatsuno, Hyogo 1988-09-00
TNI5 Tatsuno, Hyogo 1989-05-00
TNJ2 Tatsuno, Hyogo 1990-02-00
TNJ3 Tatsuno, Hyogo 1990-03-00
TNJ5 Tatsuno, Hyogo 1990-05-00
TNM6 Tatsuno, Hyogo 1993-06-00
TNM9 Tatsuno, Hyogo 1993-09-00
TNOA Tatsuno, Hyogo 1995-10-00

看起来它应该有用……我正在为这个而烦恼!

提前感谢您指出我的愚蠢之处! :-)

正如 mariadb 在 generated column 上的文档所说:

This expression might generate the value based on the values of other columns in the table, or it might generate the value by calling built-in functions or user-defined functions (UDFs).

UDF 是用 c++ 编写的函数,而不是 sql。如您所见,标准的 sql-based 用户创建的函数未包含在列表中,因此出现错误消息。

改为将函数体作为表达式包含在生成的列代码中。