我没有在MySQL查询中看到一种清晰简单的方法。架构看起来像:
CREATE TABLE users (
id VARCHAR(20),
col SET('read', 'write', 'edit', 'delete'),
);
如果我想查询具有read
和write
privs的所有用户(无论其他任何值设置如何),我提出的获取行的唯一查询是:
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
类型时,工作示例是否是实现此目的的唯一方法。
答案 0 :(得分: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;
详细了解here.
更新:
privs+0 = 3
只会返回“read& write”。
就像我说的那样,无论值多长时间分配给一个条目,值都会按顺序存储。
所以你也可以这样做:
SELECT id, privs
FROM users
WHERE
privs = 'read,write';
如果你想至少阅读&写作可能更多:
SELECT id, privs
FROM users
WHERE
privs LIKE 'read,write%';
答案 1 :(得分: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'