35.12. Conversão do Transact-SQL do SQL Server para o PL/pgSQL do PostgreSQL

Autor: Halley Pacheco de Oliveira ( ). Iniciado em 2007-02-26.

Transact-SQL é a linguagem que contém os comandos utilizados para administrar as instâncias do SQL Server, criar e gerenciar todos os objetos em uma instãncia do SQL Server, e para inserir, trazer, modificar e excluir todos os dados das tabelas do SQL Server. Transact-SQL é uma extensão da linguagem definida nos padrões SQL publicados pela International Standards Organization (ISO) e pela American National Standards Institute (ANSI) ( SQL Server 2005 Books Online — Glossary of Terms).

Transact-SQL é essencial para o SQL Server. Todos os aplicativos que se comunicam com uma instância do SQL Server o fazem enviando instruções Transact-SQL para o servidor, não importando a interface de usuário do aplicativo

O comando CREATE FUNCTION cria uma função definida pelo usuário. Esta é uma rotina Transact-SQL ou CLR (common language runtime) salva, que retorna um valor. As funções definidas pelo usuário não podem ser utilizadas para realizar ações que modificam o estado do banco de dados. As funções definidas pelo usuário, assim como as funções do sistema, podem ser chamadas de uma consulta. As funções escalares podem ser executadas utilizando a instrução EXECUTE, como os procedimentos armazenados.

Esta seção mostra, através de exemplos, a conversão de funções definidas pelo usuário escritas em Transact-SQL em funções escritas em PL/pgSQL, para ajudar aos desenvolvedores na conversão de aplicativos do SQL Server para o PostgreSQL.

No Transact-SQL a variável local é definida na instrução DECLARE @variável_local, e o valor atribuído através da instrução SET @variável_local. Também pode ser atribuído valor à variável local através da instrução SELECT @variável_local, mas não é recomendado. O nome da variável local sempre começa com o símbolo @ precedendo seu nome.

No PL/pgSQL todas as variáveis utilizadas em um bloco devem ser declaradas na seção de declarações do bloco (A única exceção é a variável de laço do FOR interagindo sobre um intervalo de valores inteiros, que é automaticamente declarada como sendo do tipo inteiro). Também pode ser atribuído valor a variável no momento de sua declaração, e não há nenhum caractere especial para indicar que a variável é local.

A Tabela 35-1 mostra os elementos da linguagem de controle de fluxo do Transact-SQL e os elementos equivalentes do PL/pgSQL.

Tabela 35-1. Controle de fluxo no Transact-SQL e no PL/pgSQL

Transact-SQL PL/pgSQL
BEGIN
    {
        instrução_sql | bloco_de_instruções
    }
END
[ <<rótulo>> ]
[ DECLARE
    declarações ]
BEGIN
    instruções
END;
BREAK
EXIT [ rótulo ] [ WHEN expressão ];
CONTINUE
 
rótulo:
GOTO rótulo
IF expressão_booleana
    { instrução_sql | bloco_de_instruções }
[ ELSE
    { instrução_sql | bloco_de_instruções } ]
IF expressão_booleana THEN
    instruções
[ ELSE
    instruções ]
END IF;

IF expressão_booleana THEN
    instruções
[ ELSIF expressão_booleana THEN
    instruções
[ ELSIF expressão_booleana THEN
    instruções
    ...]]
[ ELSE
    instruções ]
END IF;
...
RETURN expressão
RETURN expressão;
BEGIN TRY
    { instrução_sql | bloco_de_instruções }
END TRY
BEGIN CATCH
    { instrução_sql | bloco_de_instruções }
END CATCH
[ ; ]
[ <<rótulo>> ]
[ DECLARE
    declarações ]
BEGIN
    instruções
EXCEPTION
    WHEN condição [ OR condição ... ] THEN
        instruções_do_tratador
    [ WHEN condição [ OR condição ... ] THEN
          instruções_do_tratador
      ... ]
END;
WHILE expressão_booleana
    { instrução_sql | bloco_de_instruções }
    [ BREAK ]
    { instrução_sql | bloco_de_instruções }
    [ CONTINUE ]
    { instrução_sql | bloco_de_instruções }
[<<rótulo>>]
WHILE expressão LOOP
    instruções
END LOOP;

Exemplo 35-11. Função StrSeparate em Transact-SQL e PL/pgSQL

Neste exemplo a função StrSeparate, desenvolvida por Alexander Chigrik ( ) e publicada em String User-Defined Functions (UDF), é convertida de Transact-SQL para PL/pgSQL. A finalidade desta função é inserir um caractere em uma cadeia de caracteres após cada n caracteres (a partir o final da cadeia de caracteres).

Sinopse:

varchar(4000) StrSeparate(str varchar(4000), c varchar(1), n int);

onde str é a cadeia de caracteres onde o caractere c será inserido após cada n caracteres da direita para a esquerda.

Listagem da função em Transact-SQL:

CREATE FUNCTION StrSeparate
  ( @str varchar(4000),
    @c   varchar(1),
    @n   int )
RETURNS varchar(4000)
AS
BEGIN
  DECLARE @i int,    -- número do passo
          @j int,    -- posição para inserir o caractere
          @p int     -- número de passos
  IF (len(@str) <= @n) RETURN @str
  SET @str = REVERSE(@str)
  SET @i = 1
  SET @j = @n + 1
  SET @p = len(@str) / @n
  WHILE @i <= @p
    BEGIN
      SET @str = ISNULL(STUFF(@str, @j, 0, @c), @str)
      SET @j = @j + @n + 1
      SET @i = @i + 1
    END
  RETURN REVERSE(@str)
END

Listagem da função convertida para PL/pgSQL:

CREATE OR REPLACE FUNCTION REVERSE ( str text ) RETURNS text
AS $$
DECLARE
  s text := '';           -- cadeia de caracteres de trás para frente
  i int;                  -- posição do caractere
BEGIN
  IF (length(str) <= 1) THEN
    RETURN str;
  END IF;
  FOR i IN REVERSE length(str) .. 1 LOOP
    s := s || substr(str,i,1);
  END LOOP;
  RETURN s;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION StrSeparate
  ( str varchar(4000),
    c   varchar(1),
    n   int )
RETURNS varchar(4000)
AS $$
DECLARE
  p int;                  -- número de passos
  i int  := 1;            -- número do passo
  j int  := n + 1;        -- posição para inserir o caractere
  s text := REVERSE(str); -- cadeia de caracteres de trás para frente
BEGIN
  IF (length(str) <= n) THEN
    RETURN str;
  END IF;
  p := length(s) / n;
  WHILE i <= p LOOP
    s := COALESCE((substr(s, 1, j-1) || c || substr(s, j)),s);
    j := j + n + 1;
    i := i + 1;
  END LOOP;
  RETURN REVERSE(s);
END
$$ LANGUAGE plpgsql;

SELECT StrSeparate('12345678',' ',3);

 strseparate
-------------
 12 345 678

Devem ser observadas as seguintes diferenças entre a função StrSeparate escrita em Transact-SQL e sua versão escrita em PL/pgSQL:

SourceForge.net Logo CSS válido!