关于mysql:SQL:根据另一个表中的列值选择列

 2019-10-09 

SQL: Selecting columns based on column value from another table

我有以下表格:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
UserPrivileges:
+--------+------+------+------+
| UserID | Col1 | Col2 | Col3 |
+--------+------+------+------+
|      1 |    0 |    1 |    1 |
|      2 |    0 |    0 |    1 |
|      3 |    1 |    0 |    0 |
|      4 |    1 |    1 |    0 |
+--------+------+------+------+

Data:
+--------+------+------+------+
| DataID | Col1 | Col2 | Col3 |
+--------+------+------+------+
|      1 | A    | B    | C    |
|      2 | D    | E    | F    |
|      3 | G    | H    | I    |
|      4 | J    | K    | L    |
+--------+------+------+------+

我的问题最简单的形式与Data表没有任何关系,但我还是以某种方式对其进行了说明,以致于我可能会以错误的方式进行操作。

如何根据值从UserPrivileges中选择列名称? 这样我就可以在另一个查询中使用结果来仅选择那些列。

遵循以下原则:

SELECT (COLUMNS_NAME_QUERY_FROM_UserPrivileges(UserID='#')) WHERE DataID = '#' FROM Data

或者,我不介意为特定列管理用户权限的更好方法。


答案取决于您对结果的要求。是否要求结果具有一致的列集,而不考虑用户privs?如果是这样,您可以使用IF子句将不允许的值设置为null(或其他一些特殊值),例如,

1
2
3
4
5
6
7
SELECT IF (p.col1 = 0 THEN NULL ELSE d.col1) AS col1,
       IF (p.col2 = 0 THEN NULL ELSE d.col2) AS col2,
       IF (p.col3 = 0 THEN NULL ELSE d.col3) AS col3
FROM Data d,
     UserPrivileges p
WHERE p.userId = '#'
  AND d.DataId = '#'

当然,"特殊值"可能是个问题,因为您需要一个永远不会出现在数据中的值。如果您需要知道空值(因为实际值是空值)与空值(因为它是被禁止的列)之间的区别,则不能使用空值。

另一种方法可以让您简单地将每个列的特权指示符包括在结果中,然后让您的业务逻辑使用该指示符来确定哪些值对用户可见。

一种非常不同的方法将使结果集仅包含允许的列。在这种情况下,您将需要动态构建sql语句。我不知道您是以存储过程还是宿主语言来执行此操作,但是基本思想是这样的:

1
2
3
4
5
6
string sqlCmd ="SELECT"
    + (SELECT (FIELDS_NAME_QUERY(UserID='#')
       FROM USER_PRIVILEGES
       WHERE userid='#')
    + FROM data d
execute sqlCmd

"执行"是指您可以执行的任何作为sql命令的字符串。

OP进一步说明后:

好的,您需要sql函数,该函数返回一个看起来像" colname1,colname2,..."的字符串。以下内容类似于sql server中的内容。句法

1
2
3
4
5
6
7
8
9
10
11
create function  
FIELDS_NAME_QUERY (@userid int)  
begin  
select col1, col2, col3... INTO @col1priv, @col2priv, @col3priv FROM userPrivileges WHERE UserId = @UserId  
declare @result varhcar(60)  
set @result = ''  
if (@col1priv = 1) @result = 'col1'  
if (@col2priv = 1) @result = @result + ' ,col2'  
if (@col3priv = 1) @result = @result + ' ,col3'  
return @result  
end


还没有尝试过,但是这样的事情应该可以工作

查看此帖子以获取详细信息-如何从Oracle中的表中获取列名?

让我们知道您如何解决这个问题...