我有一个棘手的平面文件数据源。数据分组,如下所示:
Country City
U.S. New York
Washington
Baltimore
Canada Toronto
Vancouver
但我希望它在加载到数据库时成为这种格式:
Country City
U.S. New York
U.S. Washington
U.S. Baltimore
Canada Toronto
Canada Vancouver
之前有人遇到过这样的问题吗?有想法处理它吗? 我现在唯一的想法是使用光标,但它太慢了 谢谢!
答案 0 :(得分:3)
是的,有可能。首先,您需要将数据加载到具有IDENTITY列的表中:
-- drop table #t
CREATE TABLE #t (id INTEGER IDENTITY PRIMARY KEY,
Country VARCHAR(20),
City VARCHAR(20))
INSERT INTO #t(Country, City)
SELECT a.Country, a.City
FROM OPENROWSET( BULK 'c:\import.txt',
FORMATFILE = 'c:\format.fmt',
FIRSTROW = 2) AS a;
select * from #t
结果将是:
id Country City
----------- -------------------- --------------------
1 U.S. New York
2 Washington
3 Baltimore
4 Canada Toronto
5 Vancouver
现在有了一些递归的CTE魔法,你可以填充缺失的细节:
;WITH a as(
SELECT Country
,City
,ID
FROM #t WHERE ID = 1
UNION ALL
SELECT COALESCE(NULLIF(LTrim(#t.Country), ''),a.Country)
,#t.City
,#t.ID
FROM a INNER JOIN #t ON a.ID+1 = #t.ID
)
SELECT * FROM a
OPTION (MAXRECURSION 0)
结果:
Country City ID
-------------------- -------------------- -----------
U.S. New York 1
U.S. Washington 2
U.S. Baltimore 3
Canada Toronto 4
Canada Vancouver 5
<强>更新强>
正如Tab Alleman在下面建议的那样,在没有递归查询的情况下可以实现相同的结果:
SELECT ID
, COALESCE(NULLIF(LTrim(a.Country), ''), (SELECT TOP 1 Country FROM #t t WHERE t.ID < a.ID AND LTrim(t.Country) <> '' ORDER BY t.ID DESC))
, City
FROM #t a
BTW,输入数据的格式文件是这样的(如果你想尝试脚本将输入数据保存为c:\ import.txt,下面的格式文件保存为c:\ format.fmt):
9.0
2
1 SQLCHAR 0 11 "" 1 Country SQL_Latin1_General_CP1_CI_AS
2 SQLCHAR 0 100 "\r\n" 2 City SQL_Latin1_General_CP1_CI_AS
答案 1 :(得分:3)
cha的答案是可行的,但如果你需要在没有临时/临时表的情况下在SSIS中这样做,这是另一个:
您可以通过使用DataFlow级变量的脚本转换来运行数据流。当每行进入脚本时,检查Country列的值。
如果它具有非空值,则使用该值填充变量,并在数据流中传递它。
如果Country有空白值,则用变量值覆盖它,这将是您获得的最后一个非空白国家/地区值。
编辑:我查找了您的错误消息并学习了一些关于脚本组件的新内容(数据流工具,而不是脚本任务,控制流工具):ReadWriteVariables集合仅在 PostExecute方法可以最大限度地提高性能并将风险降至最低 锁定冲突。因此,您无法直接递增该值 处理每行数据时的包变量。递增 取而代之的是局部变量的值,并设置包的值 变量为PostExecute方法中局部变量的值 处理完所有数据后。你也可以使用 VariableDispenser属性可以解决此限制问题 本主题后面会介绍。但是,直接写入包 处理每一行的变量将对性能产生负面影响 并增加锁定冲突的风险。
来自this MSDN article,如果你想走那条路,它还有更多关于变量分配器解决方法的信息,但是当我说你可以设置包的价值时,显然我误解了你脚本中的变量。您必须使用脚本本地的变量,然后在Post-Execute事件处理程序中更改它。我无法从文章中看出这是否意味着您将无法读取脚本中的变量,如果是这种情况,那么变量分配器将是唯一的选择。或者我想你可以创建另一个脚本具有只读访问权限的变量,并将其值设置为表达式,以便它始终具有读写变量的值。这可能有用。