По вашим словам (и следующим комментариям) я не могу сказать, находится ли проблема на уровне SQL или вне его при создании текстового файла.В любом случае, вы можете решить эту проблему, используя NGrams8K (ссылка также включает версию VARCHAR (MAX), которая медленнее, чем версия 8K, но все еще противна).
Я частоавтоматизировать процесс ручного обновления сценариев сборки, импортируя их через OPENROWSET (или что-либо еще), изменяя текст, а затем записывая результаты в новый файл, заменяя старый (используя BCP).Ниже приведен код, который поможет вам понять, как я могу использовать функцию NGrams для решения этой проблемы.
Анализ:
DECLARE @someString VARCHAR(8000) =
'blah blah blah.... ;
blah blah .... ;
blah blah blah.... ;
...;';
SELECT
ng.position,
ng.token,
charValue = ASCII(ng.Token),
binaryValue = CAST(ng.token AS VARBINARY(2))
FROM samd.NGrams8K(@someString,1) AS ng;
Возвраты (для краткости сокращены):
position token charValue binaryValue
-------------------- --------- ----------- -----------
1 b 98 0x62
2 l 108 0x6C
3 a 97 0x61
4 h 104 0x68
5 32 0x20
6 b 98 0x62
...
...
68 . 46 0x2E
69 . 46 0x2E
70 . 46 0x2E
71 32 0x20
72 ; 59 0x3B
73 13 0x0D
74 10 0x0A
75 32 0x20
76 32 0x20
....
Строки уведомлений 73 и 74?Это два символа, которые вы хотите удалить: CHAR (13) и CHAR (10) AKA 0D и 0A .Вы хотите удалить их.
Используя NGrams или NGrams8k, вы можете получить позицию последнего LF + CR, найдя последний символ (13).
DECLARE @someString VARCHAR(8000) =
'blah blah blah.... ;
blah blah .... ;
blah blah blah.... ;
...;';
SELECT MAX(ng.position)
FROM samd.NGrams8K(@someString,1) AS ng
WHERE ASCII(ng.Token) = 13;
Возвращает: 73
Обратите внимание, что я использую переменную (@someString) для демонстрации, если GUI добавляет финальный LF / CR, товам придется импортировать этот файл и назначить содержимое переменной.
DECLARE @someString VARCHAR(8000) =
'blah blah blah.... ;
blah blah .... ;
blah blah blah.... ;
...;';
-- Use STUFF to remove the last CHAR(13)+CHAR(10)
DECLARE @newString VARCHAR(8000) =
STUFF(
@someString,
(
SELECT MAX(ng.position)
FROM samd.Ngrams8K(@someString,1) AS ng
WHERE ASCII(ng.Token) = 13
),2,'');
Этот код ^^^^ удаляет окончательный LF / CR.
ОБНОВЛЕНИЕ:
Я только что видел ответ Дэвида;если это так, вы можете использовать мое решение, чтобы извлечь файл, изменить его содержимое и написать новый файл.Ниже приведен пример того, как я это делаю (не идеально, но это работает).
CREATE PROC dbo.FileTransform_clean
@sourceFile NVARCHAR(500),
@destFile NVARCHAR(500),
@badText NVARCHAR(1000),
@cleanup BIT = 1
AS
BEGIN
-- 0. Prep
BEGIN
SET NOCOUNT ON;
SET @sourceFile = TRIM(@sourceFile);
DECLARE @pos SMALLINT = CHARINDEX('\',REVERSE(@sourceFile));
DECLARE @path NVARCHAR(4000) = SUBSTRING(@sourceFile,1,LEN(@sourceFile)-@pos),
@file NVARCHAR(4000) = SUBSTRING(@sourceFile,LEN(@sourceFile)-@pos+2,4000);
DECLARE @t TABLE (subdirectory NVARCHAR(4000), depth TINYINT, [file] BIT);
INSERT @t(subdirectory, depth, [file])
EXEC [master].dbo.xp_DirTree @path,1,1;
IF NOT EXISTS (SELECT 1 FROM @t AS t WHERE t.subdirectory = @file)
BEGIN
DECLARE @error VARCHAR(100) =
'The source file, '+ISNULL(@sourceFile,'NULL')+' was not found.';
PRINT @error;
GOTO error
END
IF OBJECT_ID('tempdb..##import','U') IS NOT NULL DROP TABLE ##import;
CREATE TABLE ##import(Document VARCHAR(MAX));
END
-- 1. File Import
BEGIN
PRINT 'Performing file import...';
DECLARE @SQL NVARCHAR(4000) = 'INSERT INTO ##import(Document)
SELECT * FROM OPENROWSET (BULK N'''+@sourceFile+''', SINGLE_BLOB) AS Document;';
EXEC (@SQL);
END
-- 2. Transformation
BEGIN
PRINT 'Performing file transform...';
DECLARE @query NVARCHAR(4000) =
N'SELECT STRING_AGG(s.item,CHAR(10)) WITHIN GROUP (ORDER BY s.ItemNumber)
FROM SQLToolbox_Misc.samd.delimitedSplitAB((SELECT i.Document FROM ##import AS i),CHAR(10)) AS s
WHERE NOT EXISTS (SELECT 1 FROM STRING_SPLIT('''+@badText+''','','') AS ss
WHERE CHARINDEX(ss.[value],s.item)>0);'
SET @SQL = 'bcp '+'"'+@query+'" '+'queryout "'+@destFile+'" -c -T -S '+@@SERVERNAME;
SET @SQL = REPLACE(@sql,CHAR(13)+CHAR(10),'');
DECLARE @SQLText VARCHAR(8000) = ' Executing:'+CHAR(10)+' '+@SQL;
PRINT @SQLText;
EXEC [master]..xp_cmdshell @SQL;
IF @cleanup = 1 DROP TABLE ##import;
END
error:
END
Этот код делает что-то совершенно другое, но вы можете принять к сведению, как я: 1. Вытащить файл с помощью OPENROWSET 2. Сделать что-то с содержимым (в моем коде я удаляю любой "Плохо"Текст "определяется @badText 3. Напишите новый файл, используя BCP
Надеюсь, это поможет.