目前,我正在开展一个项目,我们刚刚添加了在字段中存储多个值的功能。以前,它存储了一个值,但现在它包含多个值。以下是我所谈论的一个例子。
实施例。传递一个人的名字(John Smith)。现在,用户可以传递多个人的姓名,由''分隔。 (John Smith; John Doe; Jane Tandy)。
我的问题是,我们有一个下拉列表的数据源,该数据源当前从该字段开始。下面是它的SQL。
Select Distinct Content
From LIB_DocumentAttribute A
inner join LIB_PublicDocument B on A.PublicDocumentId = B.PublicDocumentId
Where AttributeId = (Select AttributeId From LIB_Attribute Where FieldName='Author')
and B.Status = 'Approved'
这在某种程度上有效。内容是包含多个名称的字段。现在当加载下拉列表时,它会拉回串联的名称字符串(从上面开始的更长的名称)。我想将它拆分为数据源。到目前为止,我唯一的想法是根据''分出数据。但是,我需要将拆分数据并将其应用于返回其余数据的表。下面是我已经达到但已经陷入困境的地方。
CREATE TABLE #Authors
(
Content varchar(MAX)
)
CREATE TABLE #Temp1
(
Content varchar(MAX)
)
CREATE TABLE #Temp2
(
Content varchar(MAX)
)
CREATE TABLE #Temp3
(
Content varchar(MAX)
)
--Load Authors table to store all Authors
INSERT INTO #Authors
Select Distinct Content
From LIB_DocumentAttribute A
inner join LIB_PublicDocument B on A.PublicDocumentId = B.PublicDocumentId
Where AttributeId = (Select AttributeId From LIB_Attribute Where FieldName='Author')
and B.Status = 'Approved'
--Take multiple Authors separated by '; ' and add to Temp1
INSERT INTO #Temp1
SELECT REPLACE(Content, '; ', ';') FROM #Authors WHERE Content LIKE '%; %'
--Remove multiple Authors separated by '; ' from Authors table
DELETE FROM #Authors
WHERE Content LIKE '%; %'
--Take multiple Authors separated by ';' and add to Temp2
INSERT INTO #Temp2
SELECT Content FROM #Authors WHERE Content LIKE '%;%'
--Remove multiple Authors separated by ';' from Authors table
DELETE FROM #Authors
WHERE Content LIKE '%;%'
--Somewhow split data and merge back together
DROP TABLE #Authors
DROP TABLE #Temp1
DROP TABLE #Temp2
DROP TABLE #Temp3
编辑:
所以最后,我提出了一个解决方案,利用了Kumar建议的一些部分。我创建了一个按照他的建议拆分字符串的函数,并添加了一些个人更改以使其工作。请注意,这是一个表返回函数,使用名为@Authors的表,它有一个名为Content的列。
BEGIN
DECLARE @Temp TABLE
(
Content varchar(MAX)
)
--Load Authors table to store all Authors
INSERT INTO @Authors
Select Distinct Content
From LIB_DocumentAttribute A
inner join LIB_PublicDocument B on A.PublicDocumentId = B.PublicDocumentId
Where AttributeId = (Select AttributeId From LIB_Attribute Where FieldName='Author')
--Take multiple Authors separated by ', ' and add to Temp
INSERT INTO @Temp
SELECT REPLACE(Content, ', ', ',')
FROM @Authors;
--Remove multiple Authors separated by ', ' from Authors table
DELETE FROM @Authors
WHERE Content LIKE '%,%';
--Readd multiple Authors now separated into Authors table
INSERT INTO @Authors
SELECT s.Content
FROM @Temp
OUTER APPLY SplitString(Content,',') AS s
WHERE s.Content <> (SELECT TOP 1 a.Content FROM @Authors a WHERE s.Content = a.Content)
RETURN
END
答案 0 :(得分:1)
在fiddler链接http://sqlfiddle.com/#!3/390f8/11
中查看演示Create table test(name varchar(1000));
Insert into test values('AAA BBB; CCC DDD; eee fff');
CREATE FUNCTION SplitString
(
@Input NVARCHAR(MAX),
@Character CHAR(1)
)
RETURNS @Output TABLE (
Item NVARCHAR(1000)
)
AS
BEGIN
DECLARE @StartIndex INT, @EndIndex INT
SET @StartIndex = 1
IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character
BEGIN
SET @Input = @Input + @Character
END
WHILE CHARINDEX(@Character, @Input) > 0
BEGIN
SET @EndIndex = CHARINDEX(@Character, @Input)
INSERT INTO @Output(Item)
SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1)
SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))
END
RETURN
END
Declare @name varchar(100)
Declare @table as table(name varchar(1000))
Declare cur cursor for
Select name from test
Open cur
fetch next from cur into @name
while (@@FETCH_STATUS = 0)
begin
Insert into @table
Select * from dbo.splitstring(@name,';')
fetch next from cur into @name
end
close cur
deallocate cur
Select * from @table
答案 1 :(得分:1)
这可能有用。
drop table authors
GO
create table Authors (Author_ID int identity (1,1),name varchar (255), category varchar(255))
GO
insert into authors
(name,category)
select
'jane doe','nonfiction'
union
select
'Jules Verne; Mark Twain; O. Henry', 'fiction'
union
select
'John Smith; John Doe', 'nonfiction'
GO
DECLARE @table TABLE (
names VARCHAR(255)
,id INT
)
DECLARE @category VARCHAR(255)
SET @category = 'nonfiction'
DECLARE @Author_ID INT
DECLARE AuthorLookup CURSOR
FOR
SELECT Author_ID
FROM authors
WHERE category = @category
OPEN AuthorLookup
FETCH NEXT
FROM AuthorLookup
INTO @Author_ID
WHILE @@FETCH_STATUS = 0
BEGIN
IF (
SELECT CHARINDEX(';', NAME, 0)
FROM authors
WHERE Author_ID = @Author_ID
) = 0
BEGIN
INSERT INTO @table
SELECT NAME
,Author_ID
FROM authors
WHERE Author_ID = @Author_ID
END
ELSE
BEGIN
DECLARE @value VARCHAR(255)
SELECT @value = NAME
FROM authors
WHERE Author_ID = @Author_ID
WHILE len(@value) > 0
BEGIN
INSERT INTO @table
SELECT substring(@value, 0, CHARINDEX(';', @value, 0))
,@Author_ID
SELECT @value = replace(@value, substring(@value, 0, CHARINDEX(';', @value, 0) + 2), '')
IF CHARINDEX(';', @value, 0) = 0
BEGIN
INSERT INTO @table
SELECT @value
,@Author_ID
SET @value = ''
END
END
END
FETCH NEXT
FROM AuthorLookup
INTO @Author_ID
END
CLOSE AuthorLookup
DEALLOCATE AuthorLookup
SELECT *
FROM @table
答案 2 :(得分:0)
您可以创建分割数据的功能
create function SplitString
(
@data nvarchar(max),
@sep char(1)
)
returns @result table (data nvarchar(max))
as
begin
declare @i int
while 1 = 1
begin
select @i = charindex(@sep, @data)
if @i = 0
begin
insert into @result
select @data
break
end
insert into @result
select rtrim(left(@data, @i - 1))
select @data = ltrim(right(@data, len(@data) - @i))
end
return
end
并像这样使用它:
select s.data
from test as t
outer apply SplitString(t.data,';') as s
如果你确定数据中没有特殊字符,你也可以考虑使用xml技巧:
;with cte as (
select
cast('<s>' + replace(data, ';', '</s><s>') + '</s>' as xml) as data
from test
)
select
t.c.value('.', 'nvarchar(max)') as data
from cte
outer apply data.nodes('s') as t(c)
<强> sql fiddle demo 强>