之前项目的需求:创建活动,活动可以勾选不定数量的类别Type。
贪求进度,于是在Event表直接加了一个Type Column,用字符串数组保存类别信息。
这样无论是新增,还是更新,DB操作起来起来都相当的便捷,美滋滋~
直到接到了新需求:需要按照不同的类别读取活动的数据😂。
1,创建自定义SQL Server函数,将字符串分割为字符数组
/****** Object: UserDefinedFunction [dbo].[splitl] Script Date: 2021/4/12 22:55:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[splitl] (
@String VARCHAR(MAX),
@Delimiter VARCHAR(MAX)
) RETURNS @temptable TABLE (items VARCHAR(MAX)) AS
BEGIN
DECLARE @idx INT=1
DECLARE @slice VARCHAR(MAX)
IF LEN(@String) < 1 OR LEN(ISNULL(@String,'')) = 0
RETURN
WHILE @idx != 0
BEGIN
SET @idx = CHARINDEX(@Delimiter,@String)
IF @idx != 0
SET @slice = LEFT(@String,@idx - 1)
ELSE
SET @slice = @String
IF LEN(@slice) > 0
INSERT INTO @temptable(items) VALUES(@slice)
SET @String = RIGHT (@String, LEN(@String) - @idx)
IF LEN(@String) = 0
BREAK
END
RETURN
END
GO
执行上述函数,则有如下类似的结果:
2, 将获得的type id的数组与EventType Table关联查询
declare @e_type_table TABLE(
[E_ID] [int] NULL,
[EFT_ID] [int] NULL,
[EFT_NameChi] [nvarchar](50) NULL
);
declare @ei_id_table table( EI_ID int);
insert into @ei_id_table(EI_ID) select [EI_ID] from [dbo].[Event_Info]
declare @EI_ID as int
while exists(select EI_ID from @ei_id_table)
begin
select top 1 @EI_ID = EI_ID FROM @ei_id_table;
insert into @e_type_table(E_ID,EFT_ID,EFT_NameChi)
(select @EI_ID as EI_ID,t.EFT_ID,t.EFT_NameChi from (select items as id from dbo.splitl((select [EI_Types] from [dbo].[Event_Info] where [EI_ID] = @EI_ID),',') ) as e
left join [dbo].[Event_Facility_Type] as t on e.id = t.EFT_ID)
delete from @ei_id_table where EI_ID = @EI_ID;
end
select * from @e_type_table
得到的结果如下:
后续:
这种方法,写入的时候简便,但读取的时候麻烦,而且效率比较低下。
应该创建一个Link Table,将Event跟Type关联起来。写入的时候稍麻烦,但是免去了以后读取的烦心事。
Link Table的Column大致有: ID, EventID, TypeID, Status(bit)...
那么写入的思路就是:
每次前端只返回勾选的Type ID的数组->
----用户勾选Type,但是从未建立过关联,需要新增关联
----用户勾选Type,然而虽然建立过关联,但是Status = false,需要变更其关联的Status为true
----用户取消之前的勾选,然而已经建立过关联,并且Status = true,需要变更其关联的Status为false