【发布时间】:2020-11-09 04:41:03
【问题描述】:
我有一个从 SQL Server Management Studio (v18.5) 执行的批处理查询,它有多个动态片段并生成多个查询结果,如果可能的话,我想从 SSMS 控制台自动导出到 Excel。
在批处理查询中,我首先从表中的 1 列中选择一个唯一的集合值,然后遍历该列表以使用列表中的值构建动态数据透视查询。每个数据透视查询的每个值都会有一组不同的结果。
例如:我循环的唯一列表:
Type
-----
Fan
Compressor
Belt
Motor
Filter
Fan 的数据透视查询结果将具有一组独特的列,这些列与 Compressor 的数据透视查询结果不同。
风扇轴列
FanID, Speed, Weight, Blade Size, RPM
压缩机枢轴列
CompressorID, HP, Voltage, Amps, Height,
每次循环浏览类型列表时,我都想将旋转后的查询结果导出到 Excel 文件。理想情况下,我想导出到 1 个工作簿,每个类型的旋转查询结果都有自己的工作表。由于每个透视查询结果都会有一组不同的列,因此我无法将所有查询结果编译到 1 个表中,然后导出到 Excel(或 csv)。尽量避免有多个文件,每种类型一个。
更新:
我已将以下内容添加到我的批处理查询中:
INSERT INTO OPENROWSET(''Microsoft.ACE.OLEDB.12.0'',''Excel 12.0; Database=C:\temp\tesxt.xlsx;'',''SELECT * FROM [Sheet1$]'')
但我收到以下错误:
Cannot create an instance of OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "(null)"
我在尝试上面的代码之前运行了这两个命令:
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'Ad Hoc Distributed Queries', 1
RECONFIGURE
更新: 我希望有一个糟糕的导出选项可以消除编写应用程序的需要。
我尝试了 BCP 方法,但无法让它发挥作用。我将服务器名称更改为我的,将数据库名称更改为我的;没有运气。 @sql 变量是我的动态数据透视查询。尝试了不同的 bcp 命令参数,但没有成功。
更新: 靠近一点;我用一个简单的选择查询替换了上面 bcp 命令中的 @sql 并执行了该命令,为类型列表中的每个“类型”创建了一个新的 .csv 文件;在复杂的动态数据透视@sql 字符串中一定有 bcp 不喜欢的东西。无论如何,我知道将 bcp 查询结果导出到 csv 文件的底层管道正在工作。
更新:
这是@sqlCommandForBcp
set @sqlCommandForBcp = 'bcp "'+ @sqlForPivot + '" queryout "' + @filePath + @fileName + '" -S CLT00ZB1\SQLEXPRESS2019 -T -t , -d Repository -c'
这是@sqlCommandForBcp 的打印输出,其中包括一个真实数据透视查询的示例。类型列表的每次迭代都会生成一个具有不同列的新数据透视查询。
bcp "SELECT ProductID, KWGAID, ShortDesc, VendorID, Segment, Category, Type, SubType,[Airflow], [Amperage], [Bearings], [Cross Reference], [Diameter], [Enclosure], [Footnotes], [Frame], [Frequency], [Item], [Motor Type], [OEM], [Options], [Power], [Replacing], [Rotation], [RPM], [RPM-Range], [Series-Brand], [Shaft], [Speed], [Stack Size], [Voltage]
FROM
(
SELECT ''+ CONVERT(nvarchar(8), a.SeqNum) + ' | ' + '' + a.TypeID + '' + ' | ' + CONVERT(nvarchar(1), a.IncludeName) + ' | ' +
a.Value as Value, a.Name, p.KWGAID, p.SeqNum as ProductID, p.ShortDescription as ShortDesc,
p.VendorID, p.VendorPartNumber, s.Name as Segment, c.Name as Category,
t.Name as Type, st.Name as SubType
FROM Product p INNER JOIN
Segment s ON p.SegmentID = s.ID INNER JOIN
Category c ON p.CategoryID = c.ID INNER JOIN
Type t ON p.TypeID = t.ID INNER JOIN
Vendor v ON p.VendorID = v.ID INNER JOIN
SubType st ON p.SubTypeID = st.ID INNER JOIN
Attribute a ON p.SeqNum = a.ProductSeqNum INNER JOIN
AttributeType at ON a.TypeID = at.ID
Where v.ID = 132 AND c.Name like 'Blower Motors'
) as PivotData
PIVOT
(
Max(Value)
For Name IN ([Airflow], [Amperage], [Bearings], [Cross Reference], [Diameter], [Enclosure], [Footnotes], [Frame], [Frequency], [Item], [Motor Type], [OEM], [Options], [Power], [Replacing], [Rotation], [RPM], [RPM-Range], [Series-Brand], [Shaft], [Speed], [Stack Size], [Voltage])
) as PivotResults Order by Segment, Category, Type, SubType, ShortDesc" queryout "C:\Temp\Blower Motors.csv" -S CLT00ZB1\SQLEXPRESS2019 -T -t , -d Repository -c
更新:
又向前迈了一步。将数据透视查询结果插入到临时全局表中,然后在 bcp 命令中选择该表即可!我现在将结果导出到单个 csv 文件;但是,我看到了两个问题。 1. 结果不包括列标题;我必须拥有这些,并且每个数据透视查询结果都会有不同的列。 2. 查询结果中有逗号,就是把导出的结果丢掉了。我通读了 bcp 文档,没有看到强制列标题的命令开关;也不知道如何处理查询结果中的逗号。
更新: 我最终放弃了使用 SSMS 的 tSQL 方法,开始用另一种语言编写解决方案。这仅用于临时清理项目,而不是长期生产解决方案。我正在使用通过 ODBC 和一些 VBA 链接的 Access 来处理遍历类型列表并将透视(Access 中的 CrossTab)结果导出到 Excel。使用 VBA,我拥有动态创建工作簿和插入工作表等所需的一切。
我在 SQL 中学到了一些关于 bcp 和链接服务器的知识,但是对于我想要做的事情,没有一个非常简单的解决方案。
不确定谁应该在这里获得积分。感谢大家的投入。
【问题讨论】:
-
你能显示SQL吗?如果您需要帮助。
-
您是否尝试检查此线程的答案? stackoverflow.com/questions/36987636/…
-
这篇文章帮助我解决了这个问题sqlwithmanoj.com/2012/07/10/…
-
我贴了上面的SQL;里面有一些它不喜欢的东西,只是不确定是什么。至于 Kokokoko 的 cmets,谢谢,我看了这两个...在链接服务器方法中遇到了权限问题...感觉 bcp 是“这个”关闭...哈哈。
标签: sql-server tsql pivot ssms export-to-excel