在 MySQL (MariaDB) 中使用带有 CTE 的 UPDATE 的问题

Jan*_*man 5 mysql common-table-expression mariadb sql-update

我正在疯狂地尝试让 UPDATE 与 MySQL 中的 CTE 一起工作。

\n

这是一个简化的架构sa_general_journal

\n
CREATE TABLE `sa_general_journal` (\n  `ID` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `Transaction_ID` int(10) unsigned DEFAULT NULL COMMENT \'NULL if not split, same as ID for split records\',\n  `Date` timestamp NOT NULL DEFAULT current_timestamp(),\n\xe2\x80\xa6\n  `Statement_s` int(10) unsigned DEFAULT NULL,\n\xe2\x80\xa6\n  `Name` varchar(255) DEFAULT NULL,\n\xe2\x80\xa6\n  PRIMARY KEY (`ID`),\n\xe2\x80\xa6\n) ENGINE=InnoDB AUTO_INCREMENT=25929 DEFAULT CHARSET=utf8;\n
Run Code Online (Sandbox Code Playgroud)\n

某些记录是“拆分”的,例如,信用卡对帐单金额可能包含拆分的销售税金额。在这种情况下,拆分记录的两个部分在 Transaction_ID 字段中具有相同的 ID。

\n

批量导入记录时,它们无法引用last_insert_ID填写 Transaction_ID 字段,因此需要随后清理这些记录。

\n

这是我第一次天真的尝试,它说我在附近有一个错误UPDATE。好吧,呃。

\n
WITH cte AS (\n    SELECT\n        ID,\n        MIN(ID) OVER(PARTITION BY `Date`, `Name`, Statement_s) AS Trans,\n        Transaction_ID\n    FROM sa_general_journal\n    WHERE Transaction_ID = 0)\nUPDATE cte\nSET Transaction_ID = Trans\n
Run Code Online (Sandbox Code Playgroud)\n

CTE 本身似乎有效,因为我可以跟随它SELECT * FROM cte并得到我所期望的结果。

\n

所以我开始搜索 StackOverflow,发现 CTE 不可更新,但你需要将它们加入到你想要更新的内容中。“没问题!” 我想,当我编写代码时:

\n
WITH cte AS (\n    SELECT\n        ID,\n        MIN(ID) OVER(PARTITION BY `Date`, `Name`, Statement_s) AS Trans,\n        Transaction_ID\n    FROM sa_general_journal\n    WHERE Transaction_ID = 0)\nUPDATE sa_general_journal gj, cte\nSET gj.Transaction_ID = cte.Trans\nWHERE gj.ID = cte.ID\n
Run Code Online (Sandbox Code Playgroud)\n

没有喜悦。同样的错误消息。

\n

我的理解是,在MySQL中,你不需要列列表,但我也尝试使用列列表(a, b, c),并在语句中引用正确的列UPDATE,但它仍然说我有一个问题UPDATE

\n

互联网上使用UPDATEwith的例子少之又少!我从 PerconaWITH找到了一个,我用它来创建上面的尝试,然后从 MySQL 本身找到了另一个非常相似的示例找到了另一个非常相似的示例。

\n

预先感谢您提供的任何帮助!

\n

Aki*_*ina 13

CTE是子查询定义的一部分,而不是整个查询的一部分。查询必须在 CTE 之后指定。CTE 本身不能使用。所以

UPDATE sa_general_journal gj
JOIN (WITH cte AS ( SELECT
                         ID,
                         MIN(ID) OVER(PARTITION BY `Date`, `Name`, Statement_s) AS Trans,
                         Transaction_ID
                    FROM sa_general_journal
                    WHERE Transaction_ID = 0)
      SELECT * FROM cte) subquery ON gj.ID = subquery.ID
SET gj.Transaction_ID = subquery.Trans
Run Code Online (Sandbox Code Playgroud)