【问题标题】:Extracting a string from a long string从长字符串中提取字符串
【发布时间】:2019-10-18 15:52:41
【问题描述】:

我有一个名为 Config 的列,其数据如下,它是一个长字符串

AutoFill = 1    Backgrouns = True  StoreAddress1 = '1601 River Road East'  StoreAddress2 = ''  StoreCity = 'Kitchener'  StoreProv = 'ON'  StorePostal = 'N2A 3Y4'  StorePhone = '(844) 607-6362'

我必须从中提取“1601 River Road East”并将其放在另一个表中作为地址行 1,Kitchener 作为该表中的城市,ON 作为该表中的省,N2A 3Y4 作为邮政编码

StoreAddress1 StoreAddress2 StoreCity 这个词总是会出现在这个长字符串中,用于其他行

我正在使用 Microsoft SQL Server 2016 我知道我必须使用 patindex 和 substring 但无法进行查询

【问题讨论】:

  • 到目前为止你尝试过什么?这里真正的问题是您在数据库中存储非规范化数据。希望您希望将此作为修复数据的一次性过程吗?如果没有,那么我建议应该现在作为目标,这样您就可以修复您的设计,而不必在将来像这样处理它。
  • 我别无选择,只能这样数据来自源系统,我必须从中提取这些详细信息并将其放在不同的表中
  • 也许它应该是您当时应该查看的源系统。甚至像 XML 这样的东西也会比上面的要好得多。 SQL Server 的强项不是字符串操作;它实际上很糟糕,它不支持正则表达式。您上面所拥有的是一个未定界的混搭值。
  • 我无法控制源系统,对不起,我的表中的数据是这样的
  • SQL Server 版本?

标签: sql-server


【解决方案1】:

如果是我,我会使用 Visual Studio c# 来更改这些而不是 T-SQL,这样您就可以进行一些错误检查。类似于以下内容。

var cn = new System.Data.SqlClient.SqlConnection("your connection");
      cn.Open();
      var cmd = new System.Data.SqlClient.SqlCommand("Select YourLongField From YourTable", cn);
      var dt = new System.Data.DataTable();
      dt.Load(cmd.ExecuteReader());
      cmd.Dispose();
      for (int i = 0; i < dt.Rows.Count; i++)
      {        
        var split = dt.Rows[i]["YourLongField"].ToString().Split(' ');
        //Error check here before inserting a new record
        var cmdInsertNew = new System.Data.SqlClient.SqlCommand("Insert Into YourNiceNewTable (Address1, Address2, StoreCity, StoreProv, StorePostal, StorePhone) Values (@Address1, @Address2, @StoreCity, @StoreProv, @StorePostal, @StorePhone)", cn);
cmdInsertNew.Parameters.AddWithValue("@Address1", split[2]);
        cmdInsertNew.Parameters.AddWithValue("@Address2", split[3]);
        cmdInsertNew.Parameters.AddWithValue("@StoreCity", split[4]);
        cmdInsertNew.Parameters.AddWithValue("@StoreProv", split[5]);
        cmdInsertNew.Parameters.AddWithValue("@StorePostal", split[6]);
        cmdInsertNew.Parameters.AddWithValue("@StorePhone", split[7]);
        cmdInsertNew.ExecuteNonQuery();
        cmdInsertNew.Dispose();
      }
      cn.Dispose();

【讨论】:

    【解决方案2】:

    这很丑,但是嘿...我必须在这里使用DelimitedSplit8k_LEAD,至于第二次拆分,序数位置很重要。无论如何,这完成了“工作”,但在值周围留下了单引号。这取决于您以后解决的问题。

    WITH Pivoted AS(
        SELECT V.UndelimitedList,
               DSc.ItemNumber,
               MAX(CASE DSv.ItemNumber WHEN 1 THEN DSv.Item END) AS ColumnName,
               MAX(CASE DSv.ItemNumber WHEN 2 THEN DSv.Item END) AS ItemValue
        FROM (VALUES('AutoFill = 1    Backgrouns = True  StoreAddress1 = ''1601 River Road East''  StoreAddress2 = ''''  StoreCity = ''Kitchener''  StoreProv = ''ON''  StorePostal = ''N2A 3Y4''  StorePhone = ''(844) 607-6362'''))V(UndelimitedList)
             CROSS APPLY(VALUES(REPLACE(REPLACE(V.UndelimitedList,'  ','|'),' = ','~'))) CL(DelimitedList) --Assumes no values will have a double space, and all are separated by double space
                                                                                                           --Also assumes that a Pipe (|) and Tilda (~) will never appear in your data
             CROSS APPLY dbo.DelimitedSplit8K_LEAD(CL.DelimitedList,'|') DSc
             CROSS APPLY dbo.DelimitedSplit8K_LEAD(DSc.Item,'~') DSv
        GROUP BY V.UndelimitedList,
                 DSc.ItemNumber
        HAVING MAX(CASE DSv.ItemNumber WHEN 1 THEN DSv.Item END) != '')
    SELECT MAX(CASE P.ColumnName WHEN 'AutoFill' THEN NULLIF(P.ItemValue,'''''') END) AS AutoFill,
           MAX(CASE P.ColumnName WHEN 'Backgrouns' THEN NULLIF(P.ItemValue,'''''') END) AS Backgrouns,
           MAX(CASE P.ColumnName WHEN 'StoreAddress1' THEN NULLIF(P.ItemValue,'''''') END) AS StoreAddress1,
           MAX(CASE P.ColumnName WHEN 'StoreAddress2' THEN NULLIF(P.ItemValue,'''''') END) AS StoreAddress2,
           MAX(CASE P.ColumnName WHEN 'StoreCity' THEN NULLIF(P.ItemValue,'''''') END) AS StoreCity,
           MAX(CASE P.ColumnName WHEN 'StoreProv' THEN NULLIF(P.ItemValue,'''''') END) AS StoreProv,
           MAX(CASE P.ColumnName WHEN 'StorePostal' THEN NULLIF(P.ItemValue,'''''') END) AS StorePostal,
           MAX(CASE P.ColumnName WHEN 'StorePhone' THEN NULLIF(P.ItemValue,'''''') END) AS StorePhone
    FROM Pivoted P
    GROUP BY P.UndelimitedList;
    

    DB<>Fiddle

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-02
      • 1970-01-01
      • 2014-12-29
      • 2020-12-02
      • 2011-07-21
      • 2019-10-15
      • 1970-01-01
      相关资源
      最近更新 更多