Sql-Server-2017

SQL Server 2017 - 在包含列映射的字元串中提取源和目標列名

  • February 21, 2019

我將以下格式字元串儲存在文本中(可以是任意數量的列):

col1_source|col1_target;col2_source|col2_target;col3_source|col3_target;...

我試圖想出一種優雅的方法來提取和隔離所有 xxx_source 列名和所有 xxx_target 列名,以便我可以將它們儲存在變數中並獲得以下最終結果:

@Source_Columns = ‘col1_source,col2_source,col3_source’ @Target_Columns = ‘col1_target,col2_target,col3_target’

歸根結底,我想對我的源列和目標列執行 SELECT 以執行數據比較。

這是我迄今為止所取得的成就,但我發現它太複雜了(使用表值函式):

CREATE FUNCTION [dbo].[UF_miscParseStringToTable]
   (
       @list   nvarchar(MAX)
       , @sep  varchar(8) 
   ) 
RETURNS @ts table
   (
       [ID]        int identity
       , [value]   nvarchar(MAX)
   )
AS 
BEGIN 

   -- Parameters check
   if ((@sep is null) or (datalength(@sep) < 1)) return 

   if ((@list is null) or (@list = '') or (@list = @sep)) return

   -- Add path wildcards directly with sep
   -- ?worth it?
   if (left(@sep, 1) <> '%')   set @sep = '%' + @sep
   if (right(@sep, 1) <> '%')  set @sep = @sep + '%'

   -- First first sep
   declare @i int
   set @i = patindex(@sep, @list)

   -- Acc values
   while (@i > 0) begin
       insert into @ts ([value]) values (rtrim(left(@list, @i - 1)))
       set @list = ltrim(right(RTRIM(@list), len(@list) + 3 - (@i + len(@sep) )))
       set @i = patindex(@sep, @list)
   end

   set @list = rtrim(@list)
   -- Insert last value, if any
   if (@list <> '') insert into @ts (value) values (@list)

   return

END

上面的函式基本上採用我的映射字元串並將其轉換為表中的列名列表(請參閱下面的查詢邏輯):

DECLARE @Delim varchar(1) = '|'
DECLARE @Mapping varchar(max) = 'col1_source|col1_target;col2_source|col2_target;col3_source|col3_target'  
DECLARE @String varchar(max) = REPLACE(@Mapping,';', @Delim)
SELECT * FROM dbo.UF_miscParseStringToTable(@String, @Delim)

上述結果查詢產生下表:

ID| value
1 | col1_source
2 | col1_target
3 | col2_source
4 | col2_target
5 | col3_source
6 | col3_target

我也許可以對列索引進行連接,但是我發現很難隔離我的源欄位和目標欄位,以便我可以在它們之間進行數據比較。此外,如果我不需要,我想避免對錶執行額外的連接。

以下是所需的結果(能夠執行以下操作):

SELECT col1_source, col2_source, col3_source FROM mytable;

SELECT col1_target, col2_target, col3_target FROM mytable;

任何幫助或想法都會很棒!

肖恩

您沒有指定您的 RDBMS - 我的解決方案使用 SQL Server。

您的問題表明您有一個以文本形式儲存的格式化字元串

col1_source|col1_target;col2_source|col2_target;col3_source|col3_target;...

你進一步說明

我試圖想出一種優雅的方法來提取和隔離所有 xxx_source 列名和所有 xxx_target 列名,以便我可以將它們儲存在變數中並獲得以下最終結果:

@Source_Columns = ‘col1_source,col2_source,col3_source’ @Target_Columns = ‘col1_target,col2_target,col3_target’


我的解決方案使用 SQL Server 2016 STRING_SPLIT。如果您不符合該版本,還有其他方法可以拆分字元串。

drop table if exists #temp
Declare @String varchar(100) = 'col1_source|col1_target;col2_source|col2_target;col3_source|col3_target;'
----------------------------
Declare @SourceColumns varchar(max)
Declare @TargetColumns varchar(max)

--Split on semicolon and use PARSENAME to extract the source and target column information
SELECT @SourceColumns = isnull(@SourceColumns + ',', '') + SourceColumn
   ,@TargetColumns = isnull(@TargetColumns + ',', '') + TargetColumn
FROM (
   SELECT parsename(replace(value, '|', '.'), 2) AS SourceColumn
       ,parsename(replace(value, '|', '.'), 1) AS TargetColumn
   FROM (
       SELECT *
       FROM String_split(@string, ';')
       ) a
   WHERE value <> ' '
   ) a

選擇@SourceColumns

col1_source,col2_source,col3_source

選擇@TargetColumns

col1_target,col2_target,col3_target

引用自:https://dba.stackexchange.com/questions/230382