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 / 48501
Accepted
Jacobm001
Jacobm001
Asked: 2013-08-22 10:35:56 +0800 CST2013-08-22 10:35:56 +0800 CST 2013-08-22 10:35:56 +0800 CST

Erro de Função do MySQL

  • 772

Em um banco de dados herdado, tenho duas tabelas de interesse atual recordse logins. loginme diz a localização do usuário e onde e quando seu login ocorreu (horários de entrada e saída incluídos).

A parte divertida é que não há marca de correlação entre a sessão de login e os aplicativos executados. Para resolver o problema, estou criando uma nova tabela login_appse tentando usar uma função para combinar as duas tabelas.

Até agora eu tenho:

drop function if exists ltop;
delimiter $$

create function ltop(id int, u varchar(10), s datetime, e datetime)
    returns text
    language sql
begin
    declare pid varchar(40);
    declare pname varchar(63);
    declare my_return varchar(100);
    declare cur1 cursor for (select usageProgramID 
                                from records 
                                where usageUser=u
                                    and usageWhen>=s 
                                    and usageWhen<=e
                                    and usageProgramID!="");
    open cur1;
    read_loop: loop
        fetch cur1 into pid;
        set pname = (select programName from Programs where programID=pid);
        insert into login_apps(`sid`, `programName`) values(id, pname);
    end loop read_loop;

    close cur1;

    return "finished";
end;$$
delimiter ;

Ele entra no sistema sem problemas e a inserção está funcionando conforme o esperado em um teste. O problema que estou apresentando é que, quando é executado como:

select ltop("265548", "user", "2013-02-21 13:54:27", "2013-02-21 14:32:18");

Eu recebo o erro:

ERROR 1329 (02000): No data - zero rows fetched, selected, or processed

Os dados a serem retornados não deveriam estar "concluídos"?

Em segundo lugar, não tenho muita certeza de qual seria a melhor maneira de executar isso em todos os valores de loginsquaisquer ponteiros para seguir essa rota.

mysql mysql-5.1
  • 1 1 respostas
  • 339 Views

1 respostas

  • Voted
  1. Best Answer
    Michael - sqlbot
    2013-08-22T19:54:33+08:002013-08-22T19:54:33+08:00
    ERROR 1329 (02000): No data - zero rows fetched, selected, or processed
    

    Esse erro não é sobre o seu RETURN; é isso:

    fetch cur1 into pid;
    

    Quando o cursor fica sem dados, esse erro é lançado. Isso pode ocorrer porque a SELECTconsulta declarada no cursor não encontrou nenhuma linha ou porque encontrou linhas, mas conforme você iterava por ela, você leu além da última linha. Se nada acontecesse quando o cursor ficasse sem dados, como você escaparia read_loop?

    Você precisa interceptar o erro com um manipulador , o que impedirá que a execução do procedimento seja encerrada e defina uma variável que possa ser usada para interromper o loop.

    No topo, com as outras variáveis:

    DECLARE done TINYINT DEFAULT 0;
    

    Então, depois de declarar, mas antes de abrir o cursor:

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    

    Dentro do seu loop:

    fetch cur1 into pid;
    IF done = 1 THEN LEAVE read_loop; END IF;
    

    Isso deve resolver seu problema imediato.

    Outras observações:

    Sua função modifica o banco de dados, portanto, no topo, você deve ter isto:

    returns text
    MODIFIES SQL DATA
    language sql
    

    ...embora, realmente, isso seria mais apropriadamente escrito como um procedimento armazenado em vez de uma função. O MySQL suporta funções armazenadas não determinísticas que modificam o banco de dados, você pode ter problemas potenciais com o log binário usado para recuperação pontual ou replicação.

    Para processar todos os dados em vez de um valor de cada vez, você pode usar cursores aninhados - o cursor externo buscando quaisquer dados que você está alimentando nesta função e o cursor interno - dentro de um bloco BEGIN/ adicional fazendo a lógica que você ENDobtivemos acima com valores buscados no cursor externo. Isso requer a redefinição do donevalor de volta para 0 após cada iteração do bloco interno para que o outro bloco não pare prematuramente.

    A subconsulta interna é desnecessária, pois o cursor pode ser declarado com...

    SELECT p.programName
      FROM records r JOIN Programs p ON p.programID = r.usageProgramID
     WHERE ...
    

    ...mas, na verdade, toda essa função parece ser desnecessária .

    Em SQL, normalmente é melhor dizer ao banco de dados o que precisa ser feito ("declarativo"), em vez de como fazê-lo ("procedural").

    Pensar de maneira muito processual é um antipadrão SQL .

    Não sei os nomes das colunas na tabela 'login', então você precisará corrigi-los, mas considere a seguinte consulta. Tanto quanto eu posso dizer, ele faz exatamente o que a função faz, para todos os logins e todos os registros correspondentes.

    INSERT INTO login_apps(`sid`, `programName`)
    SELECT l.session_id, p.programName
      FROM logins l
      JOIN records r ON r.usageUser = l.user_name 
                    AND r.usageWhen >= l.start_time 
                    AND r.usageWhen <= l.end_time
                    AND r.usageProgramID != ""
      JOIN Programs p ON p.programID = r.usageProgramID;
    

    Feito.

    Para manutenção futura da tabela "login_apps", um gatilho na tabela "records" pode procurar o login relacionado e gravar as novas entradas em "login_apps" toda vez que "records" tiver uma inserção ou atualização... ou quando o o tempo de parada é registrado na tabela "login", um gatilho de atualização pode ler "registros" e inserir em "login_apps".

    Pensamento final, provavelmente seria um design melhor se você armazenasse o ID do programa em vez do nome do programa na tabela login_apps ... a menos que a tabela "records" realmente tenha uma chave primária auto_increment, caso em que esse seria o valor que você deveria realmente armazene em login_apps.

    • 2

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

    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

    Conceder acesso a todas as tabelas para um usuário

    • 5 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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