使用 MySQL 函数或过程提取 SELECT 表达式

Posted

技术标签:

【中文标题】使用 MySQL 函数或过程提取 SELECT 表达式【英文标题】:Extract SELECT expression using MySQL function or procedure 【发布时间】:2017-10-23 19:27:59 【问题描述】:

我有兴趣通过提取选择表达式(select_expr 来自mysql docs)来简化 SQL 查询/视图。每个select_expr 本质上都是重复的,带有少量可以提取到变量中的变化。

例如,这是一个现有的查询/视图。

CREATE OR REPLACE VIEW my_view AS
SELECT

  json_unquote(json_extract(sr.response, concat(SUBSTRING_INDEX(json_unquote(
    JSON_SEARCH(mt.response, 'one', 'pref.field_1', NULL, '$.f[*].q')), '.', 2), 
    '.', 'value'))) AS field_1,

  json_unquote(json_extract(sr.response, concat(SUBSTRING_INDEX(json_unquote(
    JSON_SEARCH(mt.response, 'one', 'pref.field_2', NULL, '$.f[*].q')), '.', 2), 
    '.', 'value'))) AS field_2,

  json_unquote(json_extract(sr.response, concat(SUBSTRING_INDEX(json_unquote(
    JSON_SEARCH(mt.response, 'one', 'pref.field_3', NULL, '$.f[*].q')), '.', 2), 
    '.', 'value'))) AS field_3,

FROM my_table mt;

变量位为:field_1field_2field_3

理论上,这是我想做的:

CREATE OR REPLACE VIEW my_view AS
SELECT

  get_select_expr('field_1') AS field_1,
  get_select_expr('field_2') AS field_2,
  get_select_expr('field_3') AS field_3,

FROM my_table mt;

我一直在尝试类似以下的方法,但不确定如何让 select_expr 进行评估。它返回一个字符串是有道理的,但我不知道如何让它进行评估。也许我应该使用一个过程,但这是我的 MySQL 知识崩溃的地方。

DROP FUNCTION IF EXISTS get_select_expr;
CREATE FUNCTION get_select_expr (field_name VARCHAR(255))
RETURNS VARCHAR(255) DETERMINISTIC
RETURN concat('json_unquote(json_extract(mt.response, concat(
    SUBSTRING_INDEX(json_unquote(JSON_SEARCH(mt.response, 
    \'one\', \'pref.', field_3, '', NULL, \'$.f[*].q\')), 
    \'.\', 2), \'.\', \'value\')))');

SELECT get_select_expr('field_1') AS field_1 FROM my_table;

我已经完成了所有建议的类似问题,但没有找到我需要的问题。知道我可能会出错的地方或指针吗?我什至不确定我是否在寻找正确的术语。

【问题讨论】:

这行不通,你需要将完整的 sql 语句合二为一。字符串变量的内容仍然是数据。您可以使用准备好的语句来动态组装和执行 sql 语句,但它们仍然需要带有 from 子句的完整语句。 可以做的是将公式封装在一个函数中,并将字段名作为参数传递给计算输出。 【参考方案1】:

代码太复杂了,这里不需要动态生成sql代码,反正也不行。

只需创建一个以字段值和json字段值作为参数的函数,不需要动态sql:

DROP FUNCTION IF EXISTS get_select_expr;
CREATE FUNCTION get_select_expr (field_name VARCHAR(255), json_field_name varchar (255))
RETURNS VARCHAR(255) DETERMINISTIC
RETURN json_unquote(json_extract(field_name, concat(
    SUBSTRING_INDEX(json_unquote(JSON_SEARCH(field_name, 
    'one', 'pref.', json_field_name, '', NULL, '$.f[*].q')), 
    '.', 2), '.', 'value')));

SELECT get_select_expr(my_table.response, 'field_1') AS field_1 FROM my_table;

【讨论】:

我明白了,如果我从我的问题中删除concat,它会按预期工作。我意识到我已经用别名提出了这个问题,但希望不必重复字段名称。在我看到你的答案之前,我已经创建了生成每个 SQL 部分的函数,然后是一个将它们全部组合成一个完整 SQL 查询的最终函数。然后使用一个过程来执行它。这有点太难了。和同事商量后,我们觉得有点重复也没关系,打算用这个方法。谢谢

以上是关于使用 MySQL 函数或过程提取 SELECT 表达式的主要内容,如果未能解决你的问题,请参考以下文章

mysql为四个表创建储存过程或者储存函数

在 MySQL 中使用来自 select 的索引创建一个临时表

mysql 存储过程中 查询语句后面的from加上变量名 怎么写

使用/动态名称调用表的 MySQL 存储过程

存储过程/函数可以返回表吗?

在 MySQL 中:如何将表名作为存储过程和/或函数参数传递?