EDIT: erlauben mehrere char Separatoren
Dies ist, wie ich es gelöst. Sie beinhaltet:
- A Tabellenwertfunktion (
xftSplit
) für spliting Zeilenumbrüche (char (10)) in den Tabellenzeilen
- A Skalarfunktion (
fSubstrNth
) für das n-ten Halbbild eines Zeile Extrahieren ein Separator
- Eine Skalarfunktion (
fPatIndexMulti
) zum Auffinden des n-ten Index des Separators
- (Optional) alternativer
Right
Funktion gegeben negative Werte
- schließlich einiger spezifischer Code zu akzeptieren, in Ihrer Lösung zu verwenden, da SQL tut das nicht llow dynamische Tabellenfunktionsdefinitionen (in anderen Worten, man kann nicht
SELECT
aus einer Funktion mit dynamischen Spalten)
Nun, für den Code-Schnipsel:
xftSplit
-- =============================================
-- Author: Bernardo A. Dal Corno
-- Create date: 15/07/2014
-- Description: Quebra valores a partir de caracteres e retorna lista em tabela
-- =============================================
CREATE FUNCTION [dbo].[xftSplit]
(
@Texto varchar(max),
@Splitter varchar(3)
)
RETURNS
@Lista TABLE
(
ValoresQuebrados varchar(8000)
)
AS
BEGIN
DECLARE @Pos Smallint
While len(@Texto)>0 BEGIN
SET @Pos = Patindex('%'[email protected]+'%',@Texto)
IF @Pos > 0 BEGIN
INSERT INTO @Lista
SELECT left(@Texto, @Pos-1)
SET @Texto = right(@Texto, len(@Texto)[email protected])
END
ELSE BEGIN
INSERT INTO @Lista
SELECT @Texto
SET @Texto = ''
END
End
RETURN
END
fSubstrNth
-- =============================================
-- Author: Bernardo A. Dal Corno
-- Create date: 18/07/2017
-- Description: substring com 2 PatIndex limitando inicio e fim
-- =============================================
CREATE FUNCTION fSubstrNth
(
@Text varchar(max),
@Sep varchar(3),
@N int --Nth campo
)
RETURNS varchar(max)
AS
BEGIN
DECLARE @Result varchar(max)
IF @N<1 RETURN ''
IF @N=1
SET @Result = substring(@Text, 1, dbo.fPatIndexMulti(@Sep,@Text,1)-1)
ELSE
SET @Result = substring(@Text, dbo.fPatIndexMulti(@Sep,@Text,@N-1)+LEN(@Sep), CASE WHEN dbo.fPatIndexMulti(@Sep,@Text,@N)>0 THEN dbo.fPatIndexMulti(@Sep,@Text,@N)-dbo.fPatIndexMulti(@Sep,@Text,@N-1)-LEN(@Sep) ELSE LEN(@Text)+1 END)
RETURN @Result
END
fPatIndexMulti
-- =============================================
-- Author: Bernardo A. Dal Corno
-- Create date: 17/07/2017
-- Description: recursive patIndex
-- =============================================
CREATE FUNCTION [dbo].[fPatIndexMulti]
(
@Find varchar(max),
@In varchar(max),
@N tinyint
)
RETURNS int
AS
BEGIN
DECLARE @lenFind int, @Result int, @Texto varchar(max), @index int
DECLARE @i tinyint=1
SET @lenFind = LEN(@Find)-1
SET @Result = 0
SET @Texto = @In
WHILE (@i <= @N) BEGIN
SET @index = patindex('%'[email protected]+'%',@Texto)
IF @index = 0 RETURN 0
SET @Result = @Result + @index
SET @Texto = dbo.xRight(@Texto, (@index + @lenFind)*-1)
SET @i = @i + 1
END
SET @Result = @Result + @lenFind*(@i-2)
RETURN @Result
END
xRechts
-- =============================================
-- Author: Bernardo A. Dal Corno
-- Create date: 06/01/2015
-- Description: Right inverso (para nros < 0)
-- =============================================
CREATE FUNCTION [dbo].[xRight]
(
@Texto varchar(8000),
@Qntd int
)
RETURNS varchar(8000)
AS
BEGIN
DECLARE @Result varchar(8000)
IF (Len(@Texto) = 0) OR (@Qntd = 0)
SET @Result = ''
ELSE IF (@Qntd > 0)
SET @Result = Right(@Texto, @Qntd)
ELSE IF (@Qntd < 0)
SET @Result = Right(@Texto, Len(@Texto) + @Qntd)
RETURN @Result
END
spezifischen Code
SELECT
acolumn = 'any value',
field1 = dbo.fSubstrNth(line,',',1),
field2 = dbo.fSubstrNth(line,',',2),
anothercolumn = 'set your query as you would normally do',
field3 = (CASE dbo.fSubstrNth(line,',',3) WHEN 'C' THEN 1 ELSE 0 END)
FROM (
SELECT line = ValoresQuebrados FROM dbo.xftSplit(@StringVariable, char(10))
) lines
Beachten Sie, dass:
fSubstrNth
empfängt die n-ten Feld von der Linie zu extrahieren
xftSplit
erhält eine Variable, die die Zeichenfolge, die Sie auf Masse möchten enthält (unabhängig von der Quelle) und eine char(10)
als Splitter von \n
, aber es könnte sein, alles andere
- Die Abfrage kann wie jede andere auch sein. Dies bedeutet, dass es in einer Prozedur, einer Tabellenfunktion, einer Ansicht usw. gespeichert werden kann.Sie können einige oder alle Felder in beliebiger Reihenfolge extrahieren und beliebig weiterverarbeiten
- Wenn Sie in einer gespeicherten Prozedur verwendet werden, können Sie eine generische Methode zum Erstellen einer Abfrage und einer temporären Tabelle erstellen, die die Zeichenfolge mit dynamischen Spalten lädt. Sie müssen jedoch eine andere Prozedur aufrufen, um die Daten zu verwenden ODER eine spezifische Abfrage wie oben in derselben Prozedur erstellen (was sie zu einer nicht generischen, einfach wiederverwendbaren Instanz macht)