Sql server 用于分析字符串的存储过程
我需要编写一个输入为字符串的存储过程 输入字符串包含由管道分隔符分隔的变量名及其值,如下所示:Sql server 用于分析字符串的存储过程,sql-server,sql-server-2008,sql-server-2005,stored-procedures,Sql Server,Sql Server 2008,Sql Server 2005,Stored Procedures,我需要编写一个输入为字符串的存储过程 输入字符串包含由管道分隔符分隔的变量名及其值,如下所示: Name =Praveen | City=Hyderabad | Mobile=48629387429| Role=User| etc 在存储过程中,我声明了变量,如@x、@y、@z、@t,以获得如下值: @x=Praveen (Name value) @y=Hyderabad (City Value) @z=48629387429(Mobile Value) @t=User(Role Value)
Name =Praveen | City=Hyderabad | Mobile=48629387429| Role=User| etc
在存储过程中,我声明了变量,如@x、@y、@z、@t
,以获得如下值:
@x=Praveen (Name value)
@y=Hyderabad (City Value)
@z=48629387429(Mobile Value)
@t=User(Role Value)
此外,输入字符串可以具有任意顺序的值,如
City=Hyderabad | Mobile=48629387429 | Role=User | Name =Praveen |etc
一旦我将这些值解析为@x、@y、@z、@t
等,我就必须在存储过程中使用这些值
请告诉我如何解析输入字符串,以将
Name、City、Mobile、Role
的值分别解析为@x、@y、@z
和@t
。假设输入参数为@Text
DECLARE @Text varchar(255),
@x varchar(255)
SET @Text = 'Name=Praveen | City=Hyderabad | Mobile=48629387429| Role=User'
-- Added to show how to account for non-trailing |
SET @Text = @Text + ' | ';
SET @x = LTRIM(RTRIM(substring(
@Text,
charindex('Name=', @Text) + LEN('Name='),
charindex(' | ', @Text, charindex('Name=', @Text)) - LEN('Name=')
)))
SELECT @x
然后对@y、@z、@t将Name=更改为您的断点所在的任何位置重复此操作。假设您的输入参数名为@Text
DECLARE @Text varchar(255),
@x varchar(255)
SET @Text = 'Name=Praveen | City=Hyderabad | Mobile=48629387429| Role=User'
-- Added to show how to account for non-trailing |
SET @Text = @Text + ' | ';
SET @x = LTRIM(RTRIM(substring(
@Text,
charindex('Name=', @Text) + LEN('Name='),
charindex(' | ', @Text, charindex('Name=', @Text)) - LEN('Name=')
)))
SELECT @x
然后对@y、@z、@t change Name=重复这一点,无论您的中断是什么。我绝对建议您在程序端而不是数据端进行字符串解析。也就是说,如果你一定要这样做,你可以尝试做类似的事情:
DECLARE @String [nvarchar](256) = 'Name=Praveen | City=Hyderabad | Mobile=48629387429 | Role=User |'
DECLARE @name [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('Name=', @String)+5, CHARINDEX('|', @String)))
DECLARE @city [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('City=', @String)+5, CHARINDEX('|', @String)))
DECLARE @mobile [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('Mobile=', @String)+7, CHARINDEX('|', @String)))
DECLARE @role [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('Role=', @String)+5, CHARINDEX('|', @String)))
SELECT RTRIM(LTRIM(LEFT(@name, CHARINDEX('|', @name)-1))) AS Name,
RTRIM(LTRIM(LEFT(@city, CHARINDEX('|', @city)-1))) AS City,
RTRIM(LTRIM(LEFT(@mobile, CHARINDEX('|', @mobile)-1))) AS Mobile,
RTRIM(LTRIM(LEFT(@role, CHARINDEX('|', @role)-1))) AS Role
这将返回:
Name | City | Mobile | Role
________________________________________________
Praveen | Hyderabad | 48629387429 | User
请注意,初始查询中从CHARINDEX
添加的长度等于搜索字符串
“Name=”等于5个字符,因此我们添加5以将索引移过=号,
“Mobile=”等于7,因此我们加上7
类似地,在最后的SELECT
query中,我们从每个CHARINDEX
中减去1以删除|符号
资料来源:
我绝对建议您在程序端而不是数据端进行字符串解析。也就是说,如果你一定要这样做,你可以尝试做类似的事情:
DECLARE @String [nvarchar](256) = 'Name=Praveen | City=Hyderabad | Mobile=48629387429 | Role=User |'
DECLARE @name [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('Name=', @String)+5, CHARINDEX('|', @String)))
DECLARE @city [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('City=', @String)+5, CHARINDEX('|', @String)))
DECLARE @mobile [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('Mobile=', @String)+7, CHARINDEX('|', @String)))
DECLARE @role [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('Role=', @String)+5, CHARINDEX('|', @String)))
SELECT RTRIM(LTRIM(LEFT(@name, CHARINDEX('|', @name)-1))) AS Name,
RTRIM(LTRIM(LEFT(@city, CHARINDEX('|', @city)-1))) AS City,
RTRIM(LTRIM(LEFT(@mobile, CHARINDEX('|', @mobile)-1))) AS Mobile,
RTRIM(LTRIM(LEFT(@role, CHARINDEX('|', @role)-1))) AS Role
这将返回:
Name | City | Mobile | Role
________________________________________________
Praveen | Hyderabad | 48629387429 | User
请注意,初始查询中从CHARINDEX
添加的长度等于搜索字符串
“Name=”等于5个字符,因此我们添加5以将索引移过=号,
“Mobile=”等于7,因此我们加上7
类似地,在最后的SELECT
query中,我们从每个CHARINDEX
中减去1以删除|符号
资料来源:
一种可能的解决方案是使用XML
DECLARE @text VARCHAR(1000)
,@xml xml
SELECT @text = 'City=Hyderabad | Mobile=48629387429 | Role=User | Name =Praveen'
SELECT @text = REPLACE(@text,'|','"')
,@text = REPLACE(@text,'=','="')
,@text = '<row ' + @text + '"/>'
SELECT @xml = CAST(@text AS XML)
select
line.col.value('@Name[1]', 'varchar(100)') AS Name
,line.col.value('@City[1]', 'varchar(100)') AS City
,line.col.value('@Mobile[1]', 'varchar(100)') AS Mobile
,line.col.value('@Role[1]', 'varchar(100)') AS Role
FROM @xml.nodes('/row') AS line(col)
DECLARE@text VARCHAR(1000)
,@xml
选择@text='City=hydrabad | Mobile=48629387429 | Role=User | Name=Praveen'
选择@text=REPLACE(@text,“|”和“”)
,@text=REPLACE(@text,“=”,“=”)
,@text='一种可能的解决方案是使用XML
DECLARE @text VARCHAR(1000)
,@xml xml
SELECT @text = 'City=Hyderabad | Mobile=48629387429 | Role=User | Name =Praveen'
SELECT @text = REPLACE(@text,'|','"')
,@text = REPLACE(@text,'=','="')
,@text = '<row ' + @text + '"/>'
SELECT @xml = CAST(@text AS XML)
select
line.col.value('@Name[1]', 'varchar(100)') AS Name
,line.col.value('@City[1]', 'varchar(100)') AS City
,line.col.value('@Mobile[1]', 'varchar(100)') AS Mobile
,line.col.value('@Role[1]', 'varchar(100)') AS Role
FROM @xml.nodes('/row') AS line(col)
DECLARE@text VARCHAR(1000)
,@xml
选择@text='City=hydrabad | Mobile=48629387429 | Role=User | Name=Praveen'
选择@text=REPLACE(@text,“|”和“”)
,@text=REPLACE(@text,“=”,“=”)
,@text='下面是一个使用循环进行字符串操作的有趣方法。请注意,我们是如何定义@x、@y等变量来获取特定值的
-- Simulate proc parameter
declare @input nvarchar(max) = 'Name =Praveen | City=Hyderabad | Mobile=48629387429| Role=User'
-- OP's preferred destination vars
declare @x nvarchar(max) = 'Name'
declare @y nvarchar(max) = 'City'
declare @z nvarchar(max) = 'Mobile'
declare @t nvarchar(max) = 'Role'
-- The key/value delimiters we are expecting
declare @recordDelim nchar(1) = '|'
declare @valueDelim nchar(1) = '='
-- Temp storage
declare @inputTable table (
name nvarchar(128) not null primary key
, value nvarchar(max) null
)
-- Get all key/value pairs
while ltrim(rtrim(@input)) != '' begin
insert into @inputTable (name) select ltrim(rtrim(replace(left(@input, isnull(nullif(charindex(@recordDelim, @input), 0), len(@input))), @recordDelim, '')))
select @input = ltrim(rtrim(right(@input, len(@input) - isnull(nullif(charindex(@recordDelim, @input), 0), len(@input)))))
end
-- Separate keys and values
update @inputTable
set name = ltrim(rtrim(left(name, isnull(nullif(charindex(@valueDelim, name) - 1, 0), len(name)))))
, value = ltrim(rtrim(right(name, len(name) - isnull(nullif(charindex(@valueDelim, name), 0), len(name)))))
-- Populate the variables
-- If any are null, then this key/value wasn't present
set @x = (select value from @inputTable where name = @x)
set @y = (select value from @inputTable where name = @y)
set @z = (select value from @inputTable where name = @z)
set @t = (select value from @inputTable where name = @t)
另外,从输入中不规则的间距来看,我猜您希望修剪所有输入的内容(这就是为什么这个过程会到处这样做)。这里有一个有趣的方法,使用循环进行字符串操作。请注意,我们是如何定义@x、@y等变量来获取特定值的
-- Simulate proc parameter
declare @input nvarchar(max) = 'Name =Praveen | City=Hyderabad | Mobile=48629387429| Role=User'
-- OP's preferred destination vars
declare @x nvarchar(max) = 'Name'
declare @y nvarchar(max) = 'City'
declare @z nvarchar(max) = 'Mobile'
declare @t nvarchar(max) = 'Role'
-- The key/value delimiters we are expecting
declare @recordDelim nchar(1) = '|'
declare @valueDelim nchar(1) = '='
-- Temp storage
declare @inputTable table (
name nvarchar(128) not null primary key
, value nvarchar(max) null
)
-- Get all key/value pairs
while ltrim(rtrim(@input)) != '' begin
insert into @inputTable (name) select ltrim(rtrim(replace(left(@input, isnull(nullif(charindex(@recordDelim, @input), 0), len(@input))), @recordDelim, '')))
select @input = ltrim(rtrim(right(@input, len(@input) - isnull(nullif(charindex(@recordDelim, @input), 0), len(@input)))))
end
-- Separate keys and values
update @inputTable
set name = ltrim(rtrim(left(name, isnull(nullif(charindex(@valueDelim, name) - 1, 0), len(name)))))
, value = ltrim(rtrim(right(name, len(name) - isnull(nullif(charindex(@valueDelim, name), 0), len(name)))))
-- Populate the variables
-- If any are null, then this key/value wasn't present
set @x = (select value from @inputTable where name = @x)
set @y = (select value from @inputTable where name = @y)
set @z = (select value from @inputTable where name = @z)
set @t = (select value from @inputTable where name = @t)
另外,从输入中不规则的间距来看,我猜您希望修剪所有输入的内容(这就是为什么这个过程会这样做的原因)。使用4个参数比使用1要容易得多。我尝试使用CHARINDEX等函数解析字符串,子字符串,但无法理解逻辑。使用4个参数而不是1会容易得多。我曾尝试使用CHARINDEX等函数解析字符串,子字符串,但无法理解逻辑。嗨,jon3laze,非常感谢您的解决方案!在输入字符串中,最后一个参数不是以|例如:'Name=Praveen | City=hydrabad | Mobile=48629387429 | Role=User'结尾。在这种情况下,最后一个参数的代码失败。因为字符串中最后一个变量没有| delimter。我们怎么处理呢?嗨,jon3laze,非常感谢你的解决方案!在输入字符串中,最后一个参数不是以|例如:'Name=Praveen | City=hydrabad | Mobile=48629387429 | Role=User'结尾。在这种情况下,最后一个参数的代码失败。因为字符串中最后一个变量没有| delimter。我们如何处理这个问题?嗨,Michael,谢谢你在输入字符串中给出的解决方案,最后一个参数不是以|例如:'Name=Praveen | City=hydrabad | Mobile=48629387429 | Role=User'结尾。在这种情况下,最后一个参数的代码失败。因为字符串中最后一个变量没有| delimter。我们如何处理这个问题?嗨,Michael,谢谢你在输入字符串中给出的解决方案,最后一个参数不是以|例如:'Name=Praveen | City=hydrabad | Mobile=48629387429 | Role=User'结尾。在这种情况下,最后一个参数的代码失败。因为字符串中最后一个变量没有| delimter。我们如何处理这个问题?+1。XML是将一串键/值对传递给SQL Server的更干净的方法之一。为什么每个人都会在恰好支持XML的关系数据库中转换为XML?对我来说,这是一个相当简单的解决方案,理想情况下,您的关系数据库不应该被迫这样做。@EricZ:这个解决方案是否考虑到内存消耗?您建议对大型数据集使用它吗?在将字符串转换为XML之前,请确保转义可能的XML字符,例如“@text=REPLACE(@text,&,“&;”)”+1。XML是将一串键/值对传递给SQL Server的更干净的方法之一。为什么每个人都会在恰好支持XML的关系数据库中转换为XML?对我来说,这是一个相当简单的解决方案,理想情况下,您的关系数据库不应该被迫这样做。@EricZ:这个解决方案是否考虑到内存消耗?您建议对大型数据集使用它吗?当然可以