你可以做你想做的事,但我不确定为什么你会想。一旦你有你的动态列别名,你如何计划引用它们?也就是说,如果您从数据库中提取列别名,那么您将如何使用它们?我可能会错过你的问题背后的原因。
反正我假设你有一个这样的结构:
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(255) default NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `role` (
`id` int(11) NOT NULL auto_increment,
`role` varchar(255) default NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `user_role` (
`user_id` int(11),
`role_id` int(11),
PRIMARY KEY (`user_id`, `role_id`)
);
INSERT INTO `user` (`username`) VALUES
('Bob'), ('Alice'), ('Carol'), ('Dave'), ('Eve');
INSERT INTO `role` (`role`) VALUES
('Super'), ('Admin'), ('View'), ('User'), ('Email');
INSERT INTO `user_role` VALUES
(1,1), (2,2), (3,3), (4,4), (5,5);
从这一点,你可以获取有关用户和他们的角色(一个或多个)信息:
SELECT username, role.id AS role_id, role.role AS role FROM user_role
JOIN user ON user.id = user_role.user_id
JOIN role ON role.id = user_role.role_id;
+----------+---------+-------+
| username | role_id | role |
+----------+---------+-------+
| Bob | 1 | Super |
| Alice | 2 | Admin |
| Carol | 3 | View |
| Dave | 4 | User |
| Eve | 5 | Email |
+----------+---------+-------+
您还可以创建一个列别名为特定角色:
SELECT username, (role.id = 1) AS Super FROM user_role
JOIN user ON user.id = user_role.user_id
JOIN role ON role.id = user_role.role_id;
+----------+-------+
| username | Super |
+----------+-------+
| Bob | 1 |
| Alice | 0 |
| Carol | 0 |
| Dave | 0 |
| Eve | 0 |
+----------+-------+
但是,如果我正确理解您的问题,你想要做的是从角色名称中生成列别名。你不能用一个变量作为一个MySQL声明列别名,但你可以构造一个事先准备好的声明:
SET @sql = (SELECT CONCAT(
'SELECT username, ',
GROUP_CONCAT('(role.id = ', id, ') AS ', role SEPARATOR ', '),
' FROM user_role ',
'JOIN user ON user.id = user_role.user_id ',
'JOIN role ON role.id = user_role.role_id;')
FROM role);
SELECT @sql;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| @sql |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SELECT username, (role.id = 1) AS Super, (role.id = 2) AS Admin, (role.id = 3) AS View, (role.id = 4) AS User, (role.id = 5) AS Email FROM user_role JOIN user ON user.id = user_role.user_id JOIN role ON role.id = user_role.role_id; |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
,你从输出,其生成包含SQL SELECT语句的字符串见。现在,您需要创建从该字符串一份声明,并执行结果:
PREPARE stmt FROM @sql;
EXECUTE stmt;
+----------+-------+-------+------+------+-------+
| username | Super | Admin | View | User | Email |
+----------+-------+-------+------+------+-------+
| Bob | 1 | 0 | 0 | 0 | 0 |
| Alice | 0 | 1 | 0 | 0 | 0 |
| Carol | 0 | 0 | 1 | 0 | 0 |
| Dave | 0 | 0 | 0 | 1 | 0 |
| Eve | 0 | 0 | 0 | 0 | 1 |
+----------+-------+-------+------+------+-------+
编辑
为了调用交叉表查询更方便,你可以换了整个事情了在存储过程。在以下示例中,我无法使GROUP_CONCAT
在SET @sql
声明中工作,如上所述。相反,我必须把它分解成它自己的变量。我不知道为什么没有工作,但最终的结果是一样的,而且代码可能少一点神秘:
DELIMITER //
DROP PROCEDURE IF EXISTS test.crosstab//
CREATE PROCEDURE test.crosstab()
BEGIN
SET @cols = (SELECT GROUP_CONCAT(
'(role.id = ', id, ') AS ', role
SEPARATOR ', ') FROM role);
SET @sql = CONCAT(
'SELECT username, ',
@cols,
' FROM user_role ',
'JOIN user ON user.id = user_role.user_id ',
'JOIN role ON role.id = user_role.role_id;');
PREPARE stmt FROM @sql;
EXECUTE stmt;
END;
//
DELIMITER ;
CALL test.crosstab();
+----------+-------+-------+------+------+-------+
| username | Super | Admin | View | User | Email |
+----------+-------+-------+------+------+-------+
| Bob | 1 | 0 | 0 | 0 | 0 |
| Alice | 0 | 1 | 0 | 0 | 0 |
| Carol | 0 | 0 | 1 | 0 | 0 |
| Dave | 0 | 0 | 0 | 1 | 0 |
| Eve | 0 | 0 | 0 | 0 | 1 |
+----------+-------+-------+------+------+-------+
因为某些原因我不能让准备好的语句返回任何东西,但空在MySQL 5.1上,但我确实认为核心指令是有意义的,我将继续努力使其发挥作用。你曾问过我如何参考这个实现的角色。我的过程将钩在蚂蚁的生成例程,这将生成所需的.java以及映射文件。如果没有重新启动,这些角色不会改变,但是这样做可以方便未来增加角色。目前我使用上面的硬编码版本来提供用户可以与之交互的网格。 – ebt 2010-06-29 01:53:05
并感谢这很好的答案。 – ebt 2010-06-29 01:54:42
@ebt:我在Debian上运行MySQL 5.0.51a-24 + lenny3,并且准备好的语句正常工作(以上示例直接从我的控制台复制并粘贴)。我刚刚在运行MySQL 5.1.47的虚拟主机服务器上尝试了上述示例,并且他们也在那里工作。我已经编辑了包含存储过程的答案,该存储过程将命令包装成一个很好的小包。这是不可能的,但也许这(或分开'GROUP_CONCAT'调用)将解决您的问题。 – Mike 2010-06-29 07:20:52