我们知道,不同类别的商品属性是不同的。

譬如图书和男装

图书:作者、出版社、出版时间、ISBN、开本

男装:工艺(纯色或图案)、风格、适用对象、材质等


首先建一个商品分类属性表 prod_class_attr ,并插入一些测试数据:

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `prod_class_attr`
-- ----------------------------
DROP TABLE IF EXISTS `prod_class_attr`;
CREATE TABLE `prod_class_attr` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `attr_name` varchar(100) NOT NULL,
  `attr_note` varchar(100) DEFAULT NULL COMMENT '属性备注',
  `attr_pid` int(11) NOT NULL DEFAULT '0',
  `prod_classid` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of prod_class_attr
-- ----------------------------
INSERT INTO `prod_class_attr` VALUES ('1', 'press', '出版社', '0', '1');
INSERT INTO `prod_class_attr` VALUES ('2', 'author', '作者', '0', '1');
INSERT INTO `prod_class_attr` VALUES ('3', 'format', '开本', '0', '1');
INSERT INTO `prod_class_attr` VALUES ('4', 'pressdate', '出版时间', '0', '1');
INSERT INTO `prod_class_attr` VALUES ('5', 'technics', '工艺', '0', '2');
INSERT INTO `prod_class_attr` VALUES ('6', 'style', '风格', '0', '2');
INSERT INTO `prod_class_attr` VALUES ('7', 'target', '适用对象', '0', '2');
INSERT INTO `prod_class_attr` VALUES ('8', ' material', '材质', '0', '2');


再创建一张表prod_attr

用于记录商家自定义配置的个性化商品属性:

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `prod_attr`
-- ----------------------------
DROP TABLE IF EXISTS `prod_attr`;
CREATE TABLE `prod_attr` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `prod_id` int(11) NOT NULL,
  `attr_id` int(11) NOT NULL,
  `attr_value` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

动态执行sql语句

什么叫"动态执行sql语句"?举个例子,我们先来执行一条正常的sql语句:

SELECT 1 AS attr_id, '中国出版社' AS attr_value UNION SELECT 2 AS attr_id, '刘勇' AS attr_value;

查询结果如图所示:

那好,接下来我希望通过传入“字符串sql语句”,然后让Mysql帮我执行,需要怎么做呢?分为以下四步:

# 定义sql语句,通常是程序或者参数传递进来的。
SET @ss = 'SELECT 1 AS attr_id, \'中国出版社\' AS attr_value UNION SELECT 2 AS attr_id, \'刘勇\' AS attr_value;';
# 预定义
PREPARE pname from @ss;
# 执行sql语句
EXECUTE pname;
# 释放变量
DEALLOCATE PREPARE pname;

执行结果如图所示:


进阶:动态执行Sql并传入变量

# 定义变量
SET @pid = 5;
SET @pid_2 = 8;
# 定义字符串sql。请注意其中的两个“?”,以及字符串需要转移“\”的问题
SET @ss = 'SELECT ? AS prod_id, 1 AS attr_id, \'中国出版社\' AS attr_value 
           UNION 
           SELECT ? AS prod_id, 2 AS attr_id, \'刘勇\' AS attr_value';
# 预定义
PREPARE pname from @ss;
# 执行sql语句,并且传入变量,对号入座的替换“?”
EXECUTE pname using @pid, @pid_2;
# 释放变量
DEALLOCATE PREPARE pname;

只需要在字符串sql中插入占位符 "?" 即可。一一对应着using后面的变量。


先理解这两段sql

SELECT 5 AS prod_id, a.* from (
    SELECT 1 AS attr_id, '中国出版社' AS attr_value 
    UNION 
    SELECT 2 AS attr_id, '刘勇' AS attr_value
) AS a;

将上面查询出来的数据,插入到 prod_attr 表中:

INSERT INTO prod_attr 
SELECT 5 AS prod_id, a.* from (
    SELECT 1 AS attr_id, '中国出版社' AS attr_value 
    UNION
    SELECT 2 AS attr_id, '刘勇' AS attr_value
) AS a;


所有知识点结合起来,做一个存储过程sp_new_prod:

DROP PROCEDURE IF EXISTS `sp_new_prod`;

CREATE DEFINER = `root`@`localhost` PROCEDURE `sp_new_prod`(IN _prod_name VARCHAR(50), IN _class_id INT)
BEGIN
    SET @pid = 0;
    INSERT INTO prod_main(prod_name, prod_classid) VALUES (_prod_name, _class_id);
    SET @pid = LAST_INSERT_ID();
        SET @ss = 'INSERT INTO prod_attr SELECT ? AS prod_id, a.* from (SELECT 1 AS attr_id, \'中国出版社\' AS attr_value UNION SELECT 2 AS attr_id, \'刘勇\' AS attr_value ) AS a';
        PREPARE pname FROM @ss;
    EXECUTE pname USING @pid;
    DEALLOCATE PREPARE pname;
END;

执行示例:

call sp_new_prod('Java从入门到精通', 1)


最终代码:

DROP PROCEDURE IF EXISTS `sp_new_prod`;

CREATE DEFINER = `root`@`localhost` PROCEDURE `sp_new_prod`(IN _prod_name VARCHAR(50), IN _class_id INT, IN _attr_sql VARCHAR(2000))
BEGIN 
    SET @pid = 0;
    INSERT INTO prod_main(prod_name, prod_classid) VALUES (_prod_name, _class_id);
    SET @pid = LAST_INSERT_ID();
    # SET @ss = 'INSERT INTO prod_attr SELECT ? AS prod_id, a.* from (SELECT 1 AS attr_id, \'中国出版社\' AS attr_value UNION SELECT 2 AS attr_id, \'刘勇\' AS attr_value) AS a';
    SET @ss = concat('INSERT INTO prod_attr SELECT ? AS prod_id, a.* FROM (', _attr_sql ,') AS a');
    PREPARE pname FROM @ss;
    EXECUTE pname USING @pid;
    DEALLOCATE PREPARE pname; 
END;

调用示例:

call sp_new_prod('python', 1, 'SELECT 1 AS attr_id, \'中国出版社\' AS attr_value UNION SELECT 2 AS attr_id, \'刘勇\' AS attr_value')

results matching ""

    No results matching ""