MYSQL:加入包含存储函数的 2 个选择语句时出错

Posted

技术标签:

【中文标题】MYSQL:加入包含存储函数的 2 个选择语句时出错【英文标题】:MYSQL: Error joining 2 select statements that include a stored function 【发布时间】:2017-01-30 15:33:30 【问题描述】:

下午好,

我创建了一个存储函数来模拟 mysql 中“SHOW GRANTS FOR”命令的行为。脚本定义如下:

CREATE FUNCTION get_grants(p_user text, p_host text, p_type text, p_obj text) 
   RETURNS text 
   NOT DETERMINISTIC 
   READS SQL DATA
BEGIN
...
END;

如果我在 select 语句中使用该函数,它会正确执行。例如:

SELECT User as USER, Host as HOST, 
      'GLOBAL' as PRIV_TYPE, NULL as DATABASE_NAME,   
       mydatabase.get_grants(User, Host, 'GLOBAL', '') as PRIVILEGES
  FROM mysql.user

但是,当我使用 UNIONUNION ALL 语句来加入 2 个调用具有不同参数值的函数的选择语句时,如下所示:

SELECT User as USER, Host as HOST, 
       'GLOBAL' as PRIV_TYPE, NULL as DATABASE_NAME,   
       mydatabase.get_grants(User, Host, 'GLOBAL', '') as PRIVILEGES
  FROM mysql.user
UNION ALL
SELECT User as USER, Host as HOST,
       'DB' as PRIV_TYPE, Db as DATABASE_NAME,
       mydatabase.get_grants(User, Host, 'DB', Db) as PRIVILEGES
  FROM mysql.db
 ORDER BY USER, HOST, DATABASE_NAME IS NULL, DATABASE_NAME;

我收到以下错误:#1222 - 使用的 SELECT 语句的列数不同

谁能解释这里发生了什么以及如何解决这个问题?

提前致谢。

【问题讨论】:

【参考方案1】:

我认为是 UNION ALL 导致了这个问题。 通常,如果您使用 UNION ALL,列数是否不同并不重要,但 UNION 必须相等。 因此,请尝试使用 UNION ALL 并将 NULL 删除为 DATABASE_NAME 或仅使用 UNION 并将 NULL 保留为 DATABASE_NAME

SELECT User as USER, Host as HOST, 
       'GLOBAL' as PRIV_TYPE, NULL as DATABASE_NAME,   
       mydatabase.get_grants(User, Host, 'GLOBAL', '') as PRIVILEGES
  FROM mysql.user
UNION
SELECT User as USER, Host as HOST,
       'DB' as PRIV_TYPE, Db as DATABASE_NAME,
       mydatabase.get_grants(User, Host, 'DB', Db) as PRIVILEGES
  FROM mysql.db
 ORDER BY USER, HOST, DATABASE_NAME IS NULL, DATABASE_NAME;

SELECT User as USER, Host as HOST, 
       'GLOBAL' as PRIV_TYPE,   
       mydatabase.get_grants(User, Host, 'GLOBAL', '') as PRIVILEGES
  FROM mysql.user
UNION ALL
SELECT User as USER, Host as HOST,
       'DB' as PRIV_TYPE, Db as DATABASE_NAME,
       mydatabase.get_grants(User, Host, 'DB', Db) as PRIVILEGES
  FROM mysql.db
 ORDER BY USER, HOST, DATABASE_NAME IS NULL, DATABASE_NAME;

【讨论】:

【参考方案2】:

在几乎让我的大脑试图找到问题之后,事实证明实际问题与 MySQL 提供的错误消息没有任何关系(至少与文档中提供的有关此错误消息的描述无关) .

在这种情况下,错误出现在存储函数的实现中。在 SELECT...INTO 命令中,我在 INTO 子句中的两个变量之间缺少一个“,”。选择的列数与 INTO 子句中的变量数相对应,问题已解决,我设法在上述查询中使用该函数,没有任何问题。

作为参考,有问题的查询是:

SELECT Select_priv, Insert_priv, Update_priv, Delete_priv,
       Create_priv, Alter_priv, Index_priv, Drop_priv,
       Create_tmp_table_priv, Create_view_priv, Show_view_priv,
       Create_routine_priv, Alter_Routine_priv, Execute_priv, 
       Event_priv, Trigger_priv, Grant_priv, Lock_tables_priv, 
       References_priv
  INTO v_select_priv, v_insert_priv, v_update_priv, v_delete_priv,
       v_create_priv, v_alter_priv, v_index_priv, v_drop_priv,
       v_tmptables_priv, v_createview_priv, v_showview_priv, 
       v_createroutine_priv, v_alterroutine_priv, v_execute_priv,
       v_event_priv, v_trigger_priv, v_grant_priv, v_locktables_priv,
       v_references_priv
  FROM mysql.db
 WHERE User = p_user
   AND Host = p_host
   AND Db = p_obj;

【讨论】:

以上是关于MYSQL:加入包含存储函数的 2 个选择语句时出错的主要内容,如果未能解决你的问题,请参考以下文章

示例数据 - “执行包含更新和插入语句的存储过程时出现问题”

加入两个包含 SUM() 函数的子查询时出现无效操作错误

MySql视图和存储程序

MySQL:将子选择和数组合并到一个IN语句中

MySQL_基础_存储过程和函数

调用 MySQL 存储过程时出现数据包乱序错误