Mic*_*ald 11 mysql stored-procedures
我有一个包含“书籍”(儿童短篇小说)的数据库,并且对书中每个单词的字数进行统计会非常有用。
我想出了如何使用以下方法获取每个单词的字数:
SELECT SUM
(
ROUND
(
(LENGTH(pageText) - LENGTH (REPLACE (pageText, "Word", "")))
/LENGTH("Word")
)
) FROM pages WHERE bookID = id;
Run Code Online (Sandbox Code Playgroud)
这对于计算单词非常有效。但是它需要我阅读每本书,找出每个单词,并通过该函数运行它(我将它保存为存储过程。)
我有一个包含每个单词的表格,没有重复。
我的问题:有没有办法可以使用我的存储过程在 Words 表上执行某种“for each”循环?
IE。向存储过程传递书籍 ID 和单词并记录结果。为每本书做每一个字。从而为我节省了大量手动时间......这是我什至应该从数据库方面做的事情吗?我应该用 PHP 代替吗?
老实说,非常感谢任何输入!
Mic*_*bot 21
创建使用两个嵌套游标的第二个过程。
存储过程中的游标允许您执行非常不类似于 SQL 的操作:一次一行地遍历结果集,将选定的列值放入变量中并对其进行处理。
它们很容易被误用,因为 SQL 是声明性的而不是过程性的,通常不需要“for each”类型的操作,但在这种情况下,它似乎是一个有效的应用程序。
一旦掌握了它们的窍门,游标就很容易了,但它们确实需要在其支持代码中采用结构化的方法,而这种方法并不总是直观的。
我最近提供了一些相当标准的“样板”代码,用于在 Stack Overflow 的答案中使用游标调用存储过程,我将从下面的答案中大量借鉴。
使用游标需要一些标准的样板代码来包围它。
您SELECT
可以从任何地方获取要传递的值(可以是临时表、基表或视图,并且可以包括对存储函数的调用),然后使用这些值调用您的existinf 过程。
这是必要代码的语法上有效的示例,并带有注释来解释每个组件的作用。
此示例使用 2 列将 2 个值传递给被调用的过程。
请注意,出于某种原因,此处发生的事件按特定顺序排列。必须首先声明变量,必须在其继续处理程序之前声明游标,并且循环必须遵循所有这些内容。
你不能乱序做事,所以当你将一个游标嵌套在另一个游标中时,你必须通过在过程体中的BEGIN
...END
块中嵌套额外的代码来重置过程范围;例如,如果您需要在循环内使用第二个游标,您只需在循环内、另一个BEGIN
...END
块内声明它。
DELIMITER $$
DROP PROCEDURE IF EXISTS `my_proc` $$
CREATE PROCEDURE `my_proc`(arg1 INT) -- 1 input argument; you might need more or fewer
BEGIN
-- declare the program variables where we'll hold the values we're sending into the procedure;
-- declare as many of them as there are input arguments to the second procedure,
-- with appropriate data types.
DECLARE val1 INT DEFAULT NULL;
DECLARE val2 INT DEFAULT NULL;
-- we need a boolean variable to tell us when the cursor is out of data
DECLARE done TINYINT DEFAULT FALSE;
-- declare a cursor to select the desired columns from the desired source table1
-- the input argument (which you might or might not need) is used in this example for row selection
DECLARE cursor1 -- cursor1 is an arbitrary label, an identifier for the cursor
CURSOR FOR
SELECT t1.c1,
t1.c2
FROM table1 t1
WHERE c3 = arg1;
-- this fancy spacing is of course not required; all of this could go on the same line.
-- a cursor that runs out of data throws an exception; we need to catch this.
-- when the NOT FOUND condition fires, "done" -- which defaults to FALSE -- will be set to true,
-- and since this is a CONTINUE handler, execution continues with the next statement.
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- open the cursor
OPEN cursor1;
my_loop: -- loops have to have an arbitrary label; it's used to leave the loop
LOOP
-- read the values from the next row that is available in the cursor
FETCH NEXT FROM cursor1 INTO val1, val2;
IF done THEN -- this will be true when we are out of rows to read, so we go to the statement after END LOOP.
LEAVE my_loop;
ELSE -- val1 and val2 will be the next values from c1 and c2 in table t1,
-- so now we call the procedure with them for this "row"
CALL the_other_procedure(val1,val2);
-- maybe do more stuff here
END IF;
END LOOP;
-- execution continues here when LEAVE my_loop is encountered;
-- you might have more things you want to do here
-- the cursor is implicitly closed when it goes out of scope, or can be explicitly closed if desired
CLOSE cursor1;
END $$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
62104 次 |
最近记录: |