MYSQL:加入包含存储函数的 2 个 select 语句时出错
MYSQL: Error joining 2 select statements that include a stored function
下午好,
我创建了一个存储函数来模拟 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
但是,当我使用 UNION 或 UNION ALL 语句连接 2 个调用函数的 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
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 语句具有不同的列数 .
任何人都可以解释这里发生了什么以及如何解决这个问题吗?
提前致谢。
我认为是 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;
在几乎绞尽脑汁试图找出问题之后,事实证明实际问题与 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 中 "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
但是,当我使用 UNION 或 UNION ALL 语句连接 2 个调用函数的 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
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 语句具有不同的列数 .
任何人都可以解释这里发生了什么以及如何解决这个问题吗?
提前致谢。
我认为是 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;
在几乎绞尽脑汁试图找出问题之后,事实证明实际问题与 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;