AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 138549
Accepted
Michael MacDonald
Michael MacDonald
Asked: 2016-05-15 15:48:31 +0800 CST2016-05-15 15:48:31 +0800 CST 2016-05-15 15:48:31 +0800 CST

MySQL -> Loop através de uma tabela, executando um procedimento armazenado em cada entrada

  • 772

Eu tenho um banco de dados com 'livros' (contos para crianças) e seria extremamente informativo ter contagens de palavras de cada palavra nos livros.

Eu descobri como obter a contagem de palavras para cada palavra usando:

SELECT SUM
( 
    ROUND
    ( 
        (LENGTH(pageText) - LENGTH (REPLACE (pageText, "Word", "")))
        /LENGTH("Word")
    )
) FROM pages WHERE bookID = id;

O que funciona maravilhosamente para contar as palavras. MAS isso requer que eu passe por cada livro, e tire cada palavra, e execute-a por meio dessa função (eu a salvei como um procedimento armazenado).

Eu tenho uma tabela que contém cada palavra, sem duplicatas.

Minha pergunta: existe uma maneira de fazer algum tipo de loop "for each" na tabela Words usando meu procedimento armazenado?

ou seja. passe ao procedimento armazenado um ID de livro e uma palavra e registre o resultado. Fazendo CADA palavra, para CADA livro. Assim, economizando muito tempo manual... Isso é algo que eu deveria estar fazendo do lado do banco de dados? Devo tentar com PHP em vez disso?

Honestamente, qualquer entrada é muito apreciada!

mysql stored-procedures
  • 1 1 respostas
  • 69243 Views

1 respostas

  • Voted
  1. Best Answer
    Michael - sqlbot
    2016-05-15T18:43:11+08:002016-05-15T18:43:11+08:00

    Crie um segundo procedimento que usa dois cursores aninhados.

    Os cursores em procedimentos armazenados permitem que você faça uma coisa muito diferente do SQL: itere através de um conjunto de resultados uma linha por vez, colocando os valores de coluna selecionados em variáveis ​​e fazendo coisas com eles.

    Eles são facilmente mal utilizados, já que o SQL, sendo declarativo ao invés de procedural, normalmente não deveria precisar de operações do tipo "for each", mas neste caso, parece ser uma aplicação válida.

    Depois que você pega o jeito deles, os cursores são fáceis, mas eles exigem uma abordagem estruturada em seu código de suporte que nem sempre é intuitiva.

    Recentemente, forneci um código "boilerplate" bastante padrão para trabalhar com um cursor para chamar um procedimento armazenado em uma resposta no Stack Overflow e tomarei emprestado muito dessa resposta abaixo.


    Usar um cursor requer algum código clichê padrão para cercá-lo.

    Você SELECTos valores que deseja passar, de onde quer que os esteja obtendo (que pode ser uma tabela temporária, tabela base ou exibição, e pode incluir chamadas para funções armazenadas) e, em seguida, chama seu procedimento existinf com esses valores.

    Aqui está um exemplo sintaticamente válido do código necessário, com comentários para explicar o que cada componente está fazendo.

    Este exemplo usa 2 colunas para passar 2 valores para o procedimento chamado.

    Observe que os eventos que acontecem aqui estão em uma ordem específica por um motivo. As variáveis ​​devem ser declaradas primeiro, os cursores devem ser declarados antes de seus manipuladores continue e os loops devem seguir todas essas coisas.

    Você não pode fazer coisas fora de ordem, então quando você aninha um cursor dentro de outro, você tem que redefinir o escopo do procedimento aninhando código adicional dentro de BEGIN... ENDblocos dentro do corpo do procedimento; por exemplo, se você precisasse de um segundo cursor dentro do loop, bastaria declará-lo dentro do loop, dentro de outro BEGIN... ENDbloco.

    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 ;
    
    • 27

relate perguntas

  • Existem ferramentas de benchmarking do MySQL? [fechado]

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve