Heute wurde ich um einen Tipp gebeten: Wie korrigiere ich einen Tippfehler in meinen Daten?
Eigentlich mit REPLACE() ganz einfach, wenn da nicht noch die Randbedingungen wären J. Einerseits läuft die DB noch immer auf einem SQL Server 2000 (wie so viele andere ja auch) und anderseits sind die Daten in einem Feld vom Typ text abgelegt. Und da haben wir auch schon den Schlamassel; REPLACE() lässt sich nicht auf Felder vom Typ text anwenden L. Glück gehabt: Es gibt eine Einschränkung in den Daten, welche die ganze Sache wieder vereinfacht: Das falsch geschriebene Wort kommt immer in den ersten 8000 Zeichen vor.
Die korrekte Fragestellung lautet also: Wie korrigiere ich einen Tippfehler in den ersten 8000 Zeichen meiner Daten vom Typ text? Und das ist ganz klar ein Fall für UPDATETEXT:
BEGIN TRAN
DECLARE @wrongWord varchar(50)
DECLARE @correctWord varchar(50)
SELECT @wrongWord = ‘generalinvoicerequest_410.xsd’, @correctWord = ‘generalInvoiceRequest.xsd’ –- use camel-case
DECLARE @ptrval binary(16)
DECLARE @offset int
DECLARE @length int
DECLARE myCursor CURSOR FAST_FORWARD READ_ONLY FOR
SELECT TEXTPTR(message_data), CHARINDEX(@wrongWord, SUBSTRING(message_data,1,8000)) - 1, LEN(@wrongWord)
FROM IO_XMLOutput
WHERE Identifier IN (SELECT f.hnnummer
FROM fall f
JOIN auftrag a ON a.id = f.auftrag_id AND a.nr IN (‘2007.00001′, ‘2007.00004′, ‘2007.00006′)
JOIN leistungserbringer le ON le.id = f.leistungserbringer_id AND le.nr = 999007
JOIN kostentraeger_patient kp ON kp.id = f.Kostentraeger_Patient_Id
JOIN kostentraeger kt ON kt.id = kp.Kostentraeger_Id
WHERE f.patienttiers = 2
AND kt.kassencode IN (11110, 11103))
OPEN myCURSOR
FETCH NEXT FROM myCursor INTO @ptrval, @offset, @length
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATETEXT IO_XMLOutput.message_data
@ptrval – textpointer
@offset – insert offset
@length – delete length
@correctWord – new value
FETCH NEXT FROM myCursor INTO @ptrval, @offset, @length
END
CLOSE myCursor
DEALLOCATE myCursor
COMMIT
Ganz schön kompliziert, oder? Sicher ein Grund mehr auf SQL Server 2005 zu migrieren. Denn neu gibt es ja den Datentyp varchar(max); und da funktioniert auch REPLACE() wieder. Mehr darüber findest du in meinem Blogbeitrag Wie lade ich Dokumente in die DB?




hallo urs
das problem liegt eigentlich nur bei „charindex“ dieser kann text und ntext nicht verabeiten. nimmt man dagegen „patindex“ funktioniert es auch mit text > 8000 zeichen.
gruss, giusi
—————————————————–
DECLARE @ptrval binary(16)
DECLARE @pos int
DEClARE @len INT
DELCARE @substring NVARCHAR
select
@len = LEN(‘text_to_be_replaced’),
@Ptrval = textptr(replace_textfield),
@pos = PATINDEX(‘%text_to_be_replaced%’, replace_textfield)-1
from
test_table
where
bla bla
–SELECT @ptrval, @pos, @len
UPDATETEXT test_table.replace_textfield @ptrval @pos @len ‘new_text’
Kommentar von gesharptes — 18. September 2007 @ 08:30
Hallo Giusi,
Danke für deinen Tipp; da hast du natürlich recht. CHARINDEX() war nicht gerade so ne leuchtende Idee von mir. Das eigentliche Problem liegt ja aber viel mehr in der Notwendigkeit, das Text Feld mit einem Loop und UPDATETEXT aktualisieren zu müssen. Mit varchar(max) entfällt der Loop und anstelle von UPDATETEXT kann ich REPLACE() benutzen. Das macht es wirklich einfach.
Gruss, Urs
Kommentar von Urs Gehrig — 18. September 2007 @ 13:13