2012-05-21 36 views
1

我想知道这是为什么代码不会返回任何结果查询分隔列值

SELECT A.PermissionGroupID, A.ApplicationID, CONVERT(nvarchar(5),A.PermissionID) AS Permission, A.PermissionName, B.PermissionGroupName, C.ApplicationName 
    FROM Permission AS A 
    JOIN PermissionGroup AS B ON A.PermissionGroupID = B.PermissionGroupID 
LEFT JOIN Application AS C ON A.ApplicationID = C.ApplicationID 
    WHERE (A.Active = 1) 
     AND (CONVERT(nvarchar(2),A.PermissionID) IN (SELECT Permissions 
                FROM UserPermissions 
                WHERE UserID = 1)) 

但是这一次是工作

SELECT A.PermissionGroupID, A.ApplicationID, CONVERT(nvarchar(5),A.PermissionID) AS Permission, A.PermissionName, B.PermissionGroupName, C.ApplicationName 
    FROM Permission AS A 
    JOIN PermissionGroup AS B ON A.PermissionGroupID = B.PermissionGroupID 
LEFT JOIN Application AS C ON A.ApplicationID = C.ApplicationID 
    WHERE (A.Active = 1) 
     AND (CONVERT(nvarchar(2), A.PermissionID) IN ('5','6','7','8')) 

这里是我的权限表的内容

Permission 
-------------------------------- 
Permission Permission Application Permission 
ID   Group   ID    Name 
4   1    1   VISA_APPLICATION_DELETE 
5   1    1   VISA_APPLICATION_PRINT 
6   4    10   APPLICATION_ADD 
7   4    10   APPLICATION_EDIT 
8   4    10   APPLICATION_DELETE 
9   4    10   APPLICATION_VIEW 

这里是我的UserPermissions表

的内容
UserPermissions 
-------------------------- 
UserPermission  UserID Permissions 
ID 
2   1   5,6,7,8 -> I tried to change it manually to this format ('5','6','7','8') but to no avail. 
+0

什么是这些表中? – Matthew

+0

您能否举例说明'UserPermissions'表的'Permissions'列中存储的内容(何时为空,一个值或多个值)? – van

+0

代码:越容易阅读,其他人就越有可能提供帮助。 –

回答

1

为什么我怀疑权限看起来像一个字符串“5,6,7,8”。我期望查询是“PermisionId(选择PermissionId from ...)”,而不是(选择权限)。

假设是这种情况,查询以下版本应该解决您的问题:

SELECT A.PermissionGroupID, A.ApplicationID, CONVERT(nvarchar(5),A.PermissionID) AS Permission, 
     A.PermissionName, B.PermissionGroupName, C.ApplicationName 
FROM Permission A JOIN 
    PermissionGroup B 
    ON A.PermissionGroupID = B.PermissionGroupID LEFT JOIN 
    Application AS C 
    ON A.ApplicationID = C.ApplicationID cross JOIN 
    (SELECT Permissions 
     FROM UserPermissions 
     WHERE UserID = 1 
    ) p1 
WHERE (A.Active = 1) AND 
     charindex(','+CONVERT(nvarchar(2)+',', A.PermissionID)+',', ','+p1.Permissions+',') > 0 

注意我前插和追加逗号因此“1”不匹配“15”。另外,这假定每个用户的UserPermissions中只有一行。

顺便说一下,您应该修复您的模式,以便UserPermissions为每个用户和权限分别设置一行,这样您的原始公式就可以工作。

+2

也许你怀疑它是因为标题是*“在SQL Server中查询**分隔列**值”*? –

+1

你需要检查你的'CHARINDEX'状态文件。它会失败。它包含一个像这样的转换语句** CONVERT(nvarchar(2)+',',A.PermissionID)**。您也不在考虑列表中的第一项,例如看起来你在列表中尝试达到目标**“1,2,3,4”**你永远不会匹配**“1”**因为你正在寻找**“,1,”* * – GarethD

+0

尝试'(权限LIKE CONVERT(NVARCHAR(2),A.PermissionID)+',%'或权限LIKE'%,'+ CONVERT(NVARCHAR(2),A.PermissionID)+',%')' – GarethD

0

从评论我看到你担心表现。性能问题是由于您存储逗号分隔的值的字符串,因此每个值应该有一行。
将表UserPermissions更改为这样的内容。

create table UserPermissions 
(
    UserID int references Users(UserID), 
    PermissionID int references Permission(PremissionID), 
    primary key (UserID, PermissionID) 
) 

和您的查询应该是...

SELECT A.PermissionGroupID, 
     A.ApplicationID, 
     A.PermissionID, 
     A.PermissionName, 
     B.PermissionGroupName, 
     C.ApplicationName 
FROM Permission AS A 
    JOIN PermissionGroup AS B 
    ON A.PermissionGroupID = B.PermissionGroupID 
    LEFT JOIN Application AS C 
    ON A.ApplicationID = C.ApplicationID 
WHERE A.Active = 1 AND 
     A.PermissionID IN (SELECT PermissionID 
         FROM UserPermissions 
         WHERE UserID = 1) 
+0

嗨Mikael,我在想事实会更容易,因为“JOIN”会更小。这就是为什么我决定将它存储在逗号分隔值中。我之所以将它作为分隔值,是因为除了个人权限之外,我的一个要求还是添加UserGroupPermission –

+0

@SherryAnnHernandez您应该以与UserGroup和Permission之间的联结表相同的方式创建UserGroupPermissions。这里有一些关于为什么使用逗号分隔值的想法是一个坏主意的链接。 [在数据库列中存储逗号分隔列表真的很糟糕吗?](http://stackoverflow.com/a/3653574/569436)。 –

+0

存储逗号分隔列表本身并不总是很糟糕。当您想要加入另一个表或快速查找单个值(不能使用索引)时,它只会成为性能噩梦。不要混淆数据库中正确的数据结构和查询结果。 –