如何在丢失或不丢失时有条件地解析字符串中的默认值

问题描述 投票:1回答:1

我想有条件地确定我是否在字符串中有一个默认值(下面我的映射字符串中的第三个值为零)。

我有以下字符串:

'PriceSrc|PriceTrg|0;CurrencySrc|CurrencyTrg|0;ProductSrc|ProductTrg|0'

上面用分号表示SourceColumn | TargetColumn | DefaultValue。因此,我的字符串中有两个分隔符 - 管道和分号。

我正在分离我的源,目标和默认列,它在我的代码中运行良好:

DECLARE @Mapping NVARCHAR(max) = 'PriceSrc|PriceTrg|0;CurrencySrc|CurrencyTrg|0;ProductSrc|ProductTrg|0'
DECLARE @SourceTableColumns VARCHAR(256)
DECLARE @TargetTableColumns VARCHAR(256)
DECLARE @DefaultTableColumn VARCHAR(256)

    SELECT   @SourceTableColumns = isnull(@SourceTableColumns + ',', '') + SourceTableColumn
            ,@TargetTableColumns = isnull(@TargetTableColumns + ',', '') + TargetTableColumn
            ,@DefaultTableColumn = isnull(@DefaultTableColumn + ',', '') + DefaultTableColumn
    FROM (
        SELECT   parsename(replace(value, '|', '.'), 3) AS SourceTableColumn
                ,parsename(replace(value, '|', '.'), 2) AS TargetTableColumn
                ,parsename(replace(value, '|', '.'), 1) AS DefaultTableColumn
        FROM (
            SELECT *
            FROM String_split(@Mapping,';')
            ) a
        WHERE value <> ' '
        ) a

print 'Mapping: ' + @Mapping
print 'Source: ' + @SourceTableColumns
print 'Target: ' + @TargetTableColumns
print 'Default: ' + @DefaultTableColumn

以下是我的第三个默认值始终填充时的结果(我的映射字符串中的第3个值为零):

PriceSrc|PriceTrg|0;CurrencySrc|CurrencyTrg|0;ProductSrc|ProductTrg|0
Source: PriceSrc,CurrencySrc,ProductSrc
Target: PriceTrg,CurrencyTrg,ProductTrg
Default: 0,0,0

但是,当我甚至有一个缺少的默认值时,例如下面(注意我已经排除了我的字符串末尾的一个零)...

'PriceSrc|PriceTrg|0;CurrencySrc|CurrencyTrg|0;ProductSrc|ProductTrg|'

我的整个逻辑崩溃了,它消除了我所有的变量。它给了我以下结果(只有我的映射):

Mapping: PriceSrc|PriceTrg|0;CurrencySrc|CurrencyTrg|0;ProductSrc|ProductTrg|

请注意,默认值3rd参数的功能是作为覆盖值,供用户输入任何字符串或数值(如果他们选择)。如果它是NULL,我不想总是强制我的默认值,因为它并不总是需要。

如何在映射字符串中设置默认值(即DefaultTableColumn)?如上所述,我可能并不总是有默认值,但我仍然希望保持@SourceTableColumns和@TargetTableColumns变量不变。


Zohar Peled提出的修改逻辑:

SELECT   @SourceTableColumns = isnull(@SourceTableColumns + ',', '') + SourceTableColumn
        ,@TargetTableColumns = isnull(@TargetTableColumns + ',', '') + TargetTableColumn
        ,@DefaultTableColumn = isnull(@DefaultTableColumn + ',', '') + DefaultTableColumn
FROM (

SELECT  
        JSON_VALUE(JsonMapping, '$.V[0]') As SourceTableColumn,
        JSON_VALUE(JsonMapping, '$.V[1]') As TargetTableColumn,
        NULLIF(JSON_VALUE(JsonMapping, '$.V[2]'), '') As DefaultTableColumn
    FROM String_split(@Mapping, ';')
    CROSS APPLY
    (
        SELECT '{"V":["' + REPLACE([value], '|', '", "') +'"]}' As JsonMapping
    ) JsonData

    ) a

print 'Mapping: ' + @Mapping
print 'Source: ' + @SourceTableColumns
print 'Target: ' + @TargetTableColumns
print 'Default: ' + @DefaultTableColumn

以下是我得到的结果:

Mapping: PriceSrc|PriceTrg|0;CurrencySrc|CurrencyTrg|0;ProductSrc|ProductTrg|
Source: PriceSrc,CurrencySrc,ProductSrc
Target: PriceTrg,CurrencyTrg,ProductTrg

我没有得到正确的结果,因为我获得了DefaultTableColumn的所有NULL。

@DefaultTableColumn的期望值为0,0,

问候,肖恩

tsql parsing replace sql-server-2017 isnullorempty
1个回答
2
投票

首先,自2016年版本以来,SQL Server内置了string_splitout-performs any user-defined function.功能

其次,我可能会使用replace从字符串生成一个json数组,然后使用json_value来获取值:

DECLARE @Mapping NVARCHAR(max) = 'PriceSrc|PriceTrg|0;CurrencySrc|CurrencyTrg|0;ProductSrc|ProductTrg|'


SELECT  JSON_VALUE(JsonMapping, '$.V[0]') As SourceColumn,
        JSON_VALUE(JsonMapping, '$.V[1]') As TargetColumn,
        -- json_value returns an empty string if no value found, nullif converts it to a null
        NULLIF(JSON_VALUE(JsonMapping, '$.V[2]'), '') As DefaultValue
FROM string_split(@Mapping, ';')
CROSS APPLY
(
    SELECT '{"V":["' + REPLACE([value], '|', '", "') +'"]}' As JsonMapping
) As JsonData

结果:(请注意,缺少最后一个默认值)

SourceColumn    TargetColumn    DefaultValue
PriceSrc        PriceTrg        0
CurrencySrc     CurrencyTrg     0
ProductSrc      ProductTrg      NULL

更新 要将结果转换为变量,您可以使用另一个名为string_agg的内置函数(自2017版本起):

DECLARE @Mapping NVARCHAR(max) = 'PriceSrc|PriceTrg|0;CurrencySrc|CurrencyTrg|0;ProductSrc|ProductTrg|',
        @SourceTableColumns NVARCHAR(max),
        @TargetTableColumns NVARCHAR(max),
        @DefaultTableColumn NVARCHAR(max)

SELECT   @SourceTableColumns = STRING_AGG(JSON_VALUE(JsonMapping, '$.V[0]'), ',')
        ,@TargetTableColumns = STRING_AGG(JSON_VALUE(JsonMapping, '$.V[1]'), ',')
        ,@DefaultTableColumn = STRING_AGG(NULLIF(JSON_VALUE(JsonMapping, '$.V[2]'), ''), ',')
FROM String_split(@Mapping, ';')
CROSS APPLY
(
    SELECT '{"V":["' + REPLACE([value], '|', '", "') +'"]}' As JsonMapping
) As JsonData

print 'Mapping: ' + @Mapping
print 'Source: ' + @SourceTableColumns
print 'Target: ' + @TargetTableColumns
print 'Default: ' + @DefaultTableColumn

你可以在db<>fiddle上看到现场演示

© www.soinside.com 2019 - 2024. All rights reserved.