1

任何人都有一个 t-sql 函数,它从 url 获取查询字符串并返回名称/值对表?

例如,我的数据库中存储了这样的值:

foo=bar&baz=qux&x=y

我想生成一个 2 列(键和 val)表(在本例中为 3 行),如下所示:

name  | value
-------------
foo   | bar
baz   | qux
x     | y

更新:我在 t-sql 函数中需要这个是有原因的;我不能在应用程序代码中做到这一点。也许我可以在函数中使用 CLR 代码,但我不想这样做。

更新:“查询字符串”是指“?”之后的网址部分。我并不是说查询的一部分会在 url 中。查询字符串仅用作数据。

4

3 回答 3

3
create function dbo.fn_splitQuerystring(@querystring nvarchar(4000))
returns table 
as
/*
 * Splits a querystring-formatted string into a table of name-value pairs
 * Example Usage:
        select * from dbo.fn_splitQueryString('foo=bar&baz=qux&x=y&y&abc=')
 */
return ( 
    select  'name' = SUBSTRING(s,1,case when charindex('=',s)=0 then LEN(s) else charindex('=',s)-1 end) 
        ,   'value' = case when charindex('=',s)=0 then '' else SUBSTRING(s,charindex('=',s)+1,4000) end    
    from dbo.fn_split('&',@querystring)
)
go

它利用了这个通用的拆分功能:

create function dbo.fn_split(@sep nchar(1), @s nvarchar(4000))
returns table
/*
 * From https://stackoverflow.com/questions/314824/
 * Splits a string into a table of values, with single-char delimiter.
 * Example Usage:
        select * from dbo.fn_split(',', '1,2,5,2,,dggsfdsg,456,df,1,2,5,2,,dggsfdsg,456,df,1,2,5,2,,')
 */
AS
RETURN (
    WITH Pieces(pn, start, stop) AS (
      SELECT 1, 1, CHARINDEX(@sep, @s)
      UNION ALL
      SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
      FROM Pieces
      WHERE stop > 0
    )
    SELECT pn,
      SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 4000 END) AS s
    FROM Pieces
  )
go

最终让你做这样的事情:

select name, value
from dbo.fn_splitQuerystring('foo=bar&baz=something&x=y&y&abc=&=whatever')
于 2012-05-26T16:13:53.090 回答
1

我确信 TSQL 可能会被强制为您跳过这个环节,但为什么不在您的应用程序代码中解析它最可能属于的查询字符串呢?

然后,您可以查看此答案,了解其他人将查询字符串解析为名称/值对的方法。

还是这个答案

或者这个

或者这个

于 2009-04-16T12:10:58.710 回答
0

出于安全原因,请不要直接在 URL 中对查询字符串进行编码:任何人都可以轻松替换任何旧查询来访问他们不应该拥有的信息——或者更糟的是,“ DROP DATABASE;”。检查可疑的“关键字”或引用字符之类的东西不是解决方案——有创意的黑客会绕过这些措施,你会惹恼所有姓氏为“O'Reilly”的人。

例外情况:仅限内部服务器或公共httpsURL。但即便如此,您也没有理由不能在客户端构建 SQL 查询并从那里提交。

于 2009-04-16T12:11:38.223 回答