29.6. Utilização de variáveis hospedeiras

Na Seção 29.4 foi visto como executar declarações SQL a partir de um programa com SQL incorporado. Algumas destas declarações utilizam apenas valores fixos, não possuindo uma maneira de inserir valores fornecidos pelo usuário na declaração, nem os programas processam os valores retornados pelas consultas. Este tipo de declaração, na verdade, não é útil em aplicativos reais. Esta seção explica em detalhe como passar dados entre o programa C e os comandos SQL incorporados, utilizando um mecanismo simples chamado variáveis hospedeiras.

29.6.1. Visão geral

A passagem de dados entre o programa C e as declarações SQL é particularmente simples no SQL incorporado. Em vez do programa colar os dados na declaração, que envolve várias dificuldades, como colocar o valor entre apóstrofos de forma apropriada, pode-se simplesmente escrever o nome da variável C, prefixada por dois-pontos, na declaração SQL. Por exemplo:

EXEC SQL INSERT INTO alguma_tabela VALUES (:v1, 'foo', :v2);

Esta declaração faz referência a duas variáveis C, chamadas v1 e v2, e também usa um literal cadeia de caracteres SQL regular, para mostrar que não fica restrito ao uso de um tipo de dado ou outro.

Esta forma de inserir variáveis C em declarações SQL funciona em qualquer lugar onde é esperada uma expressão de valor na declaração SQL. No ambiente SQL, as variáveis C referenciadas são chamadas de variáveis hospedeiras.

29.6.2. Seções de declaração

Para passar os dados do programa para o banco de dados, por exemplo como parâmetros de uma consulta, ou para passar os dados do banco de dados de volta para o programa C, as variáveis C utilizadas para armazenar estes dados precisam ser declaradas em seções marcadas de forma especial, para que o pré-processador de SQL incorporado tenha conhecimento destas variáveis.

Estas seções começam por

EXEC SQL BEGIN DECLARE SECTION;

e terminam por

EXEC SQL END DECLARE SECTION;

Entre estas duas linhas devem haver declarações normais de variáveis C, como:

int   x;
char  foo[16], bar[16];

Podem existir tantas seções de declaração no programas quantas forem desejadas.

As declarações também são reproduzidas no arquivo de saída como variáveis C normais, para que não seja necessário declará-las novamente. As variáveis que não são utilizadas nos comandos SQL podem ser declaradas normalmente fora destas seções especiais.

A definição das estruturas e das uniões também devem ser colocadas dentro da seção DECLARE, senão o pré-processador não pode tratar estes tipos, uma vez que não conhece as definições.

O tipo especial VARCHAR é convertido em uma struct com nome para todas as variáveis. Uma declaração como

VARCHAR var[180];

é convertida em

struct varchar_var { int len; char arr[180]; } var;

Esta estrutura é adequada para servir de interface para os dados do tipo varchar do SQL. [1]

29.6.3. Declarações SELECT INTO e FETCH INTO

Agora já se sabe como passar dados gerados pelo programa para o comando SQL, mas como fazer para trazer os resultados da consulta? Para esta finalidade o SQL incorporado disponibiliza duas variantes dos comandos usuais SELECT e FETCH. Estes comandos possuem uma cláusula especial INTO, que especifica em quais variáveis hospedeiras os valores trazidos são armazenados.

Abaixo segue um exemplo:

/*
 * assumindo a existência desta tabela:
 * CREATE TABLE test1 (a int, b varchar(50));
 */

EXEC SQL BEGIN DECLARE SECTION;
int v1;
VARCHAR v2;
EXEC SQL END DECLARE SECTION;

 ...

EXEC SQL SELECT a, b INTO :v1, :v2 FROM test1;

Portanto, a cláusula INTO aparece entre a lista de seleção e a cláusula FROM. O número de elementos da lista de seleção e da lista após a cláusula INTO, também chamada de lista de destino, devem ser iguais.

Abaixo segue um exemplo mostrando o comando FETCH:

EXEC SQL BEGIN DECLARE SECTION;
int v1;
VARCHAR v2;
EXEC SQL END DECLARE SECTION;

 ...

EXEC SQL DECLARE foo CURSOR FOR SELECT a, b FROM test1;

 ...

do {
    ...
    EXEC SQL FETCH NEXT FROM foo INTO :v1, :v2;
    ...
} while (...);

Aqui a cláusula INTO aparece após todas as cláusulas normais.

Este dois métodos só permitem trazer uma linha de cada vez. Se for necessário processar conjunto de resultados contendo potencialmente mais de uma linha, é necessário utilizar um cursor, conforme mostrado no segundo exemplo.

29.6.4. Indicadores

Os exemplos acima não tratam valores nulos. Na verdade, os exemplos de recuperação vão lançar um erro se trouxerem um valor nulo do banco de dados. Para ser possível passar valores nulos para o banco de dados, ou trazer valores nulos do banco de dados, é necessário anexar uma segunda variável hospedeira na especificação de cada variável hospedeira que contém dado. Esta segunda variável é chamada de indicadora, e contém um sinalizador para informar se o dado é nulo. Neste caso o valor da variável hospedeira real é ignorado. Abaixo está mostrado um exemplo que trata a recuperação de valores nulos de forma correta:

EXEC SQL BEGIN DECLARE SECTION;
int v1, ind1, ind2;
VARCHAR v2;
EXEC SQL END DECLARE SECTION;

 ...

EXEC SQL SELECT a, b INTO :v1 :ind1, :v2 :ind2 FROM test1;

A variável indicadora (ind1 ou ind2) será igual a zero quando o valor da coluna não for nulo, ou será negativa quando o valor da coluna for nulo. Deve ser observado que não há vírgula separando a variável hospedeira da variável indicadora. Não é necessário haver espaço entre a variável hospedeira e a variável indicadora.

O indicador possui outra função: se o valor do indicador for positivo, significa que o valor não é nulo, mas que foi truncado ao ser armazenado na variável hospedeira. [2] [3]

Notas

[1]

DB2 — declaração válida da variável hospedeira vstring: struct VARCHAR { short len; char s[10] } vstring; Declaring host variables in C and C++ applications that use SQL (N. do T.)

[2]

DB2 — se o valor da coluna de resultado for nulo, o SQL coloca -1 na variável indicadora; se não for utilizada uma variável indicadora, e a coluna de resultado tiver um valor nulo, retorna um SQLCODE negativo. Se o valor da coluna de resultado causar um erro de mapeamento, o SQL define a variável indicadora como -2. A variável indicadora também pode ser utilizada para verificar se o valor da cadeia de caracteres foi truncado. Quando há truncamento, a variável indicadora contém um inteiro positivo que especifica o comprimento original da cadeia de caracteres. (N. do T.)

[3]

DB2 — A variável indicadora vem imediatamente após a variável hospedeira. (N. do T.)

SourceForge.net Logo CSS válido!