2

我在同一个数据库中有两个表。

表 1,New_Company_Data它具有包含公司名称的列“Company_Name”nvarchar(120)。

和 Table2,Old_Company_data它有 3 列“Name1”nvarchar(40)、“Name2”nvarchar(40) 和“Name3”nvarchar(40)。

我想将数据从表New_Company_Data复制到表Old_Company_Data但在此之前我必须拆分“Company_Name”列中的公司名称。我试图拆分它,但它破坏了单词。

如何在不破坏单词的情况下拆分“Company_Name”字段中的数据:

如果公司名称 <=40,则不要拆分。

如果公司名称 >40 且 <=80,则将其分成两部分而不破坏单词。

如果公司名称 >80 且 <=120,则将其分成三部分而不破坏单词。

我正在使用以下代码,但它没有正确生成结果。例如,在下面的代码中,我将 string2 设为“ik u”。但在这里我想得到接下来的 40 个字符。

declare @strs nvarchar(120)

set @strs = 'AlufinishGesellschaftfür Verfahrenstechnik u. zur 

Metalloberflächenbehandlung mbH & C' --40

declare @lon int
declare @palabras int
declare @contador int
declare @posicion int
declare @string1 nvarchar(40)
declare @string2 nvarchar(40)
declare @string3 nvarchar(40)

--wordcount
set @palabras = LEN(@strs)-LEN(replace(@strs, ' ', ''))+1 --3
--words per batch

if (LEN(@strs)<=40) set @lon = @palabras
if (LEN(@strs)>40 AND LEN(@strs)<=80) set @lon = @palabras/2 --3 
if (LEN(@strs)>80 AND LEN(@strs)<=120) set @lon = @palabras/3

--set @lon = @palabras/3
set @contador = 1
set @posicion = 0
while @contador <= @lon
begin
-- search for the first batch
    set @posicion = CHARINDEX(' ',@strs,@posicion+1)-- here it will found 1st space
    set @contador = @contador+1
end 
set @string1 = Left(@strs, @posicion)

set @strs = replace(@strs, @string1, '')

set @contador = 1
set @posicion = 0
while @contador <= @lon
begin
-- search for the second batch
    set @posicion = CHARINDEX(' ',@strs,@posicion+1)
    set @contador = @contador+1
end 
set @string2 = LEFT(@strs, @posicion)
set @string3 = replace(@strs, @string2, '')

--use test
--update company_backup

--set company1=@string1,company2=@string3 where id=12
select @string1 as string1, @string2 as string2, @string3 as string3
4

1 回答 1

2

如果您创建以下函数:-

CREATE FUNCTION [dbo].WordWrap
(
    @WrapAt int,
    @Text nvarchar(1024)
)
RETURNS nvarchar(1024)
AS
BEGIN
    declare @ReturnValue nvarchar(1024);--the string to be passed back
    declare @Snip int;-- the length to snip to the last space before the wrapap value
    declare @Block int;-- the block number of the piece in the return string
    set @Block=1;-- initialise the block number
    set @Text=ltrim(rtrim(@Text));-- clean up the input string
    while charindex('  ',@Text)>0 begin -- if there are any double spaces
        set @Text=REPLACE(@Text,'  ',' '); -- replace them with single spaces
    end
    if (@Text is null or DATALENGTH(@Text)<=@WrapAt) begin -- if the input string is null or short enough for 1 block
        set @ReturnValue='<1>'+@Text+'</1>';-- load it into the return value and we're done
    end else begin -- otherwise we have some work to do
        set @ReturnValue='' -- so let's initialise the return value
        while DATALENGTH(@Text)>0 begin -- and keep going until we have finished
            -- if the character after the wrapat is a space or there is a space anywhere before the wrapat
            if SUBSTRING(@Text,@WrapAt+1,1)=' ' or CHARINDEX(' ',left(@Text,@WrapAt))>0 begin
                if SUBSTRING(@Text,@WrapAt+1,1)=' ' begin -- if the character after the wrapat is a space
                    set @Snip=@WrapAt-- we can snip to the wrapat
                end else begin
                    --otherwise we have to snip to the last space before the wrapat
                    set @Snip=@WrapAt-charindex(' ',reverse(left(@text,@WrapAt)));
                end
                -- now we can load the return value with snipped text as the current block
                set @ReturnValue+='<'+CONVERT(varchar,@Block)+'>'+left(@Text,@Snip)+'</'+CONVERT(varchar,@Block)+'>';
                -- and leave just what's left to process, by jumping past the space (@Snip+2)
                set @Text=SUBSTRING(@Text,@Snip+2,1024);
            end else begin-- otherwise we have no space to split to - so we can only cut the string at wrapat
                -- so we load the return value with the left hand wrapat characters as the current block
                set @ReturnValue+='<'+CONVERT(varchar,@Block)+'>'+LEFT(@Text,@WrapAt)+'</'+CONVERT(varchar,@Block)+'>';
                -- and leave just what's left to process, by jumping past the wrapat (@WrapAp+1)
                set @Text=SUBSTRING(@Text,@WrapAt+1,1024);
            end
        set @Block+=1-- increment the block number in case we still have more work to do
        end
    end
    RETURN @ReturnValue;
END
GO

并且您的表中加载了以下测试数据:-

create table New_Company_Data (
    Company_name varchar(120)
);
go
insert into New_Company_Data values (null);
insert into New_Company_Data values ('');
insert into New_Company_Data values ('   abc   abc    abc      abc');
insert into New_Company_Data values ('a');
insert into New_Company_Data select REPLICATE('a',40)+REPLICATE('b',40)+REPLICATE('c',40)
insert into New_Company_Data values ('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vehicula, quam non lobortis molestie, purus dui porta sed.');
go
select dbo.WordWrap(40,n.Company_name)
from New_Company_Data n

你得到以下返回: -

NULL
<1></1>
<1>abc abc abc abc</1>
<1>a</1>
<1>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</1><2>bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb</2><3>cccccccccccccccccccccccccccccccccccccccc</3>
<1>Lorem ipsum dolor sit amet, consectetur</1><2>adipiscing elit. Duis vehicula, quam non</2><3>lobortis molestie, purus dui porta sed.</3>

我留给您弄清楚如何将(伪 xml)字符串切碎到目标列中,这取决于解决方案需要的可重复性。如果它是一次性的 - 将我的函数的输出粘贴到输出表中的临时货物列中,然后使用更新语句将每个块一个接一个地拉出到所需的输出列中。如果您需要经常重复此操作,请编写一个创建临时表和游标的 SP,并将块同时移出到目标列中。显然,您可以将我的代码拆开并直接使用逻辑来形成动态更新语句(将 SET <targetfield> 添加到 <block value> 因为每个块都从输入字符串中剪断)以在末尾执行每个枚举。

我让你来决定如何进行(即使那是问一个更直接的问题,让你知道你想以哪种方式进行)。

于 2013-10-26T23:00:15.893 回答