【问题标题】:Split a database table column value of type VARCHAR into multiple values using a delimiter?使用分隔符将 VARCHAR 类型的数据库表列值拆分为多个值?
【发布时间】:2020-04-07 02:48:21
【问题描述】:

您能否使用分隔符将VARCHAR 类型的数据库表列值拆分为多个值?

因此,在获取数据时,我想使用管道 | 作为分隔符来拆分像 text|another|other 这样的值。

我们使用的是存储过程和T-SQL,我对SQL有一些基本的了解,但我的理解是使用STRING_SPLIThttps://docs.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql?view=sql-server-ver15应该是可以的。

谁能帮助我了解更多细节?

【问题讨论】:

  • 没错。 STRING_SPLIT 可以使用SELECT value FROM STRING_SPLIT('text|another|other', '|'); 解决这个问题,但仅适用于 SQL Server 2016+
  • 你不应该首先存储这样的数据。仅仅因为有拆分功能并不意味着这是一个好主意。这样的字段是不可能索引的,这意味着搜索单个值需要扫描整个表
  • 没有拆分功能可以解决这个问题 - 这是一个设计错误,而不是编码错误。另一方面,如果您不关心查询,最好更好在客户端拆分值并使用它们做任何你想做的事情
  • 任何好的数据架构都知道在RDBMS中存储分隔数据是一个愚蠢的想法。首先,您没有机会实现外键,这意味着您无法维护数据完整性。这是一条你不想走的路。
  • 在这种情况下,@codeepic 在将数据加载到您自己的数据库之前清理数据。在代码中拆分和处理值要容易得多。例如,您是否希望将这些值与 columnsrows 分开?如果是行,则必须重复所有其他字段。表格行不能嵌套。但是,在加载数据时,您可以以任何方式拆分、嵌套、提取数据,并将其存储在任何您想要的地方

标签: sql-server tsql


【解决方案1】:

STRING_SPLIT 绝对是可能的,而且非常简单。甚至在引入STRING_SPLIT 的 SQL Server 2017 之前,它也是可能的,只是没有那么漂亮。

你的字符串的一个例子是这样的:

DECLARE @t TABLE (ID INT, StringVal VARCHAR(1000));

INSERT @t
VALUES (1, 'text|another|other');

SELECT *
FROM @t
CROSS APPLY STRING_SPLIT(StringVal, '|');

这个结果是

ID| StringVal          | value
--------------------------------
1 | text|another|other | text
1 | text|another|other | another
1 | text|another|other | other

所以回答你的问题,是的,这绝对是可能的。但是,您当然应该考虑评论讨论。

【讨论】:

    【解决方案2】:

    正如 Panagiotis Kanavos 作为评论所说,最好和最简单的方法是在 ETL 的“转换”部分(提取、转换、加载)。 当你这样做时,你甚至不必处理 SQL:因为你在 SQL-SERVER 上,我假设你使用 SSIS。您可以调用外部 C# 或 .Net 脚本来完成所有工作。

    要回答你的问题,是的,SQL 提供了很多处理字符串的内置函数:你可以使用 substr() + charindex(),或者 String_split,甚至可以自己编写

    关于字符串函数的微软文档:https://docs.microsoft.com/en-us/sql/t-sql/functions/string-functions-transact-sql?view=sql-server-ver15

    【讨论】:

      【解决方案3】:

      简短的回答是:你可以做到。

      更长的答案是:你不应该这样做,因为它违反了Database Normalization的原则。任何达到 NF3 的东西都是(可以说)最低限度的,你应该坚持下去。

      如果数据从外部来源进入您的数据库,请在您的ETL 进程中对其进行转换,然后再实际进入您的数据库。

      然后,您的数据库应以关系形式存储数据,并且应在检索时进行其他转换以适合您的前端,以使其适合您的消费应用程序。如果您愿意,可以阅读ANSI-SPARC Architecture

      【讨论】:

      • 是的。这对 SSIS 包加载数据的要求很高。
      【解决方案4】:

      请检查以下答案。这可能会有所帮助:

      DECLARE @Table TABLE (ID int, SampleData Varchar(100))
      
      INSERT @Table
      (ID,SampleData)
      VALUES
      (1, 'text|another|other'),
      (2, 'sample|data|again'),
      (3, 'this|should|help')
      
      
       SELECT 
           A.ID AS ID,  
           Split.a.value('.', 'VARCHAR(100)') AS SampleData  
       FROM  (
              SELECT 
                  ID,  
                  CAST ('<M>' + REPLACE(SampleData, '|', '</M><M>') + '</M>' AS XML) AS SampleData  
              FROM  
                  @Table A
               )  AS A 
          CROSS APPLY SampleData.nodes ('/M') AS Split(a)
      

      输出:-

      ID  SampleData
      1   text
      1   another
      1   other
      2   sample
      2   data
      2   again
      3   this
      3   should
      3   help
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-11
        • 2010-10-27
        • 2014-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多