MySQL 5.7,使用存储过程中的变量按列名对表进行排序

Posted

技术标签:

【中文标题】MySQL 5.7,使用存储过程中的变量按列名对表进行排序【英文标题】:MySQL 5.7, sort table by column name using a variable in Stored procedure 【发布时间】:2021-01-08 17:42:58 【问题描述】:

我有一个包含一些数据的简单表格:

DROP TABLE IF EXISTS `MY_TABLE`;
CREATE TABLE IF NOT EXISTS `MY_TABLE` (
  `id` CHAR(40) CHARACTER SET 'utf8' COLLATE 'utf8_bin' NOT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO `MY_TABLE` (`id`) VALUES (1);
INSERT INTO `MY_TABLE` (`id`) VALUES (2);
INSERT INTO `MY_TABLE` (`id`) VALUES (3);

现在我有一个从列中检索此数据排序的过程。 这按预期工作:

DROP PROCEDURE IF EXISTS test_procedure;
DELIMITER $$
CREATE PROCEDURE test_procedure()
BEGIN

  SELECT id AS columnAlias FROM `MY_TABLE`
  ORDER BY columnAlias;

END $$
DELIMITER ;

CALL test_procedure();  /* Returns 1, 2, 3, 4, 5, 6, 7, 8, 9 */

还有这个:

DROP PROCEDURE IF EXISTS test_procedure;
DELIMITER $$
CREATE PROCEDURE test_procedure()
BEGIN

  SELECT id AS columnAlias FROM `MY_TABLE`
  ORDER BY -columnAlias;

END $$
DELIMITER ;

CALL test_procedure(); /* Should return 9, 8, 7, 6, 5, 4, 3, 2, 1 */

现在,我的情况:列名必须从过程中传递,所以我这样做:

DROP PROCEDURE IF EXISTS test_procedure;
DELIMITER $$
CREATE PROCEDURE test_procedure(IN data JSON)

BEGIN

  SET @sortBy  = JSON_UNQUOTE(JSON_EXTRACT(DATA, '$.sortBy'));
  
  SELECT id AS columnAlias FROM `MY_TABLE`
  ORDER BY @sortBy;

END $$
DELIMITER ;

CALL test_procedure('"sortBy": "columnAlias"');  /* Should return 1, 2, 3, 4, 5, 6, 7, 8, 9 */
CALL test_procedure('"sortBy": "-columnAlias"'); /* Should return 9, 8, 7, 6, 5, 4, 3, 2, 1 */

但不能让它工作。欢迎任何帮助。


编辑:

鉴于@bill_karwin 的解决方案,我尝试使用 CASE,再次测试我的变量:

DROP PROCEDURE IF EXISTS test_procedure;
DELIMITER $$
CREATE PROCEDURE test_procedure(IN data JSON)

BEGIN

  SET @sortBy  = JSON_UNQUOTE(JSON_EXTRACT(DATA, '$.sortBy'));
  
  SELECT id AS columnAlias FROM `MY_TABLE`
  ORDER BY 
    CASE @sortBy 
      WHEN "columnAlias" THEN columnAlias
      WHEN "-columnAlias" THEN -columnAlias
    END
 ;

END $$
DELIMITER ;

CALL test_procedure('"sortBy": "-columnAlias"'); 

虽然不起作用,但返回 1, 2, 3,而当我传递带有减号的字符串时,它应该被反转:-columnAlias

【问题讨论】:

【参考方案1】:

您可以使用 CASE 表达式:

SELECT id AS columnAlias FROM `MY_TABLE`
ORDER BY CASE @sortBy WHEN 'updated_at' THEN updated_at 
                      WHEN 'user_id' THEN user_id
                      ELSE id END;

有些人使用动态 SQL,但 CASE 表达式解决方案很好,因为它会根据一组固定的列自动检查输入,因此您不会意外导致 SQL 注入漏洞。

【讨论】:

有趣!动态 SQL 看起来如何? 在 SP 中,我建议使用 2 个单独的独立查询(并且只执行其中一个,取决于参数值)而不是 ORDER BY 中的 CASE。 举个例子真的很有帮助!

以上是关于MySQL 5.7,使用存储过程中的变量按列名对表进行排序的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何使用 sql server 中的存储过程将列名存储在变量中?

从mysql 5.7中的变量将多行插入表中

MySQL 5.7 存储过程语法错误,通过 phpadmin 和 Ubuntu 16.04

MySQL 5.7新支持--------通用表空间实战

mysql,遍历列名

存储过程里面set赋值怎么没有起到作用