2012-02-21 79 views
-1

我有一个名为Spool的表,并且有一个名为“NAME”的字段。该字段有一个由破折号分隔的7个值的字符串。基于另一个字段填充表中的字段的脚本

我必须在SQL Server中执行一个脚本,用短划线分隔字符串“NAME”并记录7个不同列中的7个值。

例如 名称:ABCD-0123-ASD 在COLUMN1必须记录ABCD,在列2:0123和栏3 ASD ..等 我希望我已经解释=)

谢谢!

我正在使用SQL 2008,也是在我真正的问题中,我的字符串“NAME”中有7段,我必须将该字段的每个段放在7列中。

此外,我有表中的记录n个至极适用该脚本=) 感谢您帮助


HI杜威我有这样的:

Create FUNCTION [dbo].[SPReturnThreeFields] (@str NVARCHAR(max), @delimiter NCHAR(1)) 

AS 
BEGIN 
    declare @strOriginal NVARCHAR(max), @f1 varchar(max), @f2 varchar(max), @f3 varchar(max), @f4 varchar(max),@f5 varchar(max),@f6 varchar(max),@f7 varchar(max), @bool int = 0; 

    -- Field 1 
    set @f1=(left(@str,CHARINDEX(@delimiter,@str,1)-1)); 
    SET @str=RIGHT(@str,LEN(@str)-CHARINDEX(@delimiter,@str,1)); 

    -- Field 2 
    set @f2=(left(@str,CHARINDEX(@delimiter,@str,1)-1)); 
    SET @str=RIGHT(@str,LEN(@str)-CHARINDEX(@delimiter,@str,1)); 

    -- Field 3 
    set @f3 = (left(@str,CHARINDEX(@delimiter,@str,1)-1)); 
    SET @str=RIGHT(@str,LEN(@str)-CHARINDEX(@delimiter,@str,1)); 

    set @f4 = (left(@str,CHARINDEX(@delimiter,@str,1)-1)); 
    SET @str=RIGHT(@str,LEN(@str)-CHARINDEX(@delimiter,@str,1)); 

    set @f5 = (left(@str,CHARINDEX(@delimiter,@str,1)-1)); 

    set @bool = case when patindex('%' + @delimiter + '%' , @str) <> 0 then 0 else 1 end; 
    SET @str= case when @bool = 0 then RIGHT(@str,LEN(@str)-CHARINDEX(@delimiter,@str,1)) else @str end;  

    set @f6 = case when patindex('%' + @delimiter + '%' , @str) < 1 then case when @bool = 0 then @str else '' end else (left(@str,CHARINDEX(@delimiter,@str,1)-1)) end; 

    set @bool = case when patindex('%' + @delimiter + '%' , @str) <> 0 then 0 else 1 end; 
    SET @str= case when @bool = 0 then RIGHT(@str,LEN(@str)-CHARINDEX(@delimiter,@str,1)) else @str end;   

    set @f7 = case when patindex('%' + @delimiter + '%' , @str) < 1 then case when @bool = 0 then @str else '' end else (left(@str,CHARINDEX(@delimiter,@str,1)-1)) end; 

    --update dbo.Spool SET Segmento1 = @f1,Segmento2 = @f2,Segmento3 = @f3,Segmento4 = @f4, Segmento5 = @f5, Segmento6 = @f6, Segmento7 = @f7 where Nombre = @strOriginal; 

END 

GO 

显然,它工作正常但是如果我想在同一个表中进行更新,如何调用函数或必须是存储过程呢? 感谢您的帮助!

+0

请写明您使用的SQL Server版本。 – 2012-02-21 01:34:57

+0

我正在使用SQL 2008 – user1222295 2012-02-21 16:09:42

回答

0

这并不严格需要一个CTE,但它保持SUBSTRING/CHARINDEX/etc的数量。计算降到最低。

;WITH x AS 
(
    SELECT 
     Name, 
     fdash = CHARINDEX('-', Name), 
     ldash = CHARINDEX('-', REVERSE(Name)), 
     slen = LEN(Name) 
    FROM dbo.Spool 
    -- WHERE clause goes here 
) 
INSERT dbo.OtherTable(Column1, Column2, Column3) 
SELECT 
    Column1 = LEFT(Name, fdash - 1), 
    Column2 = SUBSTRING(Name, fdash + 1, slen - fdash - ldash), 
    Column3 = RIGHT(Name, ldash - 1) 
FROM x; 

这假定每个值有两个破折号。如果你不能保证(例如,它没有用约束强制执行),你应该在上面放置一个where子句,或者定义你想要做什么,如果有0,1或者2破折号。 where子句是:

WHERE LEN(Name) - LEN(REPLACE(Name, '-', '')) = 2 
+0

这项工作很好用2破折号,但如果有更多的破折号?我有6破折号作为最大值,我有7列在同一个表中,我必须填写此列,如果有字段名称段。也可能是不是所有的列都可以填充的可能性 非常感谢您的帮助! =) – user1222295 2012-02-21 16:12:17

0

此表值函数将允许各种分隔符。

兼容性是SQL 2005+

---------------------------------------- 
-- Define function 
CREATE FUNCTION dbo.fnReturnThreeFields (@str NVARCHAR(max), @delimiter NCHAR(1)) 
RETURNS @retval TABLE(Field1 NVARCHAR(max), Field2 NVARCHAR(max), Field3 NVARCHAR(max)) 
AS 
BEGIN 
    declare @f1 varchar(max), @f2 varchar(max), @f3 varchar(max); 

    -- Field 1 
    set @f1=(left(@str,CHARINDEX(@delimiter,@str,1)-1)); 
    SET @str=RIGHT(@str,LEN(@str)-CHARINDEX(@delimiter,@str,1)); 

    -- Field 2 
    set @f2=(left(@str,CHARINDEX(@delimiter,@str,1)-1)); 

    -- Field 3 
    SET @f3=RIGHT(@str,LEN(@str)-CHARINDEX(@delimiter,@str,1)); 

    insert into @retval values (@f1,@f2,@f3); 

    RETURN; 
END 
GO 

---------------------------------------- 
-- define test tables 
declare @table1 table(Name NVARCHAR(max)); 
declare @table2 table(Field1 NVARCHAR(max), Field2 NVARCHAR(max), Field3 NVARCHAR(max)); 
insert into @table1 values ('one-two-three') 
, ('four-five-six') 
, ('seven-eight-nine'); 

---------------------------------------- 
-- load parsed values into @table2, from @table1 
insert into @table2 
select p.* 
from @table1 t 
cross apply dbo.fnReturnThreeFields(t.Name,'-') p 

---------------------------------------- 
-- see the results 
select * from @table2; 
GO 

结果:

enter image description here

+0

将它们作为行返回,但用户希望它们插入到三个单独的列中。你也不应该声明'NCHAR'没有长度 - 是NCHAR(1)'还是'NCHAR(30)'?另外,用于分割字符串的while循环方法在进入值的高端时是一种性能问题 - 请参阅http://sqlblog.com/blogs/aaron_bertrand/archive/2010/07/07/splitting-a -list-of-integers-another-roundup.aspx – 2012-02-21 02:12:05

+0

@AaronBertrand Thx,我想我误读了列定义;更正的解决方案已发布。 – 2012-02-21 02:35:50

+0

这就是为什么没有长度的'NCHAR'是一个坏主意:http:// sqlblog。com/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-declaring-varchar-without-length.aspx – 2012-02-21 02:42:11

相关问题