Avatar billede decrypto Nybegynder
14. marts 2006 - 13:43 Der er 22 kommentarer og
1 løsning

Stored procedure: split af en streng

Jeg ved det kan lade sig gøre, jeg har nemlig gjort det før, men jeg kan bare ikke huske syntaksen.

Jeg kalder en st. proc med et sæt af argumenter. Det ene argument er en lang ';'-separeret streng.

Jeg ønsker at splitte denne streng på ';', og for hver element udføre en SQL Insert, hvori elementet indgår i min SQL.

Er der en der har et eksempel?
Avatar billede ij Nybegynder
14. marts 2006 - 14:12 #1
Yes se om det her er noget du kan bruge:
REATE PROCEDURE USPSplitPersonKeys
                    @list      ntext,
                    @delimiter char(1) = N',' AS

  DECLARE @pos      int,
          @textpos  int,
          @chunklen smallint,
          @tmpstr  nvarchar(4000),
          @leftover nvarchar(4000),
          @tmpval  int,
          @sql      nvarchar(4000)

  SET NOCOUNT ON
   
    SELECT @textpos = 1, @leftover = ''
    WHILE @textpos <= datalength(@list) / 2
    BEGIN
        SELECT @chunklen = 4000 - datalength(@leftover) / 2
        SELECT @tmpstr = @leftover + substring(@list, @textpos, @chunklen)
        SELECT @textpos = @textpos + @chunklen

        SELECT @pos = charindex(@delimiter, @tmpstr)

        WHILE @pos > 0
        BEGIN
            SELECT @tmpval = cast(left(@tmpstr, @pos - 1) as int)
            SELECT @tmpval = ltrim(rtrim(@tmpval))
            if (@tmpval <> 0)
                BEGIN
                INSERT #personkeys(PK) VALUES (@tmpval)
                END
            SELECT @tmpstr = substring(@tmpstr, @pos + 1, len(@tmpstr))
            SELECT @pos = charindex(@delimiter, @tmpstr)
        END

        SELECT @leftover = @tmpstr
    END
    if (@leftover <> 0)
        BEGIN
        INSERT #personkeys(PK) VALUES(cast(ltrim(rtrim(@leftover)) as int))
        END

GO
Avatar billede ij Nybegynder
14. marts 2006 - 14:15 #2
ja OK mangler lige et "C" i CREATE PROCEDURE, men den har du nok luret :-)
Avatar billede dj_uncas Nybegynder
14. marts 2006 - 14:16 #3
DECLARE @Position int

IF RIGHT( RTRIM( @InputString ), 1 ) <> ';'
    SET @InputString = @InputString + ';'

SET @Position = PATINDEX( '%;%', @InputString )
WHILE @Postition <> 0
BEGIN
    'Your stuff
END


Her kører en løkke en gang for hver element der er i input strengen, splittet med ;
Avatar billede dj_uncas Nybegynder
14. marts 2006 - 14:16 #4
øv, der var du hurtigere...
Avatar billede decrypto Nybegynder
14. marts 2006 - 14:28 #5
Ok, -> dj_uncas dit ekempel ser meget kort ud.

Hvis min streng fx. hedder
@stringOfID (indeholder: "1;2;3;445;45;")

Hvordan ser loopet ud, hvori der fx står:
INSERT INTO aTABLE(FK_IDNR) VALUES(???) <- herinde skal min ID'er indgå pr loop

Hvordan ser det så ud?
Avatar billede decrypto Nybegynder
14. marts 2006 - 14:39 #6
-> dj_uncas, hvor laver du denne?

IF RIGHT( RTRIM( @brandIDs ), 1 ) <> ';'
Avatar billede decrypto Nybegynder
14. marts 2006 - 14:45 #7
istedet for hvor, skal der stå hvofor.
Avatar billede dj_uncas Nybegynder
14. marts 2006 - 15:10 #8
Den første linje tjekke om der er ; i slutningen af @InputString, da while-løkken er bundet op på antallet af ;'er i den..

Inde i løkken skal du have dette:

SET @ID = LEFT( @InputString, @Position - 1 )
INSERT INTO aTABLE(FK_IDNR) VALUES(@ID)

SET @InputString = STUFF( @InputString, 1, @Position )
SET @Position = PATINDEX( '%;%', @InputString )
Avatar billede decrypto Nybegynder
14. marts 2006 - 15:25 #9
stuff funktionen kræver 4 argumenter, hvad er den fjerde?
Avatar billede decrypto Nybegynder
14. marts 2006 - 15:28 #10
Der er altid et ';' til sidst, så den linje har jeg fjernet.

Jeg tror at jeg er tæt på, men stuff funktionen kræver 4 argumenter.

Min kode ser således ud:

SET @brandIDs = @brandIDs + ';'
SET @position = PATINDEX( '%;%', @brandIDs )

WHILE @position <> 0
    BEGIN
        SET @brandID = LEFT( @brandIDs, @position - 1 )
        INSERT INTO BrandInitiative(FK_BrandID, FK_InitiativeID) VALUES(@brandID,@newID)
        SET @brandIDs = STUFF( @brandIDs, 1, @Position )
        SET @Position = PATINDEX( '%;%', @brandIDs )
    END
-------
Jeg tror, der er noget galt....
Avatar billede decrypto Nybegynder
14. marts 2006 - 15:42 #11
Der er desværre gået kage i eksemplet.

Kan du skrive eksemplet igen bare med:
@brandIDs (indeholder: "1;2;3;445;45;")

SET @position = PATINDEX( '%;%', @brandIDs )

WHILE @position <> 0
    BEGIN
        SET @brandID = LEFT( @brandIDs, @position - 1 )
        INSERT INTO Brand(BrandID) VALUES(@brandID)
       
    SET @brandIDs = STUFF( @brandIDs, 1, @Position )
        SET @Position = PATINDEX( '%;%', @brandIDs )
    END

Det her virker ikke! Hvad mangler jeg????
Avatar billede decrypto Nybegynder
14. marts 2006 - 15:42 #12
STUFF problemet er der stadigvæk.
Avatar billede dj_uncas Nybegynder
14. marts 2006 - 15:44 #13
Yes, den sidste parameter er "character_expression", den kan du bare sætte til "" (tom streng).

Se evt. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_tsqlcon_6lyk.asp
Avatar billede decrypto Nybegynder
14. marts 2006 - 15:50 #14
Men der er jo noget galt, jeg ved jo ikke hvor lange mine ID'er er. Det der mangler i STUFF er længden af det jeg vil stuffe, men den kender jeg jo ikke.
Avatar billede decrypto Nybegynder
14. marts 2006 - 15:50 #15
Hmm, ok den kan være tom prøver lige...
Avatar billede decrypto Nybegynder
14. marts 2006 - 15:55 #16
Den laver et endless loop....
Avatar billede dj_uncas Nybegynder
14. marts 2006 - 16:01 #17
Hmmm.. brb..

Det ved jeg ikke rigtig..

Det her:
----------------------------------------
SET @position = PATINDEX( '%;%', @brandIDs )

WHILE @position <> 0
    BEGIN
        SET @brandID = LEFT( @brandIDs, @position - 1 )
        --INSERT INTO Brand(BrandID) VALUES(@brandID)
        PRINT @brandID
     
    SET @brandIDs = STUFF( @brandIDs, 1, @Position, '' )
        SET @Position = PATINDEX( '%;%', @brandIDs )
    END
----------------------------------------

virker fint hos mig
Avatar billede dj_uncas Nybegynder
14. marts 2006 - 16:02 #18
bare fjern kommentar fra INSERT (--) og fjern PRINT linjen, så skulle den være god. Ellers er jeg nødt til at se hele din kode.
Avatar billede decrypto Nybegynder
14. marts 2006 - 16:09 #19
Det virker også hos mig nu....Det er min transaktions styring, der er noget galt i. Kan du se, hvad der er galt?

BEGIN TRANSACTION

    INSERT INTO dbo.Initiative(FK_ProductGroupID, FK_CountryID, [Name], CommercialName)     VALUES(@productGroupID, @countryID, @productName, @commercialName)
        IF (@@ERROR <> 0) GOTO onError
   
    SELECT @newID = @@IDENTITY
        IF (@@ERROR <> 0) GOTO onError

        SET @position = PATINDEX( '%;%', @brandIDs )

        WHILE @position <> 0
                BEGIN
                    SET @brandID = LEFT( @brandIDs, @position - 1 )
                    INSERT INTO Brand(BrandID) VALUES(@brandID)
                    IF (@@ERROR <> 0) GOTO onError
 
                SET @brandIDs = STUFF( @brandIDs, 1, @Position, '' )
                SET @Position = PATINDEX( '%;%', @brandIDs )
            END
COMMIT TRANSACTION
RETURN(0)

onError:
ROLLBACK TRANSACTION
RETURN(1)
Avatar billede dj_uncas Nybegynder
14. marts 2006 - 16:32 #20
Tja, du når ned til din onError lige meget hvad der ellers sker i resten af sql'en...
Avatar billede decrypto Nybegynder
14. marts 2006 - 20:28 #21
Okay, men så skal der jo ændringer i min transaktionelle stored proc. Men i eksemplet i en bog, stod det ellers på denne måde.
Avatar billede decrypto Nybegynder
15. marts 2006 - 08:11 #22
dj_juncas smid et svar ind, så du kan få points
Avatar billede dj_uncas Nybegynder
15. marts 2006 - 10:06 #23
ok, det kommer her.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester