我有一个在SSMS中运行的SQL查询的结果数据集,其中包括一个以.txt格式导出并保存到记事本的单行尾部记录。但是,尾部记录会自动包括十六进制控制,以便在作为尾部记录的连接字段(750个字符)之后包含换行符/回车符记录。在导出为.txt格式之前,如何从尾部记录的末尾消除此错误?文件不能包含任何空行。
对于我的尾部记录,我在SELECT语句中尝试了以下代码,这似乎是解决这种情况的常见方法:
REPLACE(REPLACE('T'+CAST(RIGHT(REPLACE(STR(COUNT(*)),' ','0'),9) AS VARCHAR)+SPACE(740),CHAR(10),''),CHAR(13),'')但是,在以.txt格式导出时,它仍然包含换行符和回车符。
REPLACE(REPLACE('T'+CAST(RIGHT(REPLACE(STR(COUNT(*)),' ','0'),9) AS VARCHAR)+SPACE(740),CHAR(10),''),CHAR(13),'')预期的结果是文件不包含导出文档的包含十六进制视图中显示的0D和0A字节字符。

发布于 2019-06-07 06:47:15
当您选择“另存结果为”并选择文本文件时,结果是一个制表符分隔的文本文件。每个字段用制表符分隔,每个记录由CR/LF终止。没有办法通过更改查询来改变这一点。

生成的文本文件如下:

该文件以字节顺序标记EF BB BF开头,表示它是UTF-8格式。78、79和7A是“x”、“y”和“z”。它们由制表符(09)分隔,记录以CR/LF (OD/OA)终止。然后对第二个记录执行相同的操作,也由CR/LF终止。
另一方面,您可以选择Copy,运行NotePad,然后粘贴文本。您将在记录之间获得CR/LFs,但在结束时没有。

发布于 2019-06-07 07:01:17
在创建文本文件时,我不能从您所说的(以及下面的评论)看出问题是在SQL级别还是在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,您可以通过定位最后一个字符(13)来获得最后一个LF+CR的位置。
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。
更新:
我刚刚看到了david的响应;如果是这样的话,您可以使用我的解决方案来拉入文件,更改内容并编写一个新文件。下面是我如何做到这一点的一个例子(不是完美的,但它是有效的)。
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编写一个新文件
希望这能有所帮助。
发布于 2019-06-07 22:42:53
可能有更好的自动化方法,但要回答所提出的问题,您可以取消选中Op中的"Retain /LF on copy or save“复选框
https://stackoverflow.com/questions/56480848
复制相似问题