Выполнение операций в текстовом файле с использованием T- SQL - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть текстовый файл, в котором нужно выполнить операцию, так как файл вообще имеет заголовки, если есть заголовки, то он переходит к следующему, если нет, то операции должны быть остановлены. Второй шаг - найти правильный разделитель, то есть канал, если файл имеет правильный разделитель, тогда он должен пройти и перейти к следующему шагу, в противном случае произойдет сбой. Если все вышеперечисленные шаги выполнены успешно, их следует экспортировать в основную таблицу.

Структура файла:

A|B|C|D|E - column
00|1|1|1|1- data
.

. И так далее.

create table #testdata (
textvalue varchar(max)
)


bulk insert #testdata
from 'D:\test.txt'
--with 
--(
--FIELDTERMINATOR = '|'
--)

select  *,rowid = row_number() over(order by textvalue desc) 
into    #test1
from    #testdata


--if exists (select 1 from #test1 where #test1.textvalue = @header and #test1.rowid = 1)
--begin
goto nextstep
--end
else
goto exitprocedure

Вывод должен быть таким: -

select FileType = 'Test',
       ReviewType = 'Correct delimiter is expected',
       PassFail = 'Success or Fail'

в зависимости от вышеприведенной проверки, в зависимости от того, что не получилось, должен отображаться вывод, как указано выше в трех полях.

Так как это нужно выполнить в T- SQL.

1 Ответ

0 голосов
/ 25 февраля 2020

Как вам уже сказали, T- SQL не является подходящим инструментом для этого ...

Способности манипуляции со строками довольно слабые, но вы можете попробовать один из следующих маршрутов:

Я начинаю симулировать с переменной, содержащей содержимое вашего текстового файла.

DECLARE @YourFile VARCHAR(MAX)=
'A|B|C|D|E
01|1|1|1|1
02|2|2|2|2';

- объявлять переменные для разрыва строки и разделителя

DECLARE @YourLineBreak VARCHAR(2)=CHAR(13)+CHAR(10); --might differ...
DECLARE @YourDelimiter VARCHAR(1)='|';

- Этот запрос будет преобразовать ваш файл в XML

DECLARE @YourInput XML=
CAST(CONCAT('<line><val>'
    ,REPLACE(REPLACE(@YourFile,@YourDelimiter,'</val><val>'),@YourLineBreak,'</val></line><line><val>')
    ,'</val></line>') AS XML);

SELECT @YourInput;

- этот запрос вернет имена столбцов

SELECT A.cols.value('text()[1]','varchar(max)') AS ColumnName
FROM @YourInput.nodes('/line[1]/*') A(cols) ;

- этот запрос вернет каждую строку данных в виде одной строки

WITH CountRows(LineIndex) AS(SELECT TOP((SELECT @YourInput.value('count(/line)','int')-1)) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
SELECT LineIndex
      ,@YourInput.query('/line[sql:column("LineIndex")+1]') AS LineValues
FROM CountRows;

- В этом запросе я сначала вводит последовательность чисел, которую можно использовать в XQuery позже

WITH InjectSequence(Combined) AS
(
    SELECT (SELECT TOP((SELECT @YourInput.value('count(/line[1]/val)','int'))) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values FOR XML PATH('Nmbr'),TYPE)
          ,@YourInput
    FOR XML PATH(''),TYPE
)
SELECT Combined.query
('
    let $cols := /line[1]/val
    for $ln in /line[position()>1]
    return
    <line>
    {
        for $nr in /Nmbr/text() 
        let $n := xs:int($nr)
        return
        <val name="{$cols[$n]}" value="{$ln/val[$n]}" />
    }
    </line>
')
FROM InjectSequence;

Какой бы подход вы ни выбрали, вам придется если вы выполняете ручную работу, очень много.

Конечный запрос должен быть либо динамически создан, либо вы можете остаться в универсальных c контейнерах, таких как XML или JSON.

С SQL -Server 2016 есть JSON

С v2016 + вы можете попробовать JSON маршрут тоже:

SELECT B.*
FROM OPENJSON(CONCAT('[',STUFF(CONCAT(',[["',REPLACE(REPLACE(@YourFile,@YourDelimiter,'","'),@YourLineBreak,'"],["'),'"]]'),1,1,''),']')) A
CROSS APPLY OPENJSON(A.[value])
WITH(col1 VARCHAR(MAX) '$[0]'
    ,col2 VARCHAR(MAX) '$[1]'
    ,col3 VARCHAR(MAX) '$[2]'
    ,col4 VARCHAR(MAX) '$[3]'
    ,col5 VARCHAR(MAX) '$[4]') B --add as many as you need

Удачи!

...