Decodifica URL di SQL Server
-
26-09-2019 - |
Domanda
Devo eseguire una query su un tavolo legacy che memorizza il testo codificato URL. Ho bisogno che questo testo sia decodificato nei miei risultati. Come posso raggiungere questo obiettivo?
Soluzione
Prova uno di questi:
CREATE FUNCTION dbo.UrlDecode(@url varchar(3072))
RETURNS varchar(3072)
AS
BEGIN
DECLARE @count int, @c char(1), @cenc char(2), @i int, @urlReturn varchar(3072)
SET @count = Len(@url)
SET @i = 1
SET @urlReturn = ''
WHILE (@i <= @count)
BEGIN
SET @c = substring(@url, @i, 1)
IF @c LIKE '[!%]' ESCAPE '!'
BEGIN
SET @cenc = substring(@url, @i + 1, 2)
SET @c = CHAR(CASE WHEN SUBSTRING(@cenc, 1, 1) LIKE '[0-9]'
THEN CAST(SUBSTRING(@cenc, 1, 1) as int)
ELSE CAST(ASCII(UPPER(SUBSTRING(@cenc, 1, 1)))-55 as int)
END * 16 +
CASE WHEN SUBSTRING(@cenc, 2, 1) LIKE '[0-9]'
THEN CAST(SUBSTRING(@cenc, 2, 1) as int)
ELSE CAST(ASCII(UPPER(SUBSTRING(@cenc, 2, 1)))-55 as int)
END)
SET @urlReturn = @urlReturn + @c
SET @i = @i + 2
END
ELSE
BEGIN
SET @urlReturn = @urlReturn + @c
END
SET @i = @i +1
END
RETURN @urlReturn
END
GO
da http://sqlblog.com/blogs/peter_debetta/archive/2007/03/09/t-sql-urldecode.aspx
CREATE FUNCTION dbo.fnDeURL
(
@URL VARCHAR(8000)
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @Position INT,
@Base CHAR(16),
@High TINYINT,
@Low TINYINT,
@Pattern CHAR(21)
SELECT @Base = '0123456789abcdef',
@Pattern = '%[%][0-9a-f][0-9a-f]%',
@URL = REPLACE(@URL, '+', ' '),
@Position = PATINDEX(@Pattern, @URL)
WHILE @Position > 0
SELECT @High = CHARINDEX(SUBSTRING(@URL, @Position + 1, 1), @Base COLLATE Latin1_General_CI_AS),
@Low = CHARINDEX(SUBSTRING(@URL, @Position + 2, 1), @Base COLLATE Latin1_General_CI_AS),
@URL = STUFF(@URL, @Position, 3, CHAR(16 * @High + @Low - 17)),
@Position = PATINDEX(@Pattern, @URL)
RETURN @URL
END
Altri suggerimenti
create function [dbo].[URLDecode](
@str nvarchar( max )
) returns nvarchar( max )
begin
if @str is null return null
declare @out nvarchar( max ) = N''
set @str = replace( @str, N'+', N'%20' )
while len(@str) > 0
begin
declare @i bigint = patindex( N'%[%][0-9a-fA-F][0-9a-fA-F]%', @str )
if @i = 0 break
set @out = @out + substring( @str, 0, @i ) + convert( nchar(2), convert( varbinary, '0x' + substring( @str, @i + 1, 2 ), 1 ) )
set @str = substring( @str, @i + 3, len(@str) )
end
return @out + @str
end
Se hai bisogno di una soluzione che supporti i caratteri non inglesi (Unicode), c'è un esempio eccellente su CodeProject:
CREATE FUNCTION [dbo].[UrlDecode] (
@URL NVARCHAR(4000) ) RETURNS NVARCHAR(4000) AS BEGIN
DECLARE @Position INT, @Base CHAR(16), @High TINYINT, @Low TINYINT, @Pattern CHAR(21)
DECLARE @Byte1Value INT, @SurrogateHign INT, @SurrogateLow INT
SELECT @Pattern = '%[%][0-9a-f][0-9a-f]%', @Position = PATINDEX(@Pattern, @URL)
WHILE @Position > 0
BEGIN
SELECT @High = ASCII(UPPER(SUBSTRING(@URL, @Position + 1, 1))) - 48,
@Low = ASCII(UPPER(SUBSTRING(@URL, @Position + 2, 1))) - 48,
@High = @High / 17 * 10 + @High % 17,
@Low = @Low / 17 * 10 + @Low % 17,
@Byte1Value = 16 * @High + @Low
IF @Byte1Value < 128 --1-byte UTF-8
SELECT @URL = STUFF(@URL, @Position, 3, NCHAR(@Byte1Value)),
@Position = PATINDEX(@Pattern, @URL)
ELSE IF @Byte1Value >= 192 AND @Byte1Value < 224 AND @Position > 0 --2-byte UTF-8
BEGIN
SELECT @Byte1Value = (@Byte1Value & (POWER(2,5) - 1)) * POWER(2,6),
@URL = STUFF(@URL, @Position, 3, ''),
@Position = PATINDEX(@Pattern, @URL)
IF @Position > 0
SELECT @High = ASCII(UPPER(SUBSTRING(@URL, @Position + 1, 1))) - 48,
@Low = ASCII(UPPER(SUBSTRING(@URL, @Position + 2, 1))) - 48,
@High = @High / 17 * 10 + @High % 17,
@Low = @Low / 17 * 10 + @Low % 17,
@Byte1Value = @Byte1Value + ((16 * @High + @Low) & (POWER(2,6) - 1)),
@URL = STUFF(@URL, @Position, 3, NCHAR(@Byte1Value)),
@Position = PATINDEX(@Pattern, @URL)
END
ELSE IF @Byte1Value >= 224 AND @Byte1Value < 240 AND @Position > 0 --3-byte UTF-8
BEGIN
SELECT @Byte1Value = (@Byte1Value & (POWER(2,4) - 1)) * POWER(2,12),
@URL = STUFF(@URL, @Position, 3, ''),
@Position = PATINDEX(@Pattern, @URL)
IF @Position > 0
SELECT @High = ASCII(UPPER(SUBSTRING(@URL, @Position + 1, 1))) - 48,
@Low = ASCII(UPPER(SUBSTRING(@URL, @Position + 2, 1))) - 48,
@High = @High / 17 * 10 + @High % 17,
@Low = @Low / 17 * 10 + @Low % 17,
@Byte1Value = @Byte1Value + ((16 * @High + @Low) & (POWER(2,6) - 1)) * POWER(2,6),
@URL = STUFF(@URL, @Position, 3, ''),
@Position = PATINDEX(@Pattern, @URL)
IF @Position > 0
SELECT @High = ASCII(UPPER(SUBSTRING(@URL, @Position + 1, 1))) - 48,
@Low = ASCII(UPPER(SUBSTRING(@URL, @Position + 2, 1))) - 48,
@High = @High / 17 * 10 + @High % 17,
@Low = @Low / 17 * 10 + @Low % 17,
@Byte1Value = @Byte1Value + ((16 * @High + @Low) & (POWER(2,6) - 1)),
@URL = STUFF(@URL, @Position, 3, NCHAR(@Byte1Value)),
@Position = PATINDEX(@Pattern, @URL)
END
ELSE IF @Byte1Value >= 240 AND @Position > 0 --4-byte UTF-8
BEGIN
SELECT @Byte1Value = (@Byte1Value & (POWER(2,3) - 1)) * POWER(2,18),
@URL = STUFF(@URL, @Position, 3, ''),
@Position = PATINDEX(@Pattern, @URL)
IF @Position > 0
SELECT @High = ASCII(UPPER(SUBSTRING(@URL, @Position + 1, 1))) - 48,
@Low = ASCII(UPPER(SUBSTRING(@URL, @Position + 2, 1))) - 48,
@High = @High / 17 * 10 + @High % 17,
@Low = @Low / 17 * 10 + @Low % 17,
@Byte1Value = @Byte1Value + ((16 * @High + @Low) & (POWER(2,6) - 1)) * POWER(2,12),
@URL = STUFF(@URL, @Position, 3, ''),
@Position = PATINDEX(@Pattern, @URL)
IF @Position > 0
SELECT @High = ASCII(UPPER(SUBSTRING(@URL, @Position + 1, 1))) - 48,
@Low = ASCII(UPPER(SUBSTRING(@URL, @Position + 2, 1))) - 48,
@High = @High / 17 * 10 + @High % 17,
@Low = @Low / 17 * 10 + @Low % 17,
@Byte1Value = @Byte1Value + ((16 * @High + @Low) & (POWER(2,6) - 1)) * POWER(2,6),
@URL = STUFF(@URL, @Position, 3, ''),
@Position = PATINDEX(@Pattern, @URL)
IF @Position > 0
BEGIN
SELECT @High = ASCII(UPPER(SUBSTRING(@URL, @Position + 1, 1))) - 48,
@Low = ASCII(UPPER(SUBSTRING(@URL, @Position + 2, 1))) - 48,
@High = @High / 17 * 10 + @High % 17,
@Low = @Low / 17 * 10 + @Low % 17,
@Byte1Value = @Byte1Value + ((16 * @High + @Low) & (POWER(2,6) - 1))
--,@URL = STUFF(@URL, @Position, 3, cast(@Byte1Value as varchar))
--,@Position = PATINDEX(@Pattern, @URL)
SELECT @SurrogateHign = ((@Byte1Value - POWER(16,4)) & (POWER(2,20) - 1)) / POWER(2,10) + 13 * POWER(16,3) + 8 * POWER(16,2),
@SurrogateLow = ((@Byte1Value - POWER(16,4)) & (POWER(2,10) - 1)) + 13 * POWER(16,3) + 12 * POWER(16,2),
@URL = STUFF(@URL, @Position, 3, NCHAR(@SurrogateHign) + NCHAR(@SurrogateLow)),
@Position = PATINDEX(@Pattern, @URL)
END
END
END
RETURN REPLACE(@URL, '+', ' ') END
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow