none
Dúvida para criar função RRS feed

  • Pergunta

  • Olá pessoal, estou com um problema para resolver que é o seguinte. Preciso pegar um campo da minha tabela que está em hexadecimal, inverter a string hexadecimal (por ex: ser for A1B2 tenho que passar para B2A1) e depois converter para decimal. Gostaria de deixar essa função pronta no meu server e sempre que eu precisar usá-la ela estará disponível. O problema é que não sei se há essa possibilidade de criar esse tipo de função diretamente no banco de dados. A idéia é quando eu criar minha view ou simplesmente dar um select essa coluna que originalmente é em hexadecimal eu já fazer a conversão no momento da execução do comando select ou create view. Isso é possível? Grato.
    sexta-feira, 4 de maio de 2012 15:33

Respostas

  • Ola Osmar,

    Se vc ja tem o algoritmo pronto, vc pode optar por criar um SQL Server CLR Procedure, ou seja, uma stored procedure dentro do SQL Server que roda um código em .Net. Ai, vc poderia chamar essa funcao passando a coluna como parametro e fazendo que ele retorne o valor que vc quer. A vantagem é que a sua necessidade é relativamente complexa para se fazer em T-SQL ou DML, gerando queries relativamente complexas / pesadas. Alem disso, vc ja possui o algoritmo pronto (e suponho que tambem posua um codigo tipo C# com esse algoritmo implementado).

    Para ilustrar a sugestao, segue o exemplo retirado de "How to: Create and Run a SQL Server User-Defined Function by using Common Language Run-time Integration" (http://msdn.microsoft.com/en-us/library/w2kae45k(v=vs.100).aspx ):

    1. Criacao do codigo C# com sua logica:

    using System.Data.SqlTypes;
    using Microsoft.SqlServer.Server;

    public partial class UserDefinedFunctions
    {
        public const double SALES_TAX = .086;

        [SqlFunction()]
        public static SqlDouble addTax(SqlDouble originalAmount)
        {
            SqlDouble taxAmount = originalAmount * SALES_TAX;

            return originalAmount + taxAmount;
        }
    }
    2. Fazer o deploy do codigo no SQL Server (Ver http://msdn.microsoft.com/en-us/library/dahcx0ww.aspx )

    3. Utilizar em queries:

    SELECT dbo.addTax(10)

    Outro artigo interessante é o "Introduction to SQL Server CLR Integration (ADO.NET)" (http://msdn.microsoft.com/en-us/library/ms254498(v=vs.100).aspx )

    Abracos, Daniel.


    -- Se minha sugestão ajudou, por favor marque-a como útil; Se resolveu a questão, por favor marque-a como resposta. Contribua para melhorar o fórum! | daniel@dimamura.com.br

    sábado, 5 de maio de 2012 04:10
  • Osmar,

    Peguei a ideia do Thiago e realizei algumas alterações, veja este outro exemplo:

    declare @hexstring as varchar(max)
    set @hexstring = 'B2A1'
    --Invertendo a posição da String
    set @hexstring = Reverse(@hexstring)
    Select @hexstring
    -- Realizando a conversão da expressão para Inteiro com base na conversão em Hexadecimal
    Select Convert(Int,Convert(varbinary(max), @hexstring))


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]

    • Sugerido como Resposta Heloisa Pires quarta-feira, 6 de junho de 2012 13:52
    • Marcado como Resposta Heloisa Pires sexta-feira, 15 de junho de 2012 15:05
    segunda-feira, 7 de maio de 2012 17:04

Todas as Respostas

  • Depende, no banco de dados o A1B2 está gravado como hexadecimal (varbinary) ou como varchar? qual o tipo do campo?



    thiagokoelho

    sexta-feira, 4 de maio de 2012 16:43
  • Fiz um negócio aqui que poderá te ajudar, dê uma olhada:

    declare @hexstring as varchar(max)
    set @hexstring = 'B2A1'
    
    --INVERTE A STRING HEXA
    set @hexstring = REVERSE(@hexstring)
    
    --CONVERTE PARA HEX e DEPOIS PARA INTEIRO
    select CONVERT(INT, (select cast('' as xml).value('xs:hexBinary(substring(sql:variable("@hexstring"), sql:column("t.pos")) )', 'varbinary(max)')
    from (select case substring(@hexstring, 1, 2) when '0x' then 3 else 0 end) as t(pos)))

    Espero ter ajudado, abraços!


    thiagokoelho

    sexta-feira, 4 de maio de 2012 17:10
  • Obrigado, vou dar uma estudada mas a função REVERSE nesse caso inverteria de "B21A" para "A1B2", no entanto eu preciso que seja "1A2B". Para isso eu tenho o algoritmo pronto eu só precisaria saber implementá-lo em sql. O restante de sintaxe eu não entendi ainda pois meu conhecimento de sql está entre o básico e o intermediário.

    sexta-feira, 4 de maio de 2012 20:25
  • Ola Osmar,

    Se vc ja tem o algoritmo pronto, vc pode optar por criar um SQL Server CLR Procedure, ou seja, uma stored procedure dentro do SQL Server que roda um código em .Net. Ai, vc poderia chamar essa funcao passando a coluna como parametro e fazendo que ele retorne o valor que vc quer. A vantagem é que a sua necessidade é relativamente complexa para se fazer em T-SQL ou DML, gerando queries relativamente complexas / pesadas. Alem disso, vc ja possui o algoritmo pronto (e suponho que tambem posua um codigo tipo C# com esse algoritmo implementado).

    Para ilustrar a sugestao, segue o exemplo retirado de "How to: Create and Run a SQL Server User-Defined Function by using Common Language Run-time Integration" (http://msdn.microsoft.com/en-us/library/w2kae45k(v=vs.100).aspx ):

    1. Criacao do codigo C# com sua logica:

    using System.Data.SqlTypes;
    using Microsoft.SqlServer.Server;

    public partial class UserDefinedFunctions
    {
        public const double SALES_TAX = .086;

        [SqlFunction()]
        public static SqlDouble addTax(SqlDouble originalAmount)
        {
            SqlDouble taxAmount = originalAmount * SALES_TAX;

            return originalAmount + taxAmount;
        }
    }
    2. Fazer o deploy do codigo no SQL Server (Ver http://msdn.microsoft.com/en-us/library/dahcx0ww.aspx )

    3. Utilizar em queries:

    SELECT dbo.addTax(10)

    Outro artigo interessante é o "Introduction to SQL Server CLR Integration (ADO.NET)" (http://msdn.microsoft.com/en-us/library/ms254498(v=vs.100).aspx )

    Abracos, Daniel.


    -- Se minha sugestão ajudou, por favor marque-a como útil; Se resolveu a questão, por favor marque-a como resposta. Contribua para melhorar o fórum! | daniel@dimamura.com.br

    sábado, 5 de maio de 2012 04:10
  • Osmar,

    Peguei a ideia do Thiago e realizei algumas alterações, veja este outro exemplo:

    declare @hexstring as varchar(max)
    set @hexstring = 'B2A1'
    --Invertendo a posição da String
    set @hexstring = Reverse(@hexstring)
    Select @hexstring
    -- Realizando a conversão da expressão para Inteiro com base na conversão em Hexadecimal
    Select Convert(Int,Convert(varbinary(max), @hexstring))


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]

    • Sugerido como Resposta Heloisa Pires quarta-feira, 6 de junho de 2012 13:52
    • Marcado como Resposta Heloisa Pires sexta-feira, 15 de junho de 2012 15:05
    segunda-feira, 7 de maio de 2012 17:04
  • Olá Osmar,

    Você teve algum progresso nessa questão?

    Conseguiu realizar testes com as queries enviadas?



    Heloisa Pires | LATAM Forum Support Engineer | Microsoft Corporation

    quarta-feira, 6 de junho de 2012 13:52
  • Bem, 

    se você ainda não conseguiu resolver, adaptei uma função de conversão para inverter corretamente teu decimal e ficou assim.

    ALTER FUNCTION Fn_hextointnt(@str VARCHAR(16)) 
    returns BIGINT 
    AS 
      BEGIN 
          DECLARE @cont    INT, 
                  @hexpart CHAR(2), 
                  @hexfin  VARCHAR(16), 
                  @i       INT, 
                  @len     INT, 
                  @char    CHAR(1), 
                  @output  BIGINT 
    
          SELECT @cont = 0, 
                 @hexfin = '', 
                 @hexpart = '' 
    
          WHILE @cont <= (SELECT Len(@str) - 2) 
            BEGIN 
                SELECT @hexpart = Reverse(Substring(@str, 1 + @cont, 2)) 
    
                SET @hexfin = @hexfin + @hexpart 
                SET @cont = @cont + 2 
            END 
    
          SET @str = Reverse(@hexfin) 
    
          SELECT @str = Upper(@str) 
    
          SELECT @len = Len(@str), 
                 @i = @len, 
                 @output = CASE 
                             WHEN @len > 0 THEN 0 
                           END 
    
          WHILE ( @i > 0 ) 
            BEGIN 
                SELECT @char = Substring(@str, @i, 1), 
                       @output = @output + ( Ascii(@char) - ( CASE 
                                                                WHEN 
                                             @char BETWEEN 'A' AND 'F' 
                                                              THEN 55 
                                                                ELSE 
                                                                  CASE 
                                             WHEN @char BETWEEN 
                                                  '0' 
                                                  AND 
                                                  '9' THEN 
                                             48 
                                                                  END 
                                                              END ) ) * 
                                           Power(16., @len - @i), 
                       @i = @i - 1 
            END 
    
          RETURN @output 
      END 
    
    SELECT dbo.Fn_hextointnt('A1B2C3D4')

    Boa Sorte !


    Antero Marques


    • Editado Antero Marques quarta-feira, 6 de junho de 2012 15:48
    • Sugerido como Resposta Antero Marques quarta-feira, 6 de junho de 2012 15:48
    quarta-feira, 6 de junho de 2012 15:46