2012-02-21 19 views
-1

私はスプールというテーブルを持っていて、 "NAME"という名前のフィールドがあります。このフィールドには、7つの値がダッシュで区切られた文字列があります。別のフィールドに基づいてテーブルのフィールドを塗りつぶすスクリプト

"NAME"という文字列をダッシュ​​で分割し、7つの異なる列にある7つの値をすべて記録するスクリプトをSQL Serverで実行する必要があります。例えば

NAME:column1ので ABCD-0123-ASDはcolumn2の中で、ABCD記録しなければならない:0123とCOLUMN3 ASD ...など私は私が説明した期待し =)

感謝を!

私は実際の問題で私の文字列「名前」に7つのセグメントがあり、そのフィールドのすべてのセグメントを7つの列に入れなければなりません。

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 

どうやらそれが正常に動作します:あなたは


HIジョン・デューイを助けるためにも

私は)=ウィッヒそのスクリプトを適用 おかげで、テーブル内のレコードの数nを持っている私は、この作りますしかし、同じテーブル内で更新を行いたい場合、関数を呼び出す方法、またはストアプロシージャでなければならない場合はどうすればよいですか? ご協力いただきありがとうございます!

+0

また、あなたが使用しているSQL Serverのバージョンを指定してください。 –

+0

私はSQL 2008を使用しています – user1222295

答えて

0

これは厳密にCTEを必要としませんが、SUBSTRING/CHARINDEX /などの数を保持します。計算を最小限に抑えます。

;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; 

これは、すべての値に2つのダッシュがあることを前提としています。それが保証できない場合(例えば制約付きで実施されていない場合)は、上記にwhere句を入れるか、0,1、または> 2のダッシュがある場合に何をしたいかを定義する必要があります。 where句は次のようになります。

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

これは2つのダッシュでうまく動作しますが、ダッシュが増えたらどうなりますか?私は最大6つのダッシュを持って、私は同じテーブルに7列を持って、フィールド名にセグメントがある場合、この列を埋める必要があります。また、すべての列に塗りつぶすことができない可能性もあります ありがとうございました! =) – user1222295

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

これは行として返しますが、3つの別々の列に挿入する必要があります。また、長さを持たない 'NCHAR'を宣言すべきではありません - ' NCHAR(1) 'または' NCHAR(30) 'ですか?さて、文字列を分割するためのwhileループメソッドは、値の高いほうに入るほどパフォーマンスが向上します。http://sqlblog.com/blogs/aaron_bertrand/archive/2010/07/07/splitting-aを参照してください。 -list-of-integers-another-roundup.aspx –

+0

@AaronBertrand Thx、私は列の定義を誤解していると思います。修正されたソリューションが転記されます。 –

+0

これは、長さを持たない 'NCHAR'が悪い考えである理由です:http:// sqlblog。com/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-declaring-varchar-without-length.aspx –

関連する問題