2017-03-22 8 views
1

私は内部的な使用のためのプロシージャを作成しようとしています。ここではカンマで区切られたタグの文字列を追加できます。文字列分割は最初のエントリのみを返します

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE PROCEDURE AddService 
    @ServiceName AS VARCHAR(MAX), 
    @Location AS VARCHAR(MAX), 
    @Description AS VARCHAR(MAX), 
    @PermissionType AS INT, 
    @Tags AS VARCHAR(MAX) 
AS 
BEGIN 
    DECLARE @ServiceId AS INT 

    INSERT INTO Services(NAME,LOCATION,DESCRIPTION,PERMISSIONTYPE) VALUES(@ServiceName,@Location,@Description,@PermissionType) 
    SET @ServiceId = (SELECT SCOPE_IDENTITY()) 

    DECLARE @TagSplit TABLE(ID INT IDENTITY(1,1),DATA VARCHAR(MAX)) 
    INSERT @TagSplit VALUES(SUBSTRING(@Tags,0,CHARINDEX(',',@Tags))) 

    WHILE EXISTS(SELECT * FROM @TagSplit) 
    BEGIN 
     DECLARE @TempId AS INT 
     DECLARE @Tag AS VARCHAR(MAX) 

     SET @TempId = (SELECT TOP 1 ID FROM @TagSplit) 
     SET @Tag = (SELECT TOP 1 DATA FROM @TagSplit) 

     INSERT INTO Tags VALUES(@ServiceId,@Tag) 

     DELETE FROM @TagSplit WHERE ID = @TempId 
    END 
END 
GO 

しかし、私は私の「タグ」の表で見ると、@Tags文字列を与えられた「いくつかの、事は」のみ「一部には」追加ではなく、「もの」されま​​す。私は、SQLで適切な文字列分割を行う方法を誤解している可能性があります。

これは正しく動作しません一部です:

WHILE EXISTS(SELECT * FROM @TagSplit) 
BEGIN 
    DECLARE @TempId AS INT 
    DECLARE @Tag AS VARCHAR(MAX) 

    SET @TempId = (SELECT TOP 1 ID FROM @TagSplit) 
    SET @Tag = (SELECT TOP 1 DATA FROM @TagSplit) 

    INSERT INTO Tags VALUES(@ServiceId,@Tag) 

    DELETE FROM @TagSplit WHERE ID = @TempId 
END 

任意のヘルプ?ジェフMODENによって

+0

? –

+0

@Damien_The_Unbelieverこれは、データベースマネージャのプロシージャを右クリックして "実行"をクリックするだけで、これが使用される方法がより簡単だったと思っていました。 – OmniOwl

答えて

2

CSVスプリッタテーブル値関数を使用してみてください

create function [dbo].[delimitedsplit8K] (
     @pstring varchar(8000) 
    , @pdelimiter char(1) 
) 
returns table with schemabinding as 
return 
    with e1(N) as (
    select 1 union all select 1 union all select 1 union all 
    select 1 union all select 1 union all select 1 union all 
    select 1 union all select 1 union all select 1 union all select 1 
) 
    , e2(N) as (select 1 from e1 a, e1 b) 
    , e4(N) as (select 1 from e2 a, e2 b) 
    , ctetally(N) as (
    select top (isnull(datalength(@pstring),0)) 
     row_number() over (order by (select null)) from e4 
) 
    , ctestart(N1) as (
    select 1 union all 
    select t.N+1 from ctetally t where substring(@pstring,t.N,1) = @pdelimiter 
) 
    , ctelen(N1,L1) as (
    select s.N1, 
     isnull(nullif(charindex(@pdelimiter,@pstring,s.N1),0)-s.N1,8000) 
    from ctestart s 
) 
select itemnumber = row_number() over(order by l.N1) 
     , item  = substring(@pstring, l.N1, l.L1) 
    from ctelen l 
; 
go 

分割文字列は参照:

次に、あなたの手順はこのようになります。このようなテーブルやXMLなどの複数の値を、保持するのではなく、自分自身にコンマを含む文字列を与えるため*設計された*データ型を使用しないのはなぜ

CREATE PROCEDURE AddService 
    @ServiceName AS VARCHAR(MAX), 
    @Location AS VARCHAR(MAX), 
    @Description AS VARCHAR(MAX), 
    @PermissionType AS INT, 
    @Tags AS VARCHAR(MAX) 
AS 
BEGIN 
    set nocount, xact_abort on; 

    DECLARE @ServiceId AS INT; 

    INSERT INTO Services(NAME,LOCATION,DESCRIPTION,PERMISSIONTYPE) 
    VALUES(@ServiceName,@Location,@Description,@PermissionType) 

    SET @ServiceId = (SELECT SCOPE_IDENTITY()); 

    insert into tags 
    select @ServiceId, s.Item 
    from [dbo].[delimitedsplit8K](@Tags,',') s; 
end 
go 
+0

これは非常に複雑に思えます。私が見つけた解決策のほとんどから、これはほとんど複雑に見えませんでした。この機能が必要ですか? – OmniOwl

+1

@Vipar SQL Server 2016を使用している場合は、代わりに 'string_split()'を使用できます。さもなければ、これはCLR機能を使用しないで最もよい方法の1つです。 2016年以前の文字列分割のための他のオプションが必要な場合、私が参照する記事にはたくさんのものがあります。 – SqlZim

+0

私は最後に別の簡単な解決策をとってきましたが、私はあなたのものを正しいものにします。 – OmniOwl

関連する問題