Ein anderes interessantes Phänomen lief mir gerade über den Weg: Liest man aus einem SQL Server eine richtig lange Zeichenkette (z.B. mehr als 2000 Zeichen, z.B. mit einer ‘FOR XML …’ Transformation im Select) wird einem das Ergebnis willkürlich bei um die 1000 Zeichen abgeschitten.
Eine generelle Workaroundfunktion ist schnell gebastelt:
Private Shared Function GetLongStringData(ByVal statement As String) As String
Dim sql As New System.Data.SqlClient.SqlCommand()
Dim con As New System.Data.SqlClient.SqlConnection()
con.ConnectionString = "connectionstring"
sql.CommandText = statement
sql.Connection = con
con.Open()
Dim r As System.Data.SqlClient.SqlDataReader = sql.ExecuteReader()
Dim strbuilder As New StringBuilder()
While r.Read()
strbuilder.Append(r(0))
End While
con.Close()
Return strbuilder.ToString()
End Function
Stellt sich allerdings nach wie vor die Frage warum die Daten abgeschnitten werden. Im SQL Server Management Studio wird alles korrekt angezeigt. Ich vermute das Problem liegt irgendwo bei der Übergabe vom SQL Server in den .Net String. Wenn jemand eine Idee hat, möge er sich bei mir melden. :)
Wer mal folgendes versucht:
select
(case
when bedingung1 then
(case
when bedingung2 then statement2
when bedingung3 then statement3
when bedingung4 then statement4
when bedingung5 then statement5
when bedingung6 then statement6
when bedingung7 then statement7
when bedingung8 then statement8
when bedingung9 then statement9
when bedingung10 then statement10
when bedingung11 then statement11
else statement12
end)
else statement1
end)
from linked_server.database.schema.table
wird feststellen, das einem der SQL Server eine Fehlermeldung bringt:
Meldung 8180, Ebene 16, Status 1, Zeile 1
Statement(s) could not be prepared.
Meldung 125, Ebene 15, Status 4, Zeile 1
Case expressions may only be nested to level 10.
Leider findet man hierzu nichts in der MSDN und auch sonst im Web wurde ich nicht fündig um diesen Fehler zu beheben. Wobei die Ursache relativ simpel ist, und die Fehlermeldung einen schon drauf hinweist: Case Statements dürfen über eine Linked-Server Verbindung nur bis maximal 10 Schachtelungen haben.
So einen Hinweis hätte ich eigentlich in der MSDN erwartet!
Das kann man auch nicht durch irgendwelche Einstellungen am Linked Server ändern. Da hilft nur eine Behelfsview in der Quelldatenbank. Dann kann man auch fröhlich und mit einer Erfahrung mehr die Datenmigration fortsetzen.
Kann man immer wieder mal brauchen: Eine Split-Funktion für MSSQL (ab 2000).
CREATE FUNCTION [dbo].[udf_ItemExtract]
(
@Position INTEGER,
@List VARCHAR(2000), --VARCHAR(MAX)
@Delimiter VARCHAR(1)
)
RETURNS VARCHAR(2000) --VARCHAR(MAX)
AS
BEGIN
DECLARE @RetVal VARCHAR(2000) SET @RetVal = '' --VARCHAR(MAX)
DECLARE @Counter INT SET @Counter = 0
DECLARE @StartPos INT
DECLARE @Length INT
DECLARE @DelimPos INT SET @DelimPos = 0
-- SCAN THROUGH UNTIL WE FIND THE ITEM AT THE POSITION OF THE INDEX - WE'LL GO THROUGH WHILE LOOP AT LEAST ONCE
WHILE @Counter < @Position
BEGIN
SET @Counter = @Counter + 1 -- increment counter
SET @StartPos = @DelimPos + 1 -- move the start position to right after previously found delimiter (or 1st char if this is the fist time through
SET @DelimPos = CHARINDEX(@Delimiter,@List,@DelimPos + 1) --find the next delimiter
-- IF THERE ARE NO DELIMITERS LEFT...
IF @DelimPos = 0
BEGIN
-- IF WE'RE ON THE POSITION WE'RE LOOKING FOR, THEN SET LENGTH TO THE REST OF THE STRING
IF @Counter = @Position SET @Length = (LEN(@List)+1)-@StartPos
-- OTHERWISE SET LENGTH TO -1 AND THAT WILL BE AN INDICATOR TO RETURN EMPTY STRING
ELSE SET @Length = -1
END
ELSE SET @Length = @DelimPos - @StartPos -- otherwise length is now from new start pos right up to delimiter
END
-- RETURN THE EXTRACTED STRING
IF @Length > 0 SET @RetVal = SUBSTRING(@List,@StartPos,@Length)
RETURN @RetVal
END