如何在存储过程中将EventAccessIds = 1 + 4 + 8分解为EventId = 1,EventId = 4和EventId = 8?

时间:2015-11-19 21:53:04

标签: sql asp.net database

用户可以访问特定事件。我在User中有一行名为EventAccessIds。我希望用户可以通过某种方式访问​​所有ID。如果用户A应该访问事件1,4和8,那么EventAccessIds应该是1 + 4 + 8或类似的东西。

然后我想拉出那些ID并使用Select语句填充不同区域的数据(下拉列表,网格视图等)。基本上,它将为用户A填充事件ID为1,4和8的数据。

问题是,我是数据库和SQL的新手,所以我不太确定如何编写所有这些代码。我正在使用存储过程。我想也许是这样的事情将EventAccessIds发送到事件:

WITH first AS
    (
   SELECT EventAccessIds
    FROM Users
    WHERE UserName = @UserName
    ), second AS
    (
    SELECT *
    FROM Event
    WHERE EventId = EventAccessIds
    )

但是如何将EventAccessIds = 1 + 4 + 8分解为EventId = 1,EventId = 4和EventId = 8?

EDIT spGetAllEvents

USE [Events2]
GO
/****** Object:  StoredProcedure [dbo].[spGetAllEvents]    Script Date: 11/19/2015 9:03:42 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spGetAllEvents]
    @UserName nVarChar(80)
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
WITH first 
AS 
( 
    SELECT EventAccessIds 
    FROM Users 
    WHERE UserName = @UserName
), second AS 
(
    SELECT e.* FROM [Event] as e
    WHERE e.EventId in
    (
        SELECT convert(int, s.Data)
        FROM [first] as f
        CROSS APPLY
        (SELECT * FROM dbo.Split(f.EventAccessIds, '+')) as s
    )
)
END

用户(第1张图片)和活动(第2张图片) Users

Event

2 个答案:

答案 0 :(得分:2)

如果我理解你的要求,那就是这样的? SQL Fiddle demo

declare @input varchar(max) 
DECLARE @SQLString nvarchar(500)
DECLARE @ParmDefinition nvarchar(500)
DECLARE @result varchar(max) 

set @input = '1+4+8'

SET @SQLString = N'SELECT @result = ' + @input

SET @ParmDefinition = N'@result varchar(max)  OUTPUT'

EXECUTE sp_executesql @SQLString, @ParmDefinition, @result=@result OUTPUT
SELECT @result

declare @eventTable table (id int, data varchar(max))
insert into @eventTable select 1, 'Event id 1'
insert into @eventTable select 2, 'Event id 2'
insert into @eventTable select 4, 'Event id 4'
insert into @eventTable select 8, 'Event id 8'

select * 
from @eventTable et
where (id & @result) = id

答案 1 :(得分:1)

首先,您必须使用自己的函数拆分EventAccessIds,因为SQL Server没有Split函数。

其中一个很好的例子发布在Ole Michelsen's blog

CREATE FUNCTION [dbo].[Split]
(
    @String NVARCHAR(4000),
    @Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
    WITH Split(stpos,endpos)
    AS(
        SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
        UNION ALL
        SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
            FROM Split
            WHERE endpos > 0
    )
    SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
        'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)
    FROM Split
)
GO

然后,您可以像使用int数组一样使用拆分表:

WITH first AS
(
    SELECT EventAccessIds
    FROM Users
    WHERE UserName = @UserName
), second AS
(
    SELECT *
    FROM Event
    WHERE EventId IN (SELECT CONVERT(int, Data) FROM dbo.Split(EventAccessIds, '+')
)

<强>已更新

由于您的[第二个]查询似乎引用了[first]查询中选择的EventAccessIds,因此它应该是这样的:

WITH first 
AS 
( 
    SELECT EventAccessIds 
    FROM Users 
    WHERE UserName = @UserName
), second AS 
(
    SELECT e.* FROM [Event] as e
    WHERE e.EventId in
    (
        SELECT convert(int, s.Data)
        FROM [first] as f
        CROSS APPLY
        (SELECT * FROM dbo.Split(f.EventAccessIds, '+')) as s
    )
)