存储过程成功,但在mysql中无法正常运行

存储过程成功,但在mysql中无法正常运行,mysql,stored-procedures,sql-insert,Mysql,Stored Procedures,Sql Insert,我有一个关于两个表的存储过程,如下所示: CREATE DEFINER=`brambang`@`%` PROCEDURE `create_discount_campaign`( IN discount_campaign_discount_type_id CHAR(22), IN discount_campaign_product_id INT(10), IN discount_campaign_marketing_target_id

我有一个关于两个表的存储过程,如下所示:

 CREATE DEFINER=`brambang`@`%` PROCEDURE `create_discount_campaign`(
          IN discount_campaign_discount_type_id CHAR(22),
          IN discount_campaign_product_id INT(10),
          IN discount_campaign_marketing_target_id INT(10),
          IN discount_campaign_max_use_per_user int(11),
          IN discount_campaign_discount_code varchar(100),
          IN discout_campaign_discount_amount decimal(10,0),
          IN discount_campaign_start_date datetime,
        IN discount_campaign_end_date datetime,
        IN discount_campaign_min_order_quantity INT(11),
        IN discount_campaign_min_order_price decimal(10,0),
        IN discount_campaign_discount_quota INT(11),
        IN discount_campaign_min_product_varian INT(11),
        IN discount_campaign_apply_all_product INT(10),
        IN discount_campaign_product_product_id int(10) unsigned,
        IN discount_campaign_product_active tinyint(1),
        IN discount_campaign_product_createdby int(11),
        IN discount_campaign_product_updatedby int(11),
        IN discount_campaign_product_category_id VARCHAR(100),
        IN discount_campaign_advanced_discount_advanced_rules_id int(50),
        IN discount_campaign_advanced_value varchar(255),
        IN discount_campaign_advanced_status tinyint(4)
    )
    proc:
        BEGIN
            DECLARE is_dc_discount_type_id INT(10);
            DECLARE is_dc_product_id INT(10);
            DECLARE is_dc_marketing_target_id INT(10);
            DECLARE is_dc_max_use_per_user INT(11);
            DECLARE is_dc_discount_code varchar(100);
            DECLARE is_dc_discount_amount decimal(10,0);
            DECLARE is_dc_start_date datetime;
            DECLARE is_dc_end_date datetime;
            DECLARE is_dc_min_order_quantity INT(11);
            DECLARE is_dc_min_order_price decimal(10,0);
            DECLARE is_dc_discount_quota INT(11);
            DECLARE is_dc_min_product_variant INT(11);
            DECLARE is_dc_apply_all_product INT(10);
            DECLARE is_dcp_product_id INT(10);
            DECLARE is_dcp_active tinyint(1);
            DECLARE is_dcp_createdby int(11);
            DECLARE is_dcp_updatedby int(11);
            DECLARE is_dca_discount_advanced_rules_id int(50);
            DECLARE is_dca_value varchar(255);
            DECLARE is_dca_status tinyint(4);
            DECLARE LAST_INSERT_ID int(11);
            DECLARE discount_campaign_product_category_id varchar(100);
            SET @querie = NULL;
            SET @querie2 = NULL;
            SET @querie3 = NULL;
            SET lc_time_names = "id_ID";
            SET @is_dc_discount_type_id = NULL;
            SET @is_dc_product_id = NULL;
            SET @is_dc_marketing_target_id = NULL;
            SET @is_dc_max_use_per_user = NULL;
            SET @is_dc_discount_code = NULL;
            SET @is_dc_discount_amount = NULL;
            SET @is_dc_start_date = NULL;
            SET @is_dc_end_date = NULL;
            SET @is_dc_min_order_quantity = NULL;
            SET @is_dc_min_order_price = NULL;
            SET @is_dc_discount_quota = NULL;
            SET @is_dc_min_product_variant = NULL;
            SET @is_dc_apply_all_product = NULL;
            SET @is_dcp_product_id = NULL;
            SET @is_dcp_active = NULL;
            SET @is_dcp_createdby = NULL;
            SET @is_dcp_updatedby = NULL;
            SET @is_dca_discount_advanced_rules_id = NULL;
            SET @is_dca_value = NULL;
            SET @is_dca_status = NULL;
            SET @LAST_INSERT_ID = NULL;
            SET @discount_campaign_product_category_id = NULL;
    
            
                SET @is_dc_discount_type_id = discount_campaign_discount_type_id;
                SET @is_dc_product_id = discount_campaign_product_id;
                SET @is_dc_marketing_target_id = discount_campaign_marketing_target_id;
                SET @is_dc_max_use_per_user = discount_campaign_max_use_per_user;
                SET @is_dc_discount_code = discount_campaign_discount_code;
                SET @is_dc_discount_amount = discout_campaign_discount_amount;
                SET @is_dc_start_date = discount_campaign_start_date;
                SET @is_dc_end_date = discount_campaign_end_date;
                SET @is_dc_min_order_quantity = discount_campaign_min_order_quantity;
                SET @is_dc_min_order_price = discount_campaign_min_order_price;
                SET @is_dc_discount_quota = discount_campaign_discount_quota;
                SET @is_dc_min_product_variant = discount_campaign_min_product_varian;
                SET @is_dc_apply_all_product = discount_campaign_apply_all_product;
                SET @discount_campaign_product_category_id = discount_campaign_product_category_id;
                
                SET @querie = CONCAT("
            INSERT INTO discount_campaigns (
              discount_type_id, 
              product_id, 
              marketing_target_id, 
             max_use_per_user, 
              discount_code, 
              discount_amount, 
              start_date,
                        end_date,
              min_order_quantity,
              min_order_price,
              discount_quota,
              min_product_variant,
              apply_all_products,
              createdAt,
              updatedAt
            ) VALUES (
              ?, 
              ?, 
              ?, 
              ?, 
              ?, 
              ?, 
              ?,
              ?,
              ?,
              ?,
              ?,
              ?,
              ?,
              NOW(),
              NOW()
            );
          ");
                
          PREPARE stmt FROM @querie;
    
          EXECUTE stmt 
          USING 
            @is_dc_discount_type_id,
              @is_dc_product_id, 
              @is_dc_marketing_target_id, 
             @is_dc_max_use_per_user, 
              @is_dc_discount_code, 
              @is_dc_discount_amount, 
              @is_dc_start_date,
                        @is_dc_end_date,
              @is_dc_min_order_quantity,
              @is_dc_min_order_price,
              @is_dc_discount_quota,
              @is_dc_min_product_variant,
              @is_dc_apply_all_product;
          
                DEALLOCATE PREPARE stmt;
                
             SET @is_dcp_product_id = discount_campaign_product_product_id;
             SET @is_dcp_active = discount_campaign_product_active;
             SET @is_dcp_createdby = discount_campaign_product_createdby;
             SET @is_dcp_updatedby = discount_campaign_product_updatedby;
             SET @LAST_INSERT_ID = LAST_INSERT_ID();
             
             IF (discount_campaign_apply_all_product = 0) THEN
              SET @querie2 = CONCAT("INSERT INTO discount_campaign_product (discount_campaign_id,
              product_id, 
              active, 
              createdby, 
             updatedby, 
              createdAt,
              updatedAt
            ) SELECT ?,product_id,?,?,NULL,NOW(),NULL 
            FROM product_categories WHERE category_id IN 
            (?) AND status=1");
                
          PREPARE stmt_2 FROM @querie2;
    
          EXECUTE stmt_2 
          USING 
            @LAST_INSERT_ID,
            @is_dcp_active, 
            @is_dcp_createdby, 
            @discount_campaign_product_category_id;
            DEALLOCATE PREPARE stmt_2;
           END IF;
    
    END
基本上我有两个表,折扣活动,别名为dc的任何变量都是这个表,折扣活动,别名为dcp的任何变量都是这个表。此存储过程具有将数据插入到带有已生成参数的表中的功能。在折扣活动表中有一列,即应用所有产品。如果参数中填写了0的apply_all_product,则别名为dcp的另一个参数将在折扣_campaign_product表中插入一些数据。但当我应用apply_all_product=0时,此存储过程仅在折扣活动表中插入数据,而不是在折扣活动产品表中插入数据


此存储过程中的错误在哪里?

我猜您没有看到任何行插入到折扣活动产品中,因为产品类别中没有匹配的行。您使用了INSERT…SELECT FROM product_categories,但您搜索的是类别id所在的行

我想您的意思是在1,2,3,4,5中将其转换为category_id,但这不是SQL中查询参数的工作方式。一个参数只能用于一个标量值。因此,在您的代码中,它将像在“1,2,3,4,5”中搜索单个字符串的category_id一样进行搜索。当它将字符串强制转换为数字时,它可能会匹配字符串中的第一个数字,但是如果没有与第一个数字匹配的类别,那么它将找不到匹配项

解决方法是在设置类别id“1,2,3,4,5”中使用FIND_。这实际上不是函数应该如何使用的,但它可以在逗号分隔的整数列表中查找整数。注意不要在列表元素之间加空格,因为它不适用于FIND_in_SET

其他问题:

你声明了局部变量,然后就不用了。请理解,在MySQL中,变量myvar和@myvar是两个不同的变量。您需要将不带@sigil的类型声明为局部变量。而带有@sigil的类型是用户定义的会话变量,您不需要声明它——只需设置它的值,就可以隐式创建该变量

您正在使用PREPARE/EXECUTE,但在这种情况下不需要使用动态SQL。您唯一的动态部分是值,因此您可以将输入参数用作过程的查询参数。它们保证像单个标量一样工作,并且不会导致SQL注入。只有在查询中有动态表达式或动态标识符时,才需要使用PREPARE/EXECUTE,但实际上没有

在查询中直接使用过程参数的唯一风险是,应确保参数名称与查询中表的任何列名不同

小数10,0没有多大意义。为什么使用小数位数为0的刻度?这只是一个整数

INT11和INT50没有区别。INT类型的参数不会更改其大小或值的范围。事实上,在MySQL 8.0中不赞成将此参数用于INT类型,因此您应该养成删除它的习惯

这是我测试过的程序,它是有效的:

CREATE PROCEDURE create_discount_campaign(
    IN discount_campaign_discount_type_id CHAR(22),
    IN discount_campaign_product_id INT,
    IN discount_campaign_marketing_target_id INT,
    IN discount_campaign_max_use_per_user INT,
    IN discount_campaign_discount_code varchar(100),
    IN discout_campaign_discount_amount decimal(10,0),
    IN discount_campaign_start_date datetime,
    IN discount_campaign_end_date datetime,
    IN discount_campaign_min_order_quantity INT,
    IN discount_campaign_min_order_price decimal(10,0),
    IN discount_campaign_discount_quota INT,
    IN discount_campaign_min_product_varian INT,
    IN discount_campaign_apply_all_product INT,
    IN discount_campaign_product_product_id INT UNSIGNED, -- this is unused?
    IN discount_campaign_product_active TINYINT,
    IN discount_campaign_product_createdby INT,
    IN discount_campaign_product_updatedby INT,
    IN discount_campaign_product_category_id VARCHAR(100),
    IN discount_campaign_advanced_discount_advanced_rules_id INT,
    IN discount_campaign_advanced_value varchar(255),
    IN discount_campaign_advanced_status TINYINT
)
MODIFIES SQL DATA
BEGIN
    DECLARE last_id BIGINT;

    INSERT INTO discount_campaigns
    SET
      discount_type_id = discount_campaign_discount_type_id,
      product_id = discount_campaign_product_id,
      marketing_target_id = discount_campaign_marketing_target_id,
      max_use_per_user = discount_campaign_max_use_per_user,
      discount_code = discount_campaign_discount_code,
      discount_amount = discout_campaign_discount_amount,
      start_date = discount_campaign_start_date,
      end_date = discount_campaign_end_date,
      min_order_quantity = discount_campaign_min_order_quantity,
      min_order_price = discount_campaign_min_order_price,
      discount_quota = discount_campaign_discount_quota,
      min_product_variant = discount_campaign_min_product_varian,
      apply_all_products = discount_campaign_apply_all_product,
      createdAt = NOW(),
      updatedAt = NOW();

    IF (discount_campaign_apply_all_product = 0) THEN
        SET last_id = LAST_INSERT_ID();
        INSERT INTO discount_campaign_product (discount_campaign_id,
          product_id, active, createdby, updatedby, createdAt, updatedAt)
        SELECT last_id, c.product_id, discount_campaign_product_active,
          discount_campaign_product_createdby, NULL, NOW(), NULL
        FROM product_categories AS c
        WHERE FIND_IN_SET(c.category_id, discount_campaign_product_category_id)
          AND c.status=1;
    END IF;
END

注意,我在第一次插入时使用了不同的语法。这是对标准SQL的MySQL扩展,仅适用于单行插入。但是它非常方便,因为它使它更容易。在带有列列表和VALUES子句的标准INSERT语法中,我发现很难确保已将列与正确的值匹配。插入。。。SET语法更具可读性。

请添加表定义和call语句。谢谢您,先生,我在不到一年的时间里才有MySQL方面的经验,我很荣幸从您那里得到了高质量的答案,将不胜感激。让我一个接一个的学习,谢谢你的评论,因为这对我来说是新的,非常感谢