如何在丢失或不丢失时有条件地解析字符串中的默认值
How to conditionally parse a default value in a string when missing or not
我想有条件地确定字符串中是否有默认值(下面映射字符串中第三个值中的零)。
我有以下字符串:
'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
这是我的第三个默认值始终填充时的结果(映射字符串中第三个值中的零):
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|
请注意,默认值第 3 个参数的作用是作为覆盖值,供用户输入任何字符串或数值(如果他们愿意)。如果它为 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,
此致,
肖恩
首先,从 2016 版本开始,SQL 服务器内置了 string_split
function which out-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
上观看现场演示
我想有条件地确定字符串中是否有默认值(下面映射字符串中第三个值中的零)。
我有以下字符串:
'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
这是我的第三个默认值始终填充时的结果(映射字符串中第三个值中的零):
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|
请注意,默认值第 3 个参数的作用是作为覆盖值,供用户输入任何字符串或数值(如果他们愿意)。如果它为 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,
此致, 肖恩
首先,从 2016 版本开始,SQL 服务器内置了 string_split
function which out-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
:
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
上观看现场演示