yoo!
har denna utmärkta function, den splittar en sträng och lägger värdena i en tmp tabell som man sedan kan joina med.
men, det händer då och då att jag behöver splitta en sträng som är längre än 8000 tecken och då räcker denna inte längre till.
skulle man kunna byta till datatypen text i funktionen på nått vis? eller finns det nått annat sätt att splitta på?
ALTER FUNCTION ufSplit(@sText varchar(8000), @sDelim varchar(20) = ' ')
RETURNS @retArray TABLE (idx smallint Primary Key, value varchar(8000))
AS
BEGIN
DECLARE @idx smallint,
@value varchar(8000),
@bcontinue bit,
@iStrike smallint,
@iDelimlength tinyint
IF @sDelim = 'Space'
BEGIN
SET @sDelim = ' '
END
SET @idx = 0
SET @sText = LTrim(RTrim(@sText))
SET @iDelimlength = DATALENGTH(@sDelim)
SET @bcontinue = 1
IF NOT ((@iDelimlength = 0) or (@sDelim = 'Empty'))
BEGIN
WHILE @bcontinue = 1
BEGIN
--If you can find the delimiter in the text, retrieve the first element and
--insert it with its index into the return table.
IF CHARINDEX(@sDelim, @sText)>0
BEGIN
SET @value = SUBSTRING(@sText,1, CHARINDEX(@sDelim,@sText)-1)
BEGIN
INSERT @retArray (idx, value)
VALUES (@idx, @value)
END
--Trim the element and its delimiter from the front of the string.
--Increment the index and loop.
SET @iStrike = DATALENGTH(@value) + @iDelimlength
SET @idx = @idx + 1
SET @sText = LTrim(Right(@sText,DATALENGTH(@sText) - @iStrike))
END
ELSE
BEGIN
--If you can’t find the delimiter in the text, @sText is the last value in
--@retArray.
SET @value = @sText
BEGIN
INSERT @retArray (idx, value)
VALUES (@idx, @value)
END
--Exit the WHILE loop.
SET @bcontinue = 0
END
END
END
ELSE
BEGIN
WHILE @bcontinue=1
BEGIN
--If the delimiter is an empty string, check for remaining text
--instead of a delimiter. Insert the first character into the
--retArray table. Trim the character from the front of the string.
--Increment the index and loop.
IF DATALENGTH(@sText)>1
BEGIN
SET @value = SUBSTRING(@sText,1,1)
BEGIN
INSERT @retArray (idx, value)
VALUES (@idx, @value)
END
SET @idx = @idx+1
SET @sText = SUBSTRING(@sText,2,DATALENGTH(@sText)-1)
END
ELSE
BEGIN
--One character remains.
--Insert the character, and exit the WHILE loop.
INSERT @retArray (idx, value)
VALUES (@idx, @sText)
SET @bcontinue = 0
END
END
END
RETURN
END
LarsGMedlem sedan dec. 200012 464 inlägg Du kan inte ha parametrar av typen text så det går inte. Varifrån kommer dessa strängar? Borde du inte ha dessa värden i en tabell istället?
Strängarna kommer oftast ifrån en asp-sida.
Ex.
På en sida listar jag en massa poster och efter varje post finns en checkbox där man markerar posten.
Man markerar ett par stycken poster och klickar på raderaknapp, alla posters id:n skickas in som en sträng i en SP som splittar den och raderar posterna.
ALTER PROCEDURE upNewsDelete
@IDno varchar(8000)
AS
BEGIN
SET NOCOUNT ON
DELETE News
WHERE IDno IN (SELECT value FROM ufSplit(@IDno, ','))
SELECT @@rowcount
END
Visst, man skulle kunna loopa på aspsidan istället och skicka in en post åt gången men, nja.
Problemet uppstår alltså då man markerar för många poster så strängen blir för lång (har man höga id-nummer så behövs det inte så många poster innan man kommer upp i 8000 tecken)
LarsGMedlem sedan dec. 200012 464 inlägg Men om du har en 4-bytes integer som nyckel så räcker det med 12 byte i text-format och då får du ändå plats med mer än 600 värden.
Visst, man skulle kunna loopa på aspsidan istället och skicka in en post åt gången men, nja.
Varför bara en post åt gången?
Varför bara en post åt gången?
Jag förstår inte riktigt vad du menar här. :q
Hur kan man annars radera flera poster åt gången?
Alltså om checkboxarna har ett id:nr som value så kan jag ju loopa igenom alla boxar och köra en delete i varje loop.
Ovan var ett exempel, här är ett till:
På en asp-sida skickar man nyhetsbrev.
Man skriver ett ämne samt en bodytext och i en textarea fyller man i alla mottagaradresser man ska skcka till (kommaseparerade).
Infon skickas sedan in i databasen som tre strängar, ämne, body och mottagare.
Databasen splittar sedan upp alla mottagare och gör en insert för varje in i en kö-tabell som hanterar alla mailutskick.
Och låt oss säga att en epostadress är 15 tecken lång plus ett kommatecken mellan varje så kan man alltså bara skicka in 500 adresser, vilket kanske inte räcker så långt alla ggr.
Det finns ju flera sätt att lösa detta på, man kan t.ex köra en len() på asp-sidan och skicka en varning att man fyllt i för många adresser osv. men jag skulle gärna vilja lösa det hela i sql-servern om det går!
Du kan inte ha parametrar av typen text så det går inte.
Hmm, jag har bestämt för mig att jag använt text som parameter i SP:s, men du kanske bara menar i UDF:s, eller?
Skulle man inte kunna skicka in mottagarna som typen text i SP:n och där dela upp den i flera varchars på nått vis? Eller är text helt omöjligt att formatera/konvertera?
Puhh, många frågor och funderingar blev det! :)
LarsGMedlem sedan dec. 200012 464 inlägg Du skrev att du skulle kunna göra en loop i ASP och skicka in en post åt gången och då tänkte jag mig att du menade
' start transaction
for each f in formname
sql = "delete from t where id = " & f.value
connect.execute sql,,128
next
'commit transaction
och då menade jag bara att du skulle kunna samla ihop så många id som du får plats med innan du gör execute.
' start transaction
l = 0
c = 0
sql = ""
for each f in formname
if l + len(f.value) > 7998 then
connect.execute sql & ")",,128
l = 0
end if
if l = 0 then
sql = "delete from t where id in ( "
c = 0
end if
if c > 0 then sql = sql & ","
sql = sql & f.value
l = len(sql)
c = c + 1
next
if c > 0 then connect.execute sql & ")",,128
'commit transaction
Jag menade variabel när jag skrev det där om parametrar och textdatatyp. Det finns dock begränsningar som att det inte går att använda len på en variabel av typen text. Visst, det går att ha flera 8000 tecken parametrar men det känns lite oflexibelt.
Men det verkar i alla fall konstigt att någon skulle sitta och kryssa för flera hundra checkboxar i ett formulär. Kan du inte kategorisera saker lite?
Kan du inte kategorisera saker lite?
Mjao, det kan jag kanske göra i de flesta fall.
Det vore bara så enkelt att bara tjoffa in en lång skön sträng i databasen och sedan sköta uppdelningen där.
Om inte annat så får man fruktat snabbladdade sidor med bara ett databasanrop.
Men:
Eftersom DU inte verkar ha gjort en liknande hantering av strängar så måste väl det betyda att jag är fel ute! ;)
Får ta och fundera lite, får se om man kommer på nån bra lösning! :)
Hmm, denna artikel var lite för avancerad för mig men visst verkar detta vara vad jag söker?! Eller?
Man skickar in en sträng (i deras fall i formatet ntext) som sedan splittas upp och skickas tillbaka som en tabell.
http://www.sommarskog.se/arrays-in-sql.html#iterative
LarsGMedlem sedan dec. 200012 464 inlägg Ja, man skall använda datalength ja. Jo det verkar vara kuckelimaffens,precis vad du vill ha. Men som sagt så är det inte något som jag skulle använda.
Jag har nog mest spridit förvirring i denna tråd :)
Jag gjorde ett litet snabbt test på en enkel select och den verka hämta så som jag vill. :)
Men som sagt så är det inte något som jag skulle använda.
Då blir man ju genast orolig!
Varför vill du inte använda en sådan funktion?
Har du någon bättre lösning på stränghantering? Eller undviker du helt enkelt långa strängar! :q