AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 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

MySQL函数错误

  • 772

在一个继承的数据库中,我有两个当前感兴趣的表,records和logins. login告诉我用户的位置以及他登录的地点和时间(包括进出时间)。

有趣的是登录会话和运行的应用程序之间没有关联标记。为了解决这个问题,我正在创建一个新表login_apps并尝试使用一个函数来合并这两个表。

到目前为止我有:

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 ;

它毫无问题地进入系统,并且插件在测试中按预期工作。我提出的问题是当它运行时:

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

我收到错误:

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

返回的数据不应该是“完成”的吗?

其次,我不太确定在logins任何指针的每个值上运行这条路线的最佳方式是什么?

mysql mysql-5.1
  • 1 1 个回答
  • 339 Views

1 个回答

  • 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
    

    该错误与您无关RETURN;是这样的:

    fetch cur1 into pid;
    

    当游标用完数据时,将抛出此错误。这可能是因为SELECT在游标中声明的查询没有找到任何行,或者因为它确实找到了行但是当您遍历它时,您读取了最后一行。如果游标用完数据时什么也没发生,您将如何退出read_loop?

    您需要使用handler捕获错误,这将阻止过程的执行终止,并设置一个可用于跳出循环的变量。

    在顶部,与其他变量:

    DECLARE done TINYINT DEFAULT 0;
    

    然后,在声明之后但在打开游标之前:

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    

    在你的循环中:

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

    这应该可以解决您眼前的问题。

    其他观察:

    你的函数修改数据库,所以在顶部,你应该有这个:

    returns text
    MODIFIES SQL DATA
    language sql
    

    ...虽然,实际上,将其编写为存储过程而不是函数更合适。MySQL 支持修改数据库的非确定性存储函数,用于时间点恢复或复制的二进制日志可能会出现潜在问题。

    要一次处理所有数据而不是一个值,您可以使用嵌套游标——外部游标获取您输入该函数的任何数据,内部游标——在一个附加的BEGIN/END块中执行您的逻辑在上面,我们得到了在外部游标中获取的值。这需要在内部块的每次迭代后将值重置done回 0,以便另一个块不会过早停止。

    内部子查询是不必要的,因为游标可以声明为...

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

    ...但是,事实上,这整个功能似乎是不必要的。

    在 SQL 中,通常最好告诉数据库需要做什么(“声明式”),而不是如何做(“过程式”)。

    过于程序化的思考是一种 SQL 反模式。

    我不知道“登录”表中的列名,因此您需要更正这些列名,但请考虑以下查询。据我所知,对于所有登录和所有匹配记录,它的作用与函数完全相同。

    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;
    

    完毕。

    为了将来维护“login_apps”表,“records”表上的触发器可以查找相关登录,并在每次“records”有插入或更新时将新条目写入“login_apps”......停止时间记录在“登录”表中,更新触发器可以读取“记录”并插入到“登录应用程序”中。

    最后的想法是,如果您将程序 ID 而不是程序名称存储在 login_apps 表中,这可能是更好的设计……除非“records”表实际上有一个 auto_increment 主键,在这种情况下,这将是您应该的值真正存储在 login_apps 中。

    • 2

相关问题

  • 是否有任何 MySQL 基准测试工具?[关闭]

  • 我在哪里可以找到mysql慢日志?

  • 如何优化大型数据库的 mysqldump?

  • 什么时候是使用 MariaDB 而不是 MySQL 的合适时机,为什么?

  • 组如何跟踪数据库架构更改?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    授予用户对所有表的访问权限

    • 5 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

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

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve