Populate this table - I suggest using a script, for example from PHP:
$dbh = new PDO("mysql:dbname=$dbname", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
$ins = $dbh->prepare('INSERT INTO ents (ref, rep) VALUES (?, ?)');
$t = get_html_translation_table(HTML_ENTITIES);
foreach ($t as $k => $v) $ins->execute([substr($v, 1, -1), $k]);
Define an SQL function to perform entity replacements (using this table where applicable, or else by character code):
DELIMITER ;;
CREATE FUNCTION dhe(s TEXT) RETURNS TEXT
BEGIN
DECLARE n, p, i, t INT DEFAULT 0;
DECLARE r VARCHAR(12);
entity_search: LOOP
SET n := LOCATE('&', s, n+1);
IF (!n) THEN
LEAVE entity_search;
END IF;
IF (SUBSTRING(s, n+1, 1) = '#') THEN
CASE
WHEN SUBSTRING(s, n+2, 1) RLIKE '[[:digit:]]' THEN
SET t := 2, p := n+2, r := '[[:digit:]]';
WHEN SUBSTRING(s, n+2, 1) = 'x' THEN
SET t := 3, p := n+3, r := '[[:xdigit:]]';
ELSE ITERATE entity_search;
END CASE;
ELSE
SET t := 1, p := n+1, r := '[[:alnum:]_]';
END IF;
SET i := 0;
reference: LOOP
IF SUBSTRING(s, p+i, 1) NOT RLIKE r THEN
IF SUBSTRING(s, p+i, 1) RLIKE '[[:alnum:]_]' THEN
ITERATE entity_search;
END IF;
LEAVE reference;
END IF;
IF i = 8 THEN ITERATE entity_search; END IF;
SET i := i + 1;
END LOOP reference;
SET s := CONCAT(
LEFT(s, n-1),
CASE t
WHEN 1 THEN COALESCE(
(SELECT rep FROM ents WHERE ref = SUBSTRING(s, p, i))
, SUBSTRING(s, n, i + IF(SUBSTRING(s, p+i, 1)=';',1,0))
)
WHEN 2 THEN CHAR(SUBSTRING(s, p, i))
WHEN 3 THEN CHAR(CONV(SUBSTRING(s, p, i), 16, 10))
END,
SUBSTRING(s, p + i + IF(SUBSTRING(s, p+i, 1)=';',1,0))
);
END LOOP entity_search;
RETURN s;
END;;
DELIMITER ;