如何导出空白表(即仅标题)以及包含数据的表。使用空白表格的原因是我的客户想要导入表格结构,即标题,以便将来在需要时可以使用它。
在以下情况下遵循解决方案:Exporting data from multiple SQL tables to different flat files using SSIS Script Task时出现以下错误:
错误:System.Reflection.TargetInvocationException:调用的目标引发了异常。 ---> System.NullReferenceException:对象引用未设置为对象的实例。在ST_97b3989b700a41f1ad54fb2abd27b891.vbproj.ScriptMain.Main()处-内部异常堆栈跟踪的结尾处-在System.RuntimeMethodHandle._InvokeMethodFast(对象目标,Object []参数,SignatureStruct&sig,MethodAttributes methodAttributes,RuntimeTypeReflectle typeOwner)处。 .System.Reflection.RuntimeMethodInfo.Invoke(对象obj,BindingFlags invokeAttr,活页夹活页夹,Object []参数,CultureInfo文化),位于Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTATaskScriptingEngine的System.RuntimeType.InvokeMember(字符串名称,BindingFlags bindingFlags,活页夹活页夹,对象目标,Object []提供的Args,ParameterModifier []修饰符,CultureInfo文化,String []命名为Paraams) .ExecuteScript()
答案 0 :(得分:1)
不需要自定义编码-这是SSIS的所有现成功能。
您的包裹看起来像这样
创建变量来处理我们所需要的。除rsObject
@[User::PathOutput] + "\\" + @[User::SchemaName] + "_" + @[User::TableName] + ".csv"
有两个连接管理器:Source和ExportFile。
Source是一个指向我的源数据库(localhost \ dev2014 msdb)的OLE DB连接管理器。
ExportFile是一个平面文件连接管理器,使用单列ColumnList,DT_STR数据类型,8000列宽定义,并使用CRLF的列定界符。要注意的另一件事是,我在连接管理器上定义了一个表达式(右键单击“连接管理器”,然后选择“属性”)。在这里,我们将ConnectionString
分配给变量@ [User :: CurrentFileName]
此任务的目的是生成我们正在使用的数据集。我将使用STUFF / FOR XML PATH“技巧”将多行连接为一行。我们将所有列折叠为一行,其中将包含SchemaName,TableName和以逗号分隔的列名列表。运行以下查询以查看其生成的数据。
SELECT
S.name AS SchemaName
, T.name AS TableName
, (
SELECT
STUFF
(
(
SELECT
',' + C.name
FROM
sys.columns AS C
WHERE
C.object_id = T.object_id
ORDER BY
C.column_id
FOR XML PATH('')
)
, 1
, 1
, ''
)
) AS ColumnList
FROM
sys.schemas AS S
INNER JOIN
sys.tables AS T
ON S.schema_id = T.schema_id
ORDER BY
1,2;
您可以修改上面的内容以过滤行数为零的位置,或者仅生成所有表,然后不向客户端发送不需要的文件。该解决方案留给您。
我指定Execute SQL Task返回完整的ResultSet。我将结果放入我们的变量@ [User :: rsObject]。
我使用了一个ForEach循环容器设置来粉碎ADO.NET结果。源表是我们的@ [User :: rsObject]。在围绕数据集的每个循环中,我们将@ [User :: SchemaName],@ [User :: TableName],@ [User :: ColumnList]
分配给SSIS变量该数据流任务旨在通过带有参数的OLE DB源选择列列表变量,并路由到平面文件目标。
OLE DB源使用以下查询
SELECT CAST(? AS varchar(8000)) AS ColumnList
我将@ [User :: ColumnList]映射到顺序位置0。这将允许源查询“导入”变量的值。
平面文件目标使用我们的ExportFile连接管理器,并将列ColumnList
映射到文件中的唯一列。
商业智能标记语言或Biml是描述SSIS包的XML方言。因为我可以为您提供此代码来创建上面已描述的确切包,所以它使创建SSIS包变得容易得多。
您如何使用它?
代码
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Connections>
<OleDbConnection ConnectionString="Data Source=localhost\dev2014;Initial Catalog=msdb;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;Packet Size=32767;" Name="Source" />
<FlatFileConnection Name="ExportFile" FileFormat="FFF Header File" FilePath="C:\ssisdata\Demo.csv" DelayValidation="true" />
</Connections>
<FileFormats>
<FlatFileFormat Name="FFF Header File" CodePage="1252" IsUnicode="false" >
<Columns>
<Column Name="ColumnList" DataType="AnsiString" Length="8000" Delimiter="CRLF" />
</Columns>
</FlatFileFormat>
</FileFormats>
<Packages>
<Package Name="SO_51195870" ConstraintMode="Linear">
<Connections>
<Connection ConnectionName="ExportFile">
<Expressions>
<Expression ExternalProperty="ConnectionString">@[User::CurrentFileName]</Expression>
</Expressions>
</Connection>
</Connections>
<Variables>
<Variable Name="SchemaName" DataType="String"></Variable>
<Variable Name="TableName" DataType="String"></Variable>
<Variable Name="ColumnList" DataType="String"></Variable>
<Variable Name="PathOutput" DataType="String">C:\ssisdata</Variable>
<Variable Name="CurrentFileName" DataType="String" EvaluateAsExpression="true">@[User::PathOutput] + "\\" + @[User::SchemaName] + "_" + @[User::TableName] + ".csv"</Variable>
<Variable Name="rsObject" DataType="Object" />
</Variables>
<Tasks>
<ExecuteSQL Name="SQL GetData" ConnectionName="Source" ResultSet="Full">
<Results>
<Result Name="0" VariableName="User.rsObject"/>
</Results>
<DirectInput>SELECT
S.name AS SchemaName
, T.name AS TableName
, (
SELECT
STUFF
(
(
SELECT
',' + C.name
FROM
sys.columns AS C
WHERE
C.object_id = T.object_id
ORDER BY
C.column_id
FOR XML PATH('')
)
, 1
, 1
, ''
)
) AS ColumnList
FROM
sys.schemas AS S
INNER JOIN
sys.tables AS T
ON S.schema_id = T.schema_id
ORDER BY
1,2</DirectInput>
</ExecuteSQL>
<ForEachAdoLoop Name="FELC Shred Results" SourceVariableName="User.rsObject">
<VariableMappings>
<VariableMapping Name="0" VariableName="User.SchemaName"/>
<VariableMapping Name="1" VariableName="User.TableName"/>
<VariableMapping Name="2" VariableName="User.ColumnList"/>
</VariableMappings>
<Tasks>
<Dataflow Name="DFT Generate Export" DelayValidation="true">
<Transformations>
<OleDbSource Name="OLESRC Query" ConnectionName="Source">
<DirectInput>SELECT CAST(? AS varchar(8000)) AS ColumnList</DirectInput>
<Parameters>
<Parameter Name="0" VariableName="User.ColumnList" />
</Parameters>
</OleDbSource>
<FlatFileDestination Name="DST File" ConnectionName="ExportFile"></FlatFileDestination>
</Transformations>
</Dataflow>
</Tasks>
</ForEachAdoLoop>
</Tasks>
</Package>
</Packages>
</Biml>
所引用的解决方案不希望导出空记录集。它具有明确的逻辑来测试空情况If reader.HasRows Then
...,这也是所提供错误的来源。最后一块中的writer.Close()
为Nothing,因此无法对其执行Close操作。
为了避免该异常,可能会进行重写
Finally
connection.Close()
If writer IsNot Nothing Then
writer.Close()
End If
End Try
也就是说,即使您删除了具有行检查功能,您仍然会得到一个空文件。
我真诚地推荐我概述的方法。我使用系统表来生成模式,表和列的集合。该数据集用于构建外部文件。这是解决上述问题的无脚本SSIS方法。引用的VB方法不会 这样做,这将完全重写该代码。
答案 1 :(得分:0)