2

我没有看到在 MySQL 查询中执行此操作的清晰简单的方法。架构看起来像:

CREATE TABLE users (
    id VARCHAR(20),
    col SET('read', 'write', 'edit', 'delete'),
);

如果我想查询所有具有readwriteprivs 的用户(不管设置了任何其他值),我想出的唯一查询是:

SELECT id, privs
FROM users WHERE
FIND_IN_SET('read',privs) > 0 AND 
FIND_IN_SET('write',privs) > 0

有没有办法简化这个?就像是:

SELECT id, privs
FROM users WHERE
privs('read' & 'write')

假设,我想使用更复杂的位逻辑,但我想知道工作示例是否是使用SET类型时完成此操作的唯一方法。

4

2 回答 2

1

您的值的存储顺序与您的 create table 语句中的顺序相同。

在你的情况下:

        decimal   |   binary
read    1         |   0001
write   2         |   0010
edit    4         |   0100
delete  8         |   1000

您可以通过添加“转换”列来获得十进制值0

所以要读写,你可以这样做:

SELECT id, privs
FROM users 
WHERE
privs+0 = 3;

在此处阅读更多相关信息

更新:

privs+0 = 3将只返回“读&写”。

就像我说的那样,无论值被分配给条目的频率如何,这些值都将按顺序存储。

所以你也可以这样做:

SELECT id, privs
FROM users 
WHERE
privs = 'read,write';

如果你想至少有读写能力,甚至可能更多:

SELECT id, privs
FROM users 
WHERE
privs LIKE 'read,write%';
于 2012-04-16T11:09:05.693 回答
1

如果在 MySQL 中没有优雅的方法来做到这一点,我会解决这个问题,至少我不需要手动记住所有设置元素位字段的位置/值,我仍然可以使用更多的助记符字符串。将只使用 CROSS JOIN:

SELECT u.id, u.col
FROM users u

CROSS JOIN
(
  select sum(val) as bit_result from
  (
  SELECT 'read' as txt,1 as val
  union
  SELECT 'write' as txt,2 as val
  union
  SELECT 'edit' as txt,4 as val
  union
  SELECT 'delete' as txt,8 as val
  ) as x
  where txt in ('read','write')
) as z

WHERE u.col & z.bit_result = z.bit_result

源数据:

CREATE TABLE users (
    id VARCHAR(20),
    col SET('read', 'write', 'edit', 'delete')
);

insert into users(id,col)
values ('hello','read,write');

insert into users(id,col)
values ('hola','read,delete,write');

insert into users(id,col)
values ('yeah','delete,write');

输出:'hello' 和 'hola'

http://sqlfiddle.com/#!2/56070/41

于 2012-04-16T13:04:22.373 回答