Domanda

I am trying to create a stored procedure that among other things, updates a table with information from other table:

UPDATE table1 T1, table2 T2
set T1.rank = T1.rank + T2.rank
T1.tags = merge(T1.tags, T2.tags)
WHERE T1.id = T2.id

tags is a string of comma separated words and merge is a function (not a procedure) that breaks the strings into temporary tables and returns the a new string with unique tags using prepared statements. I know can't use prepared statements inside functions but the part that uses those is inside a procedure that is called inside the function.

So I get an error starting that I can't use dynamic sql procedure inside a function and I need the function so I can use the return value as the new value in the update.

Any Possible way to achive this?

È stato utile?

Soluzione

You can do that (an update with merging tags) in one statement with pure SQL. The trick is in using a number aka tally table, which can be created and populated in seconds (also with one SQL statement).

Here is your UPDATE statement

UPDATE table1 t1 JOIN table2 t2
    ON t1.id = t2.id JOIN
(
  SELECT id, GROUP_CONCAT(DISTINCT tag ORDER BY tag) tags
    FROM
  (
     SELECT a.id, SUBSTRING_INDEX(SUBSTRING_INDEX(tags, ',', n.id), ',', -1) tag
       FROM
    (
       SELECT t1.id, CONCAT(t1.tags, ',', t2.tags) tags
         FROM table1 t1 JOIN table2 t2
           ON t1.id = t2.id
    ) a CROSS JOIN tally n
     WHERE n.id <= 1 + (LENGTH(tags) - LENGTH(REPLACE(tags, ',', '')))
       AND n.id < 100 -- change that number to accommodate max possible number of tags 
  ) b
   GROUP BY id
) c ON t1.id = c.id
   SET t1.tags = c.tags,
       t1.rank = t1.rank + t2.rank

Here is schema and statement that populates tally table with up to 100k rows.

CREATE TABLE tally (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY);

INSERT INTO tally 
SELECT NULL
FROM (SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
      , (SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
      , (SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) c
      , (SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) d
      , (SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) e
;

Here is SQLFiddle demo

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top