如何使用 SQL 语句重命名 AzerothCore 上的术士仆从?

How do I rename Warlock Minions on AzerothCore with an SQL statement?

我想写一个 SQL 查询来重命名我在 AzerothCore 上的术士仆从,但我的第一次尝试遇到了 MySQL 错误:

MySQL Error 1093 - Can't specify target table for update in FROM clause

我的代码:

USE `acore_characters`;
SET @IMP := 416;
SET @IMP_NAME = 'NewImpName';
SET @OWNER_NAME = 'NameOfMyWarlock';
UPDATE `character_pet` SET name = @IMP_NAME WHERE `id` IN
  (SELECT p.`id` FROM `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
    WHERE c.`name` = @OWNER_NAME AND p.`entry`= @IMP);

this answer on Whosebug 的帮助下,以下内容现在可以使用了。

--------------------------
-- Variant (A): Outdated
--------------------------
USE `acore_characters`;

-- Warlock pet creatures
SET @IMP := 416;
SET @VOIDWALKER := 1860;
SET @SUCCUBUS := 1863;
SET @FELHUNTER := 417;
SET @FELGUARD := 17252;

-- Names
SET @OWNER_NAME := 'MyWarlockName';
SET @IMP_NAME :='NewImpName';
SET @VOIDWALKER_NAME := 'NewVoidwalkerNamen';
SET @SUCCUBUS_NAME := 'NewSuccubusName';
SET @FELHUNTER_NAME := 'NewFelhunterName';
SET @FELGUARD_NAME := 'NewFelguardName';

-- Update Imp Name
UPDATE `character_pet` SET name = @IMP_NAME WHERE `id` IN
  (SELECT s.`id` FROM (SELECT p.`id` FROM `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
    WHERE c.`name` = @OWNER_NAME AND p.`entry`= @IMP) s);

-- Update Voidwalker Name
UPDATE `character_pet` SET name = @VOIDWALKER_NAME WHERE `id` IN
  (SELECT s.`id` FROM (SELECT p.`id` FROM `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
    WHERE c.`name` = @OWNER_NAME AND p.`entry`= @VOIDWALKER) s);

-- Update Succubus Name
UPDATE `character_pet` SET name = @SUCCUBUS_NAME WHERE `id` IN
  (SELECT s.`id` FROM (SELECT p.`id` FROM `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
    WHERE c.`name` = @OWNER_NAME AND p.`entry`= @SUCCUBUS) s);

-- Update Felhunter Name
UPDATE `character_pet` SET name = @FELHUNTER_NAME WHERE `id` IN
  (SELECT s.`id` FROM (SELECT p.`id` FROM `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
    WHERE c.`name` = @OWNER_NAME AND p.`entry`= @FELHUNTER) s);

-- Update Felguard Name
UPDATE `character_pet` SET name = @FELGUARD_NAME WHERE `id` IN
  (SELECT s.`id` FROM (SELECT p.`id` FROM `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
    WHERE c.`name` = @OWNER_NAME AND p.`entry`= @FELGUARD) s);

-- Show result
SELECT p.`id`, p.`entry`, p.`name`, c.`name` AS `owner_name`
FROM `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
WHERE c.`name` = @OWNER_NAME;

我既不喜欢额外的嵌套 SELECT 也不真正理解为什么 MySQL 没有它会抱怨,因为内部 SELECT 的结果不受外部 UPDATE.以下变体使用 的建议并在 JOIN 上执行更新。遗憾的是我不能使用“多合一更新”方法,因为 AzerothCore 对 MySQL 的最低要求是 5.7,而 WITH ... VALUES 构造显然需要 8.x.

--------------------------
-- Variant (B): Current
--------------------------
USE `acore_characters`;

-- Names (parameters)
SET @OWNERNAME := 'MyWarlockName';
SET @IMPNAME :='NewImpName';
SET @VOIDWALKERNAME := 'NewVoidwalkerNamen';
SET @SUCCUBUSNAME := 'NewSuccubusName';
SET @FELHUNTERNAME := 'NewFelhunterName';
SET @FELGUARDNAME := 'NewFelguardName';

-- Warlock pet creatures (constants)
SET @IMP := 416;
SET @VOIDWALKER := 1860;
SET @SUCCUBUS := 1863;
SET @FELHUNTER := 417;
SET @FELGUARD := 17252;

-- Update Imp Name
UPDATE `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
SET p.`name` = @IMPNAME
WHERE p.`entry` = @IMP AND c.`name` = @OWNERNAME;

-- Update Voidwalker Name
UPDATE `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
SET p.`name` = @VOIDWALKERNAME
WHERE p.`entry` = @VOIDWALKER AND c.`name` = @OWNERNAME;

-- Update Succubus Name
UPDATE `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
SET p.`name` = @SUCCUBUSNAME
WHERE p.`entry` = @SUCCUBUS AND c.`name` = @OWNERNAME;

-- Update Felhunter Name
UPDATE `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
SET p.`name` = @FELHUNTERNAME
WHERE p.`entry` = @FELHUNTER AND c.`name` = @OWNERNAME;

-- Update Felguard Name
UPDATE `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
SET p.`name` = @FELGUARDAME
WHERE p.`entry` = @FELGUARD AND c.`name` = @OWNERNAME;

-- Show result
SELECT p.`id`, p.`entry`, p.`name`, c.`name` AS `owner_name`
FROM `character_pet` p INNER JOIN `characters` c ON p.`owner` = c.`guid`
WHERE c.`name` = @OWNERNAME;

您根本不需要子查询,只需使用 JOIN

UPDATE character_pet p
INNER JOIN characters c 
    ON p.owner = c.guid 
    AND c.name = @OWNER_NAME 
    AND p.entry = @IMP
SET name = @IMP_NAME

如果您正在进行多次更新,您还可以加入一个 VALUES 语句

WITH vals(id, newname) AS (
    VALUES (416, 'NewImpName'),
           (1860, 'NewVoidwalkerName')
           (1863, 'NewSuccubusName')
           (417, 'NewFelhunterName')
           (17252, 'NewFelguardName'))
UPDATE character_pet p
INNER JOIN vals v
    ON p.entry = v.id
INNER JOIN characters c 
    ON p.owner = c.guid
    AND c.name = 'MyWarlockName'
SET p.name = v.newname