2016-07-13 56 views
0

我在表中的一個有一個USER_ROLE列,這已經管分離像解析管分隔值

guest|user_Admin|user_guest 
user_Admin|guest 
guest|user_guest|user_Admin 
user_guest|user_Admin 
user_Admin 

我必須從上面的表格,其中有得到角色值管理在它。 我不想整個行都有Admin。

例如,如果列數據是客| user_guest | user_Admin,查詢應該只返回user_Admin而不是完整的價值。

我該如何實現它?

+0

你可以寫一個case語句,例如'CASE WHEN User_Role LIKE'%user_Admin%'THEN'user_Admin'END'或者如果你只想要user_Admin作爲用戶角色的用戶,那麼'SELECT'user_Admin'FROM myTable WHERE User_Role LIKE'%user_Admin%''或類似的東西。 – ZLK

+1

[在sql中管道分隔的列中搜索值的可能重複](http://stackoverflow.com/questions/18767077/search-value-in-column-which-is-pipe-separated-in-sql) –

+0

我不想硬編碼價值。我想從數據中推導出它。 – turbo88

回答

-1

這應該工作。它使用遊標來處理每個角色。

--- --- UPDATE

更新光標處理以覆蓋許多邊緣情況。

DECLARE @roles varchar(1000), @ADMININDEX int, @STARTINDEX int, @ENDINDEX int, @TEMP varchar(1000) 

DECLARE MY_CURSOR CURSOR 
    LOCAL STATIC READ_ONLY FORWARD_ONLY 
FOR 
SELECT roles 
FROM test 

OPEN MY_CURSOR 
FETCH NEXT FROM MY_CURSOR INTO @roles 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    --Do something with Id here 
    SET @ADMININDEX = CHARINDEX('Admin',@roles) 
    IF (@ADMININDEX > 0) 
    BEGIN 
     SET @ADMININDEX += 5 
     SET @TEMP = CHARINDEX('|', SUBSTRING(@roles, @ADMININDEX, LEN(@roles))) 
     IF @TEMP = 0 
      SET @ENDINDEX = LEN(@roles) + 1 
     ELSE 
      SET @ENDINDEX = @TEMP - 1 + @ADMININDEX 
     SET @roles = SUBSTRING(@roles, 0, @ENDINDEX) 
     SET @STARTINDEX = LEN(@roles) - CHARINDEX('|', REVERSE(@roles)) + 2 
     IF (@STARTINDEX>@ADMININDEX) 
      PRINT @roles 
     ELSE 
      PRINT SUBSTRING(@roles, @STARTINDEX, @ENDINDEX) 
    END 
    FETCH NEXT FROM MY_CURSOR INTO @roles 
END 
CLOSE MY_CURSOR 
DEALLOCATE MY_CURSOR 
+0

這在技術上只適用於用戶角色類似'xyz_admin'的情況。如果用戶的角色類似於「admin_xyz」,則不會得到正確的結果。它也不適用於沒有管理員角色的用戶(如果這很重要)。 – ZLK

+0

@ZLK這些情況是非常容易繞過一些小的修改。我只是根據提供的樣本奠定了基礎。 – 10100111001

+0

爲什麼downvote被給出的原因將是有幫助的。 – 10100111001

1

首先,我要告訴你你應該怎麼做......規範你的表。

如果有問題的表是用戶角色表,那麼將您的user_role列拆分爲單個值。如果它是包含其他列的較大表的一部分,則應使用單獨的表來存儲用戶角色信息。我還建議爲每個值分配不同的級別,因此您不必分析字符串。

例如,有一個像

CREATE TABLE userRoles (userID INT, userRole INT); 

一個user_roles表...然後有一個角色表所示:

CREATE TABLE Roles (userRole INT IDENTITY(1, 1), roleDescription VARCHAR(255), roleLevel INT); 
INSERT Roles (roleDescription, roleLevel) VALUES ('guest', 1), ('user_guest', 2), ('user_Admin', 3); 

......這樣一來,你可以找到做管理員角色加入並尋找3級而不是解析字符串。如果你的表很小,沒有什麼大不了的,但是你的表越大,解析字符串的成本就越高。通過適當的索引,這將成爲檢索所需數據的最快方法,同時還可以根據需要輕鬆更改數據(需要更改角色名稱?沒問題...在Roles表中編輯roleDescription)。

但是做不到這一點,這裏有一對夫婦的解決方案,你可以考慮......

declare @1 table (ID INT IDENTITY(1, 1), User_Role varchar(255)); 
insert @1 (User_Role) values ('guest|hello_Kitty_Admin|user_guest'),('user_Admin_zzz|guest'),('guest|user_guest|greatest_admin_of_all_time'),('user_guest|user_Admin2'),('user_Admin'),('regular_user'); 
with t as (
    select id, user_role, left(User_Role, charindex('admin', User_Role) + isnull(nullif(charindex('|', substring(User_Role, charindex('admin', User_Role), len(User_Role))), 0) - 2, len(User_Role))) zzz 
    from @1) 
select id, isnull(right(zzz, isnull(nullif(charindex('|', reverse(zzz)), 0) - 1, len(zzz))), user_role) adminrole 
from t; 

...上述所有正在做的是解析您USER_ROLE柱,發現其中admin是和獲取一切行括號之間該值(如果不存在,它只是返回全額USER_ROLE)

declare @2 table(ID INT IDENTITY(1, 1), User_Role varchar(255)); 
insert @2 (User_Role) values ('guest|hello_Kitty_Admin|user_guest'),('user_Admin_zzz|guest'),('guest|user_guest|greatest_admin_of_all_time'),('user_guest|user_Admin2'),('user_Admin'),('regular_user'); 
with cte as (
    select id, user_role, substring(user_role, 1, isnull(nullif(charindex('|', user_role), 0) - 1, len(user_role))) roles, nullif(charindex('|', user_role), 0) cindex, 1 L 
    from @2 
    union all 
    select id, user_role, substring(user_role, cindex+1, isnull(nullif(charindex('|', user_role, cindex+1), 0) - 1 - cindex, len(user_role))), nullif(charindex('|', user_role, cindex+1), 0), L + 1 
    from cte 
    where cindex is not null) 
select id, max(isnull(x.y, user_role)) adminrole 
from cte t 
outer apply (
    select min(roles) over (partition by len(roles)) 
    from cte 
    where id = t.id 
    and roles like '%admin%') x(y) 
group by id, x.y 
order by id; 

...這是在做同樣的事情,另外一個用不同的方法。

或者您可以使用類似於其他答案的光標,稍作修改。

但真的,正常化!