Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server 2016 T-SQL将逗号字符串转换为内部联接数据库名称_Sql Server_Tsql_Sql Server 2016 - Fatal编程技术网

Sql server SQL Server 2016 T-SQL将逗号字符串转换为内部联接数据库名称

Sql server SQL Server 2016 T-SQL将逗号字符串转换为内部联接数据库名称,sql-server,tsql,sql-server-2016,Sql Server,Tsql,Sql Server 2016,我有一个列的值,如下所示: ID | userPerms | Name | DOB -----+-----------+-----------+---------- 5985 |1,3,4 |Bob Barker |12/12/1923 895 |1,2 |Bill Gates |10/14/1955 5897 |1,2,4 |Steve Jobs |02/24/1955 SET DATEFORMAT mdy; DECLARE @tblDat

我有一个列的值,如下所示:

ID   | userPerms | Name      | DOB
-----+-----------+-----------+----------
5985 |1,3,4      |Bob Barker |12/12/1923
895  |1,2        |Bill Gates |10/14/1955
5897 |1,2,4      |Steve Jobs |02/24/1955
SET DATEFORMAT mdy;

DECLARE @tblData TABLE(ID INT, userPerms VARCHAR(100),Name VARCHAR(100),DOB DATE);
INSERT INTO @tblData VALUES
 (5985,'1,3,4','Bob Barker','12/12/1923')
,(895,'1,2','Bill Gates','10/14/1955')
,(5897,'1,2,4','Steve Jobs','02/24/1955');

DECLARE @tblPerm TABLE(ID INT, Perm VARCHAR(100));
INSERT INTO @tblPerm VALUES
 (1,'Read')
,(2,'Write')
,(3,'Upload')
,(4,'Admin');

SELECT d.ID,d.Name,d.DOB 
      ,STRING_AGG(p.Perm,',') AS Perms
FROM @tblData AS d
CROSS APPLY STRING_SPLIT(d.userPerms,',') AS A
INNER JOIN @tblPerm AS p ON CAST(A.value AS INT)=p.ID --<-- added cast to int
GROUP BY d.ID,d.Name,d.DOB;
该列是userPerms列

我需要能够内部连接与这些数字相关联的userPerm表

我的查询当前为:

SELECT 
    uT.employeeID + '|' + uT.lastFirstMiddle + '|' + uT.ntName + '|' + uT.email + '|' + 
    uT.firstName  + '|' + uT.lastName        + '|' + uT.active + '|' + uT.userPerms + '|' + 
    uT.userPermPages 
FROM 
    usersTbl AS uT
INNER JOIN 
    usersPermissions AS uP ON uP.id = uT.userPerms 
WHERE 
    uT.id = 1
当然,它不会工作,因为数据中有逗号

因此,我在输出中寻找的是:

ID   | userPerms        | Name      | DOB
-----+------------------+-----------+------------
5985 |Read,Upload,Admin |Bob Barker |12/12/1923
895  |Read,Write        |Bill Gates |10/14/1955
5897 |Read,Write,Admin  |Steve Jobs |02/24/1955
有没有人知道如何将它们分开,以便内部连接按设计工作

更新1

我让它工作了,但是:

它不会将userperm组合到原始字符串中

SELECT 
    uT.employeeID + '|' + uT.lastFirstMiddle + '|' + uT.ntName + '|' + 
    uT.email + '|' + uT.firstName + '|' + uT.lastName + '|' + uT.active, 
    (
        SELECT 
            ',' + uP.type
        FROM 
            usersPermissions AS uP
        WHERE 
            ',' + uT.userPerms + ',' 
        LIKE 
            '%,' + cast(uP.id AS nvarchar(20)) + ',%'
        FOR 
            XML PATH(''), TYPE
    ).value('substring(text()[1], 2)', 'varchar(max)') AS userPerms,
    (
        SELECT 
            ',' + uP.name
        FROM 
            pagePermissions AS uP
        WHERE 
            ',' + uT.userPerms + ',' 
        LIKE 
            '%,' + cast(uP.id AS nvarchar(20)) + ',%'
        FOR 
            XML PATH(''), TYPE
    ).value('substring(text()[1], 2)', 'varchar(max)') AS userPermPages
FROM 
    usersTbl as uT 
WHERE 
    uT.id = '1';

对于这样的ID列表,DB设计不是很好。最好使用关系表来存储多对多关系。也就是说,这可能会奏效:


我们的想法是在uT.userPerms的开头和结尾添加逗号,并使用like运算符连接到uP.id的任何出现,在uT.userPerms中也用逗号包围。

好吧,你问我……:-

我目前没有安装SQL Server 2016,因此这是未经测试的air代码。但我认为你需要这样的东西:

ID   | userPerms | Name      | DOB
-----+-----------+-----------+----------
5985 |1,3,4      |Bob Barker |12/12/1923
895  |1,2        |Bill Gates |10/14/1955
5897 |1,2,4      |Steve Jobs |02/24/1955
SET DATEFORMAT mdy;

DECLARE @tblData TABLE(ID INT, userPerms VARCHAR(100),Name VARCHAR(100),DOB DATE);
INSERT INTO @tblData VALUES
 (5985,'1,3,4','Bob Barker','12/12/1923')
,(895,'1,2','Bill Gates','10/14/1955')
,(5897,'1,2,4','Steve Jobs','02/24/1955');

DECLARE @tblPerm TABLE(ID INT, Perm VARCHAR(100));
INSERT INTO @tblPerm VALUES
 (1,'Read')
,(2,'Write')
,(3,'Upload')
,(4,'Admin');

SELECT d.ID,d.Name,d.DOB 
      ,STRING_AGG(p.Perm,',') AS Perms
FROM @tblData AS d
CROSS APPLY STRING_SPLIT(d.userPerms,',') AS A
INNER JOIN @tblPerm AS p ON CAST(A.value AS INT)=p.ID --<-- added cast to int
GROUP BY d.ID,d.Name,d.DOB;

将拆分函数与交叉应用一起使用如何?然后将结果转换为CSV?有没有可能修复数据结构?存储带分隔符的数据违反了1NF的规定,并且会造成令人难以置信的痛苦。实际上,这种事情应该由角色来处理,而不是由每个用户来处理。将权限分配给角色,然后将用户分配给角色。SQL Server 2016提供STRING_SPLIT和STRING_AGG。使用第一个和CROSS APPLY将您的ID作为派生表,然后使用连接绑定您的值,最后使用第二个重新关联结果。@danihp真的!Codd将varchar值“%”、“+uT.userPerms+”、“like%”、“+castuP.id as nvarchar20+”、“%”转换为数据类型int时,保存quee…ry.-d转换失败,但仍然显示数字。“STRING_AGG”不是可识别的内置函数名。@StealthRT是否确实在SQL Server 2016上运行,目标数据库是否处于适当的兼容性级别,SSM是否为合适的版本?无法测试它。。。阅读MSDN中的两个函数。如果您无法使这些功能正常工作,有几种方法可以替换这些功能。
create table  #tblData (ID INT, userPerms VARCHAR(100),Name VARCHAR(100),DOB DATE);
INSERT INTO #tbldata VALUES
 (5985,'1,3,4','Bob Barker','12/12/1923')
,(895,'1,2','Bill Gates','10/14/1955')
,(5897,'1,2,4','Steve Jobs','02/24/1955');

create table   #tblPerm (ID INT, Perm VARCHAR(100));
INSERT INTO #tblPerm VALUES
 (1,'Read')
,(2,'Write')
,(3,'Upload')
,(4,'Admin');    

Create FUNCTION [dbo].[fnSplitString] 
    ( 
        @string NVARCHAR(MAX), 
        @delimiter CHAR(1) 
    ) 
    RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
    ) 
    BEGIN 
        DECLARE @start INT, @end INT 
        SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
        WHILE @start < LEN(@string) + 1 BEGIN 
            IF @end = 0  
                SET @end = LEN(@string) + 1

            INSERT INTO @output (splitdata)  
            VALUES(SUBSTRING(@string, @start, @end - @start)) 
            SET @start = @end + 1 
            SET @end = CHARINDEX(@delimiter, @string, @start)

        END 
        RETURN 
    END
    go
    ;with cte
    as
    (
    select t1.ID,t1.userPerms,t1.Name,t3.Perm ,t1.DOB from #tblData as t1
    cross apply 
    dbo.fnsplitstring(t1.userPerms,',') as t2
    join #tblPerm as t3
    on t3.ID=t2.splitdata
    )

    select id,STUFF((select ','+perm from cte t1 
    where t1.ID=t2.id 
    for XML path('')),1,1,'')  as userperms,Name,DOB
    from cte t2
    group by id ,name,DOB