SQL Server 将值拆分为列

标签 sql sql-server sql-server-2008 t-sql

我有由 $$ 字符分隔的字符串,如下所示:

BOB$$"DOG"$$"BROWN"$$"9"$$"4"$$"Latest"$$$$$$"small.
EVA$$"CAT"$$"BLACK"$$"1"$$"4"$$$$"Mouse"$$"Milk"$$small. 

我想获得使用后的功能:更新/插入选择/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 into select 函数生成 9 行来获取结果吗? 我可以创建两个表;第一个表包含单列,第二个表包含 9 或 10 列。

我需要 100 多行的通用解决方案。上面两行只是示例。

我想继续使用这种类型的代码:

SELECT   [Column0]
        ,LEFT([Column0], CHARINDEX('$$', [Column0]) - 1) AS [name]

FROM    [dbo].[tablename]

最佳答案

您走在正确的道路上。当使用 SSIS 导入平面文件时,我们通常将所有内容导入为 varchar 数据类型列表(称为临时表),然后检查列值的数据类型一致性。 这使我们能够导入所有内容而不会丢失数据,并为清理数据提供了机会。

方法 1:对于您的情况,您可以在 SSIS 数据流任务源中使用 $$ 作为列分隔符。 SSIS 不关心标题列的顺序或名称。标题名称中可以包含任何内容,例如 Column 1、Column 2 等。 在这种方法中,您将数据从文件导入到 9 列表中。如果某些行中有较少/较多的列,则此方法将会失败。

方法 2:将所有内容作为单列导入到 varchar 临时表 (1) 中。 从这里,您拆分所有列并插入到另一个 9 列(可空)的 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

see working demo

关于SQL Server 将值拆分为列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46680776/

相关文章:

SQL 将具有相同节点的 XML 转换为数据集

mysql - 服务器链接 - mysql 和 sql 2008 服务器链接

sql - API : How can I remotely check if two data sets are identical, 没有通过 API 发送所有数据?

sql - 对于性能问题,在数据库中保留记录而不是删除它是否有好处?

sql - PostgreSQL 中使用多个条件的复杂重复数据删除

sql - 在sql中以管道分隔的列中搜索值

C# - 即使 CommandTimeout 设置为在设定时间后终止查询,查询仍在 SQL Server 数据库中运行

sql - 在 XML 数据类型中存储特殊字符(例如 &)

SQL IF 存在还是 WHERE 存在?

MySQL 查询查找跨多行的匹配项