2012-05-21 2 views
1

Я интересно, почему этот код не возвращает результатЗапросы разделителями значение столбца в SQL Server

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 
-------------------------- 
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» (когда пусто, одно значение или несколько значений)? – van

+0

Код: чем проще читать, тем более вероятны другие. –

ответ

1

Почему я подозреваю, что разрешения похожи на строку «5, 6, 7, 8». Я бы ожидал, что запрос будет «где PermissionId in (Select 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 

Примечание I PREPEND и добавить запятую так «1» не соответствует «15». Кроме того, это предполагает, что в UserPermissions для пользователя есть только одна строка.

Кстати, вы должны исправить свою схему, чтобы у UserPermissions была отдельная строка для каждого пользователя и разрешения, поэтому ваша оригинальная формулировка будет работать.

+2

Возможно, вы подозреваете, что это заголовок * «Запрос ** с разделителем столбца ** значение в SQL Server» *? –

+1

Вам нужно проверить свой статут 'CHARINDEX'. Это провалится. Он содержит преобразование так: ** CONVERT (nvarchar (2) + ',', A.PermissionID) **. Вы также не рассматриваете первый элемент в списке, например. с тем, что, по-видимому, вы пытаетесь достичь в списке ** «1,2,3,4» **, вы никогда не будете сопоставлять ** «1» **, потому что вы ищете ** «, 1,». * * – GarethD

+0

Try '(Разрешения 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

Привет, Микаэль, я думал, что это будет намного проще, так как «JOIN» будет меньше. Вот почему я решил сохранить его в значении с разделителями-запятыми.Причина также в том, что я делаю это разделенным значением, потому что, помимо индивидуального разрешения, одним из моих требований также является добавление UserGroupPermission –

+0

@SherryAnnHernandez. Вы должны создавать UserGroupPermissions таким же образом, как таблица соединений между UserGroup и Permission. Вот ссылка на некоторые мысли о том, почему использование значения с разделителями-запятыми - плохая идея. [Сохраняет ли список разделенных запятыми столбцов базы данных действительно так плохо?] (Http://stackoverflow.com/a/3653574/569436). –

+0

Сохранение списка, разделенного запятой, само по себе не всегда. Это просто становится кошмаром производительности, когда вы хотите присоединиться к другой таблице или быстро найти одно значение (не можете использовать индексы). Не путайте правильную структуру данных в базе данных с тем, что вы хотите видеть в качестве результатов запроса. –

Смежные вопросы