我的字符串由$$
个字符分隔,如下所示:
BOB$$"DOG"$$"BROWN"$$"9"$$"4"$$"Latest"$$$$$$"small.
EVA$$"CAT"$$"BLACK"$$"1"$$"4"$$$$"Mouse"$$"Milk"$$small.
我想获得使用后的功能:更新/插入select / SSIS映射
表格如下:
Column1 Column2 Column3 Column4 Column5 Column6 Column7 Column8 Column9
BOB "DOG" "BROWN" "9" "4" "Lat,est" NULL NULL small.
EVA "CAT" "BLACK" "1" "4" NULL "Mouse" "Milk" small.
我可以使用功能Update / Insert进行9行选择以获得结果吗? 我可以创建两个表;第一个表包含单列,第二个表包含9或10列。
我需要100多行的通用解决方案。以上两行只是示例。
我想继续使用这种类型的代码:
SELECT [Column0]
,LEFT([Column0], CHARINDEX('$$', [Column0]) - 1) AS [name]
FROM [dbo].[tablename]
答案 0 :(得分:1)
你可以使用它。
;WITH CTE_1 AS (
SELECT TXT= TXT +'$$', ID = ROW_NUMBER() OVER(ORDER BY TXT)
FROM (VALUES
('BOB$$"DOG"$$"BROWN"$$"9"$$"4"$$"Lat,est"$$$$$$small.'),
('EVA$$"CAT"$$"BLACK"$$"1"$$"4"$$$$"Mouse"$$"Milk"$$small.')) AS X(TXT)
)
, CTE_2 AS -- It split text to rows
(
SELECT RIGHT(CTE_1.TXT, LEN(CTE_1.TXT) - CHARINDEX('$$',CTE_1.TXT)-1) TXT , SUBSTRING(CTE_1.TXT, 0, CHARINDEX('$$',CTE_1.TXT)) WORD, CHARINDEX('$$',CTE_1.TXT) AS CI, CTE_1.ID, 1 WID
FROM CTE_1
UNION ALL
SELECT RIGHT(CTE_2.TXT, LEN(CTE_2.TXT) - CHARINDEX('$$',CTE_2.TXT)-1) TXT , SUBSTRING(CTE_2.TXT, 0, CHARINDEX('$$',CTE_2.TXT)) WORD, CHARINDEX('$$',CTE_2.TXT) AS CI, CTE_2.ID, WID = WID +1
FROM CTE_2 WHERE LEN(CTE_2.TXT) > 0
)
SELECT * FROM (SELECT ID, (CASE WHEN WORD='' THEN NULL ELSE WORD END) WORD, WID FROM CTE_2 ) SRC -- It convert rows to columns by using pivot
PIVOT(MAX(WORD) FOR WID IN ([1],[2],[3],[4],[5],[6],[7],[8],[9])) PVT
OPTION (MAXRECURSION 0)
结果:
ID 1 2 3 4 5 6 7 8 9
-------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
1 BOB "DOG" "BROWN" "9" "4" "Lat,est" NULL NULL small.
2 EVA "CAT" "BLACK" "1" "4" NULL "Mouse" "Milk" small.
答案 1 :(得分:1)
你走在正确的轨道上。使用SSIS导入平面文件时,我们通常会将所有内容导入为varchar数据类型列表(称为登台表),然后检查列值以确保数据类型的一致性。 这使我们可以导入所有内容而不会丢失数据,并为清理数据提供了机会。
方法1:对于您的情况,您可以在SSIS数据流任务源中使用$$作为列分隔符。 SSIS不关心标题列的顺序或名称。您可以在标题名称中添加任何内容,例如第1列,第2列等。 在这种方法中,您将数据从文件导入9列表。如果某些行中的列数较少/较多,则此方法将失败。
方法2:您将所有内容作为单列导入到varchar登台表(1)。 从这里开始拆分所有列并插入到9列(NULLable)的另一个varchar登台表(2)中,然后在将数据移动到数据类型列表之前进行数据验证。
可以在方法2中使用的查询
create table staging_tbl_single_row (datarow varchar(max))
insert into staging_tbl_single_row values
('BOB$$"DOG"$$"BROWN"$$"9"$$"4"$$"Latest"$$$$$$"small.'),
('EVA$$"CAT"$$"BLACK"$$"1"$$"4"$$$$"Mouse"$$"Milk"$$small.')
; with cte as
(
select
row_number() over (order by (select NULL)) as column1,
replace(datarow,'$$','|') as column2
from staging_tbl_single_row
)
--Insert into SomeTable
select
[1],[2],[3],[4],[5],[6],[7],[8],[9]
from
(
select
t.column1,
split_values=SUBSTRING( t.column2, t1.N, ISNULL(NULLIF(CHARINDEX('|',t.column2,t1.N),0)-t1.N,8000)),
r= row_number() over( partition by column1 order by t1.N)
from cte t
join
(
select
t.column2,
1 as N
from cte t
UNION ALL
select
t.column2,
t1.N + 1 as N
from cte t
join
(
select
top 8000
row_number() over(order by (select NULL)) as N
from
sys.objects s1
cross join
sys.objects s2
) t1
on SUBSTRING(t.column2,t1.N,1) = '|'
) t1
on t1.column2=t.column2
)a
pivot
(
max(split_values) for r in ([1],[2],[3],[4],[5],[6],[7],[8],[9])
)p
答案 2 :(得分:0)
解决方案不是我的,并显示了一般方法
declare @s varchar(max) ='BOB$$DOG$$BROWN$$9$$4$$Latest$$$$small.
EVA$$CAT$$BLACK$$1$$4$$$$Mouse$$Mil$$small'
select
t.n.value('b[1]', 'varchar(10)'),
t.n.value('b[2]', 'varchar(10)'),
t.n.value('b[3]', 'varchar(10)'),
t.n.value('b[4]', 'varchar(10)'),
t.n.value('b[5]', 'varchar(10)'),
t.n.value('b[6]', 'varchar(10)'),
t.n.value('b[7]', 'varchar(10)'),
t.n.value('b[8]', 'varchar(10)')
from
(select cast(cast('' as xml).query('sql:variable("@s")') as varchar(max))) a(s) cross apply
(select cast('<a><b>' + replace(replace(a.s, '$$', '</b><b>'), '.', '</b></a><a><b>') + '</b></a>' as xml)) b(x) cross apply
b.x.nodes('a') t(n);
答案 3 :(得分:0)
遵循一个简单的C#示例,可以轻松转换为C#转换:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication10
{
class Program
{
static void Main(string[] args)
{
string[] MyInput = new string[]{"BOB$$\"DOG\"$$\"BROWN\"$$\"9\"$$\"4\"$$\"Latest\"$$$$ß\"small."
, "EVA$$\"CAT\"$$\"BLACK\"$$\"1\"$$\"4\"$$$$\"Mouse\"$$\"Milk\"small."};
int InputIndex = 0;
string[] delimiters = new string[]{"$$"};
foreach (string si in MyInput)
{
string OutCol01 = null, OutCol02 = null, OutCol03 = null, OutCol04 = null, OutCol05 = null
, OutCol06 = null, OutCol07 = null, OutCol08 = null, OutCol09 = null, OutCol10 = null;
int ColIdx = 0;
InputIndex += 1;
string[] x = si.Split(delimiters, StringSplitOptions.None);
foreach (string s in x)
{
ColIdx += 1;
switch (ColIdx)
{
case 1:
OutCol01 = s;
break;
case 2:
OutCol02 = s;
break;
case 3:
OutCol03 = s;
break;
case 4:
OutCol04 = s;
break;
case 5:
OutCol05 = s;
break;
case 6:
OutCol06 = s;
break;
case 7:
OutCol07 = s;
break;
case 8:
OutCol08 = s;
break;
case 9:
OutCol09 = s;
break;
case 10:
OutCol10 = s;
break;
default:
break;
}
}
Console.WriteLine(InputIndex.ToString() + " - " + OutCol01);
Console.WriteLine(InputIndex.ToString() + " - " + OutCol02);
Console.WriteLine(InputIndex.ToString() + " - " + OutCol03);
Console.WriteLine(InputIndex.ToString() + " - " + OutCol04);
Console.WriteLine(InputIndex.ToString() + " - " + OutCol05);
Console.WriteLine(InputIndex.ToString() + " - " + OutCol06);
Console.WriteLine(InputIndex.ToString() + " - " + OutCol07);
Console.WriteLine(InputIndex.ToString() + " - " + OutCol08);
Console.WriteLine(InputIndex.ToString() + " - " + OutCol09);
Console.WriteLine(InputIndex.ToString() + " - " + OutCol10);
}
Console.ReadKey();
}
}
}
答案 4 :(得分:0)
如果您有fix 9 Column Data
:
SELECT CASE
WHEN Column1 = ''
THEN NULL
ELSE Column1
END Column1,
CASE
WHEN Column2 = ''
THEN NULL
ELSE Column2
END Column2,
CASE
WHEN Column3 = ''
THEN NULL
ELSE Column3
END Column3,
CASE
WHEN Column4 = ''
THEN NULL
ELSE Column4
END Column4,
CASE
WHEN Column5 = ''
THEN NULL
ELSE Column5
END Column5,
CASE
WHEN Column6 = ''
THEN NULL
ELSE Column6
END Column6,
CASE
WHEN Column7 = ''
THEN NULL
ELSE Column7
END Column7,
CASE
WHEN Column8 = ''
THEN NULL
ELSE Column8
END Column8,
CASE
WHEN Column9 = ''
THEN NULL
ELSE Column9
END Column9
FROM
(
SELECT DISTINCT
Split.a.value('/M[1]', 'NVARCHAR(MAX)') Column1,
Split.a.value('/M[2]', 'NVARCHAR(MAX)') Column2,
Split.a.value('/M[3]', 'NVARCHAR(MAX)') Column3,
Split.a.value('/M[4]', 'NVARCHAR(MAX)') Column4,
Split.a.value('/M[5]', 'NVARCHAR(MAX)') Column5,
Split.a.value('/M[6]', 'NVARCHAR(MAX)') Column6,
Split.a.value('/M[7]', 'NVARCHAR(MAX)') Column7,
Split.a.value('/M[8]', 'NVARCHAR(MAX)') Column8,
Split.a.value('/M[9]', 'NVARCHAR(MAX)') Column9
FROM
(
SELECT CAST('<M>'+REPLACE(<Column>, '$$', '</M><M>')+'</M>' AS XML) AS String
FROM <table_name>
) A
CROSS APPLY String.nodes('/M') Split(a)
) A;
期望输出:
Column1 Column2 Column3 Column4 Column5 Column6 Column7 Column8 Column9
BOB "DOG" "BROWN" "9" "4" "Lat,est" NULL NULL small.
EVA "CAT" "BLACK" "1" "4" NULL "Mouse" "Milk" small.
答案 5 :(得分:0)
虽然您已经接受了另一种解决方案,但我想展示如何解决这个SSIS方式,绝对不需要编码:
1)如果尚未存在,请将数据流元素添加到您的包控制流程中。
2)转到数据流并添加平面文件来源元素。
3)点击编辑平面文件来源。
在连接管理器窗格中,选中复选框&#34;将来自源的空值保留为数据流中的空值&#34; < / p>
点击新建... 按钮创建新的平面文件连接。
4)在平面文件连接管理器编辑器上,单击浏览... 以打开源文件。
选择所需的代码页/编码
保留格式,文本限定符,标题行分隔符和标题行的预选默认值跳过强>
取消选中&#34;第一个数据行中的列名称&#34; (除非您的示例以外,您的真实文件包含标题行)
5)切换到列窗格并将列分隔符更改为$$
(只需输入 - 列出的值只是被提议作为最常用的选择)
6)切换到高级窗格。
选中左侧列表框中的每一列,并将名称属性编辑为有意义的值
根据需要修改 OutputColumnWidth 的值。
选择左侧列表框中的所有列,并将 TextQualified 质量编辑为False
...这样可确保您的周围报价符合要求。
切换到预览窗格,使用确定检查并关闭平面文件连接编辑器。
7)使用确定关闭平面文件源编辑器。
8)添加所需的目标(OLE DB)并连接您的平面文件源