sql-server - 如何选择 SQL Server 表作为制表符分隔的字符串
问题描述
我想从 SQL 中选择一个表并将其转换为最好是制表符分隔的,否则为 CSV 格式。
| col_1 | col_2 | col_3 | col_n |
+-------+-------+-------+-------+
| data1 | data2 | data3 | data4 |
| data5 | data6 | data7 | data8 |
使用for xml path
我可以选择表作为带有<tag-name>
分隔符的字符串。
let str = stuff((select * from db_name for xml path('')), 1, 1 '')
实际输出
<col_1>data1</col_1><col_2>data2</col_2><col_3>data3</col_3><col_4>data4</col_4>
<col_5>data5</col_5><col_6>data6</col_6><col_7>data7</col_7><col_8>data8</col_8>
预期的字符串输出
data1 data2 data3 data4
data5 data6 data7 data8
该表非常宽,因此使用类似concat
并列出每一列的方法不是很容易维护。
如何选择上表作为制表符分隔的字符串?
解决方案
Notice the _RN is required in the supplying query. Could also be a TVF
Also, the ,ELEMENTS XSINIL
is required to keep the "position" of null values, but they will NOT be null, bur rather an empty string
Example dbFiddle
Declare @YourTable Table ([col_1] varchar(50),[col_2] varchar(50),[col_3] varchar(50),[col_n] varchar(50)) Insert Into @YourTable Values
('data1','data2','data3','data4')
,('data5','data6','data7','data8')
Select [dbo].[svf-str-Data-Tab-delimited]((Select *,_RN=Row_Number() over (Order By (Select null)) From @YourTable for XML RAW,ELEMENTS XSINIL ))
Returns
data1 data2 data3 data4
data5 data6 data7 data8
The Function if Interested
CREATE Function [dbo].[svf-str-Data-Tab-delimited] (@XML xml)
Returns varchar(max)
Begin
Declare @S varchar(max) = ''
Select @S = @S+ case when ColItem<>'_RN' then ColValue else '' end + case when ColItem='_RN' then char(13)+char(10) else char(9) end
From (
Select ColSeq = row_number() over(order by (select null))
,ColItem = xAttr.value('local-name(.)', 'nvarchar(100)')
,ColValue = xAttr.value('.','nvarchar(max)')
From @XML.nodes('/row/*') xNode(xAttr)
) A
Order By ColSeq
Return @S
End
EDIT -
The original solution had a trailing tab. I also modified the function by adding parameters for the delimiter and EOL.
Example Updated dbFiddle
Declare @YourTable Table ([col_1] varchar(50),[col_2] varchar(50),[col_3] varchar(50),[col_n] varchar(50)) Insert Into @YourTable Values
('data1','data2','data3','data4')
,('data5','data6','data7','data8')
Declare @XML xml = (Select *,_RN=Row_Number() over (Order By (Select null)) From @YourTable for XML RAW,ELEMENTS XSINIL )
Select [dbo].[svf-str-Data-To-Delimited](char(9),char(13)+char(10),@XML)
Returns
data1 data2 data3 data4
data5 data6 data7 data8
The Update Function
CREATE Function [dbo].[svf-str-Data-To-Delimited] (@Delim varchar(50),@EOL varchar(50),@XML xml)
Returns varchar(max)
Begin
Return(
Select convert(varchar(max),(
Select case when Item='_RN' then ''
else case when nullif(lead(Item,1) over (Order by Seq),'_RN') is not null
then concat(Value,@Delim)
else concat(Value,@EOL)
end
end
From (
Select Seq = row_number() over(order by (select null))
,Item = xAttr.value('local-name(.)', 'nvarchar(100)')
,Value = xAttr.value('.','nvarchar(max)')
From @XML.nodes('/row/*') xNode(xAttr)
) A
Order By Seq
For XML Path (''),TYPE).value('.', 'nvarchar(max)') )
)
End
推荐阅读
- angular-reactive-forms - 如何获取值已更改的输入字段名称 [Angular 6]
- c# - 为一对多但两次配置 EF Fluent API
- date - 从 HiveQL 中的现有日期创建日期
- python - Python 为 crypt 结果添加了额外的内容
- hyperledger-fabric - 无法从结构多组织网络在第二个对等点上安装 .bna
- c++ - 如何用 C++ 编写简单的启动代码?
- awk - awk/grep 根据 file1 中的匹配字符串列表在 file2 中打印整个记录
- python - 机器学习数据集标签取决于不止一行
- vba - 转发 Outlook 电子邮件而不添加原始电子邮件的签名或 From: 和 To:
- r - R:在保持顺序的同时折叠列中的重复值