好吧我知道你标记了oracle,所以也许你自己或另一个Oracle guru可以从sql-server迁移此解决方案。我知道oracle有能力进行这些操作。
通常我会说你想要一个快速/奇特的方式来分割一个字符串,但在这种情况下,你需要维护分隔符之间的字符串序号位置。所以我想到了一种可以做到这一点的方法。
1)首先将CSV导入临时表中作为全部1列。现在如果您的CRLF也在名称列中找到,那么这将成为问题....但我们会认为这不是因为您没有指定它。
2)在该表上构建一个row_number用作假主键,并确定何时存在的分隔符多于应该存在的分隔符。
3)使用递归cte将字符串溢出到行中,并在以后要连接的原始字符串中保留子字符串的序号位置。
4)确定由MergePositions改变OrdinalPostion并产生DENSE_RANK()的基础上它什么行组
5)条件聚合使用OrdinalGroup作为列号码,然后使用级联方法把所有OrdginalGroup结合3排。
DECLARE @CSV as TABLE (LumpedColumns NVARCHAR(MAX))
INSERT INTO @CSV VALUES
('May 1st, 2015|Y|Jingle|he|imerscmidt|19901002|123456789|3')
,('May 1st, 2015|N|Jingleheimerscmidt|19901002|123456789|3')
,('May 5th, 2015|Y|Jon|19901001||1')
,('May 1st, 2015|N|Jon|19901002||1')
,('May 1st, 2015|Y|Jacob|19901001|234567890|2')
,('May 5th, 2015|N|Jingleheimerscmidt|19901001|123456789|3')
,('May 1st, 2015|Y|Jingleheimerscmidt|19901001|123456789|3')
;WITH cteFakePrimaryKey AS (
SELECT
LumpedColumns
,CASE WHEN LEN(LumpedColumns) - LEN(REPLACE(LumpedColumns,'|','')) > 5 THEN
LEN(LumpedColumns) - LEN(REPLACE(LumpedColumns,'|','')) - 5 ELSE 0 END as MergeXPositions
,ROW_NUMBER() OVER (ORDER BY (SELECT 0)) as PK
FROM
@CSV
)
, cteRecursive AS (
SELECT
PK
,LumpedColumns
,MergeXPositions
,LEFT(LumpedColumns,CHARINDEX('|',LumpedColumns)-1) as ColValue
,RIGHT(LumpedColumns,LEN(LumpedColumns) - CHARINDEX('|',LumpedColumns)) as Remaining
,1 As OrdinalPosition
FROM
cteFakePrimaryKey
UNION ALL
SELECT
PK
,LumpedColumns
,MergeXPositions
,LEFT(Remaining,CHARINDEX('|',Remaining)-1)
,RIGHT(Remaining,LEN(Remaining) - CHARINDEX('|',Remaining))
,OrdinalPosition + 1
FROM
cteRecursive
WHERE
Remaining IS NOT NULL AND CHARINDEX('|',Remaining) > 0
UNION ALL
SELECT
PK
,LumpedColumns
,MergeXPositions
,Remaining
,NULL
,OrdinalPosition + 1
FROM
cteRecursive
WHERE Remaining IS NOT NULL AND CHARINDEX('|',Remaining) = 0
)
, cteOrdinalGroup AS (
SELECT
PK
,LumpedColumns
,ColValue
,OrdinalPosition
,DENSE_RANK() OVER (PARTITION BY PK ORDER BY
CASE
WHEN OrdinalPosition < 3 THEN OrdinalPosition
WHEN OrdinalPosition > (3 + MergeXPositions) THEN OrdinalPosition
ELSE 3 END) as OrdinalGRoup
FROM
cteRecursive
)
SELECT
PK
,LumpedColumns
,MAX(CASE WHEN OrdinalGRoup = 1 THEN ColValue END) as Date_Added
,MAX(CASE WHEN OrdinalGRoup = 2 THEN ColValue END) as this_flag
,STUFF(
(SELECT '|' + ColValue
FROM
cteOrdinalGroup g2
WHERE
g1.PK = g2.PK
AND g2.OrdinalGroup = 3
ORDER BY
g2.OrdinalPosition
FOR XML PATH(''))
,1,1,'') as name
,MAX(CASE WHEN OrdinalGRoup = 4 THEN ColValue END) as DOB
,MAX(CASE WHEN OrdinalGRoup = 5 THEN ColValue END) as SSN
,MAX(CASE WHEN OrdinalGRoup = 6 THEN ColValue END) as ID
FROM
cteOrdinalGroup g1
GROUP BY
PK
,LumpedColumns
ORDER BY
PK
没有打开文件?你的意思是不用在文本编辑器中打开手动执行它?该文件必须打开才能阅读其内容。您可以将它作为单个VARCHAR值引入,并根据您自己的规则剪切字符串....例如将每列分割为多行并确定何时存在太多行,然后连接回行并转回表格格式 – Matt
如果您可以控制csv文件的生成,您可以添加文本限定符,例如引号,以便文本中的管道不会与摄取应用程序(或您自己的数据清理代码)与分隔符相混淆。 – Jayvee
无论如何,您必须打开文件进行更改 - 无论是通过代码还是手动。 – Missy