【问题标题】:MySQL Stored Procedure with Cursor - Syntax Error带有光标的 MySQL 存储过程 - 语法错误
【发布时间】:2016-08-20 04:46:51
【问题描述】:

我正在创建此存储过程,但在该过程的第一次选择时出现语法错误。此过程有一个名为 selProyecto 的 IN var。

BEGIN
   DECLARE num_clientes INT DEFAULT 0;
   DECLARE exit_loop BOOLEAN;       
   DECLARE nInicio DATE;
   DECLARE nFin DATE;
   DECLARE nIdCliente INT;
   DECLARE clientCounter INT;
   DECLARE auxDias INT;
   DECLARE finClientes BOOLEAN;
   DECLARE finContratos BOOLEAN;

   SELECT COUNT(clientes.id) from clientes WHERE id_proyecto = selProyecto INTO num_clientes;

   DECLARE clientes_proyecto CURSOR FOR SELECT id FROM clientes WHERE id_proyecto = selProyecto;

   -- Declaración de un manejador de error tipo NOT FOUND
   DECLARE CONTINUE HANDLER FOR NOT FOUND SET finClientes = TRUE;
   OPEN clientes_proyecto;
   loop_clientesProyecto: LOOP

    -- Recogemos la id del Cliente
    FETCH clientes_proyecto INTO nIdCliente;
    -- Reseteamos los días trabajados
    SET auxDias = 0;

    -- Abrimos un segundo cursor para iterar los contratos de ese cliente
    DECLARE cliContratos CURSOR FOR SELECT fecha_inicio, fecha_fin FROM contratos_cliente WHERE id_cliente = nIdCliente;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET finContratos = TRUE;
    OPEN cliContratos;
    loop_contratos: LOOP
        FETCH cliContratos INTO nInicio, nFin;
        IF nFin < CURDATE() THEN
            auxDias = auxDias + Datediff(nInicio, nFin);
         ELSE
            auxDias = auxDias + Datediff(nInicio, CURDATE());
         END IF;
        IF finContratos THEN
            LEAVE loop_contratos;
        END IF;
    end loop_contratos;

    -- Ya tenemos los días trabajados del cliente, realizamos el cálculo del porcentaje
    SET @porcentaje = @porcentaje + ((((auxDias)/90)*(100/num_clientes))/100)

    IF finClientes THEN
        LEAVE loop_clientesProyecto;
    END IF;

   end loop_clientesProyecto;

END

目的是计算已工作 90 天但无法保存的客户的百分比。

首先我使用SELECT COUNT(clientes.id) from clientes WHERE id_proyecto = selProyecto INTO num_clientes; 获取客户端总数,然后声明一个游标来迭代每个客户端。在游标内,我尝试声明另一个游标以获取该客户的总工作日。最后我用一个函数计算工作日的百分比。

问题是它在第一次选择之前引发语法错误。

我已尝试将句子更改为:SET num_clientes = (SELECT COUNT(clientes.id) from clientes WHERE id_proyecto = selProyecto);,结果相同

【问题讨论】:

  • 什么是语法错误?
  • 我在 phpMyAdmin 中做,上面写着You have an syntax error near "DECLARE clientes_proyecto CURSOR FOR SELECT id FROM clientes WHERE id_proyecto = selProyecto;"

标签: mysql stored-procedures


【解决方案1】:

我已经处理好了自己。代码如下:

BEGIN
   DECLARE num_clientes INT DEFAULT 0;      
   DECLARE nInicio DATE;
   DECLARE nFin DATE;
   DECLARE nIdCliente INT;
   DECLARE clientCounter INT;
   DECLARE auxDias INT;
   DECLARE finClientes BOOLEAN;
   DECLARE finContratos BOOLEAN;
   DECLARE porcentaje DOUBLE;
   DECLARE clientes_proyecto CURSOR FOR SELECT id FROM clientes WHERE id_proyecto = selProyecto;
   DECLARE CONTINUE HANDLER FOR NOT FOUND SET finClientes = TRUE;

   SET num_clientes = (SELECT COUNT(clientes.id) from clientes WHERE id_proyecto = selProyecto);



   -- Declaración de un manejador de error tipo NOT FOUND

   OPEN clientes_proyecto;
   loop_clientesProyecto: LOOP

    -- Recogemos la id del Cliente
    FETCH clientes_proyecto INTO nIdCliente;
    -- Reseteamos los días trabajados
    SET auxDias = 0;

    BLOCK2: BEGIN
    DECLARE cliContratos CURSOR FOR SELECT fecha_inicio, fecha_fin FROM contratos_clientes WHERE id_cliente = nIdCliente;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET finContratos = TRUE;
    -- Abrimos un segundo cursor para iterar los contratos de ese cliente
    OPEN cliContratos;
    loop_contratos: LOOP
        FETCH cliContratos INTO nInicio, nFin;
        IF nFin < CURDATE() THEN
            SET auxDias = auxDias + Datediff(nInicio, nFin);
         ELSE
            SET auxDias = auxDias + Datediff(nInicio, CURDATE());
         END IF;
        IF finContratos THEN
            LEAVE loop_contratos;
        END IF;
    END LOOP loop_contratos;
    CLOSE cliContratos;
    END BLOCK2;

    -- Ya tenemos los días trabajados del cliente, realizamos el cálculo del porcentaje
    SET porcentaje = porcentaje + ((((auxDias)/90)*(100/num_clientes))/100);

    IF finClientes THEN
        LEAVE loop_clientesProyecto;
    END IF;

   END LOOP loop_clientesProyecto;
   CLOSE clientes_proyecto;

   SELECT porcentaje;

END

正如您所见,对于嵌套的 CURSORS,我们必须在 DECLARE 部分定义第一个,然后声明处理程序。在 LOOP 中,我们必须定义一个新的 BLOCK 并执行下一个 CURSOR LOOP。

【讨论】:

    【解决方案2】:

    问题可能出在这里:

    DECLARE clientes_proyecto CURSOR FOR SELECT id FROM clientes WHERE id_proyecto = selProyecto

    您在定义之前引用了selProyecto

    更新:这是我服务器上的一个类似示例:

    mysql> DECLARE foo CURSOR FOR SELECT id FROM mysql.user WHERE id = bar;
    ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DECLARE foo CURSOR FOR SELECT id FROM mysql.user WHERE id = bar' at line 1
    

    【讨论】:

    • selProyecto 是过程中的一个 IN var。抱歉没有发表评论。
    猜你喜欢
    • 2013-03-28
    • 2020-01-14
    • 1970-01-01
    • 2012-04-12
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多