Tivoli Service Desk 6.0 Developer's Toolkit - Guia de Programação do Script

Capítulo 8: Recursos de Gerenciamento do Banco de Dados

Retornar ao Índice


Introdução

O Developer's Toolkit foi projetado especificamente para simplificar o processo de criação de aplicativos de banco de dados cliente/servidor. Por essa razão, a linguagem TSD Script contém um conjunto de instruções destinadas à interação com bancos de dados SQL.

A interface SQL do TSD Script é uma parte intrínseca da linguagem. A interface SQL emprega a flexibilidade dos tipos RECORD e LIST do TSD Script. Além disso, as instruções SQL do TSD Script oferecem concorrência passiva interna para o desenvolvimento de aplicativos multiusuário confiáveis.

Um outro recurso que é particularmente útil é a capacidade para utilizar buscas ordenadas com o Oracle. A busca ordenada melhora significativamente o tempo necessário para consultar um banco de dados.

Visão geral sobre SQL

SQL, ou Structured Query Language (Linguagem de Consulta Estruturada), é uma linguagem de padrão industrial utilizada para:

Como este manual não pretende ser um tutorial do SQL, é aconselhável que você esteja familiarizado com a sintaxe SQL antes de ler este capítulo.

Bancos de dados suportados

Os seguintes bancos de dados (também conhecidos como origens) são suportados pelo Developer's Toolkit:

Suporte SQL no Developer's Toolkit

O Developer's Toolkit e a linguagem TSD Script aceitam várias instruções SQL e bancos de dados SQL utilizados para desenvolver aplicativos de cliente/servidor.

Instruções SQL não suportadas com drivers diretos

Algumas instruções SQL não são suportadas por drivers diretos da Oracle, Sybase/SQLServer e Informix. As instruções são listadas na tabela a seguir.

Esta instrução... É suportada somente em...
SQLDeleteCurrent DB2/2
SQLGetCursorName DB2/2
SQLUpdateCurrent DB2/2

Nota: SQLUpdateCurrent e SQLDeleteCurrent requerem a utilização de instruções aninhadas e devem ser utilizadas com a menor freqüência possível. As instruções são geralmente consideradas obsoletas e não são suportadas extensamente.

Atributos e Descrições da Origem dos Dados

Esta seção descreve os atributos que estão disponíveis quando você configura uma origem de dados. Os atributos controlam o procedimento de uma camada de banco de dados no Developer's Toolkit.

Nota: Estes atributos não são necessários quando você usa o Editor de Configuração SQL para configurar sua origem dos dados. Consulte a seção Como Conectar seu Aplicativo a um Banco de Dados que aparece posteriormente neste capítulo.

Definição da origem do banco de dados

Uma origem de banco de dados é uma coleção de informações identificadas por um nome específico. Ela é usada para definir o banco de dados e a conexão do banco de dados.

Nota: A opção para o nome da origem é sua. O TSD Script não requer, nem reconhece, quaisquer nomes predefinidos. O TSD Script requer que os nomes da origem dos dados não comecem com um número. No entanto, os aplicativos escritos com o TSD Script podem esperar certos nomes de origens. Por exemplo, o Tivoli Problem Management espera "ADVISOR" como o nome da origem de dados. Consulte a documentação do aplicativo para obter tais requisitos.

Atributos da origem

Quando uma origem de dados é configurada, os atributos, ou as características, para essa origem de dados são listados utilizando-se a sintaxe ATRIB=VALOR. Os atributos possíveis são:

Os seguintes atributos normalmente não são utilizados:

O TSD Script utiliza automaticamente os padrões para cada DBMS que ele aceita. Estes atributos são utilizados somente para substituir padrões em casos especiais, como uma ocorrência de distinção entre maiúsculas e minúsculas.

Na maioria dos casos, você não precisa substituir o padrão. Muitos destes atributos afetam os recursos avançados em um banco de dados e só devem ser alterados pelo administrador de banco de dados.

CASE_CONVERSION

Se você utiliza um banco de dados com nomes de objeto com distinção entre maiúsculas e minúsculas, deve codificar as consultas com as maiúsculas ou minúsculas apropriadas. Se você cria todos os objetos de seu banco de dados usando a mesma ocorrência (todas maiúsculas ou todas minúsculas), o TSD Script pode converter todos os nomes de objeto para aquela ocorrência. Os valores possíveis para esta entrada de atributo são: UPPER, LOWER ou NONE. O valor padrão, se esta entrada não existir, é NONE.

Nota: O TSD Script preserva sempre as maiúsculas e minúsculas de literais de cadeia colocados entre aspas em uma consulta.

CASE_SENSITIVE

Esta entrada refere-se ao modo como seu DBMS trata maiúsculas e minúsculas relativas aos objetos de banco de dados. Os objetos de banco de dados são nomes de tabela, nomes de coluna e etc. Se o valor for TRUE, o TSD Script preservará maiúsculas e minúsculas de todos os nomes de objeto (a menos que a entrada CASE_CONVERSION seja definida). Se a entrada CASE_SENSITIVE não existir, o valor padrão será FALSE.

COLUMN_DEFINITION_TABLE

As entradas a seguir podem ser utilizadas para substituir os nomes de coluna esperados pelo TSD Script na exibição do catálogo de colunas padrão.

Coluna Padrão
COL_NAME_COLUMN NAME
COL_REMARKS_COLUMN REMARKS
COL_LENGTH_COLUMN LENGTH
COL_SCALE_COLUMN SCALE
COL_TYPE_COLUMN COLTYPE
COL_NULLS_COLUMN NULLS
COL_TBNAME_COLUMN TBNAME
COL_TBCREATOR_COLUMN TBCREATOR

Nota: O TSD Script utiliza automaticamente os padrões para cada DBMS que ele suporta. Portanto, esta entrada não é utilizada sob circunstâncias normais. Esta entrada seria utilizada somente para substituir o padrão em casos especiais. Esta entrada contém o nome da tabela ou exibição do dicionário/catálogo de colunas. Como os produtos Tivoli fornecem uma exibição "delimitadora" para consistência, o valor padrão é sempre SAI_SYSCOLUMNS.

COMMIT_SELECTS

Esta entrada estará disponível somente se MANUAL_COMMITS for TRUE. Se aplicável, a definição COMMIT_SELECTS padrão será TRUE.

Defina a entrada COMMIT_SELECTS para TRUE se desejar consolidação automática após seleções.

DATE_FORMAT

DATE_FORMAT é o formato de data esperado para a origem dos dados (DBMS). Para a maioria dos sistemas, o formato de data padrão é: mm/dd/yyyy (mm, indica o mês, dd indica o dia e yyyy indica o ano). O formato de data padrão para o Oracle é dd-MON-yy (em que MON é o mês abreviado).

Você personaliza um formato de data especificando o formato do dia, mês, ano e separador. Embora muitas combinações destes itens sejam aceitas, há algumas exceções que não são aceitas. Por exemplo, yyyymmdd é aceito, mas não ocorre o mesmo com yyyyddmm.

Como especificar o dia

Você pode cortar zeros à esquerda dos dias e meses. Para cortar zeros à esquerda nos dias, especifique somente um "d" na data.

Nota: Se você cortar zeros à esquerda dos dias, deve cortá-los também dos meses. Por exemplo, mm/d/yyyy não é permitido.

Exemplo Resultado
mm/dd/yyyy 07/08/1999
m/d/yyyy 7/8/1999

Como especificar o mês

Você pode especificar o mês pelo número do mês no ano do calendário (1=Janeiro) ou pelo nome do mês. Para especificar o mês por números, utilize "MM." Para cortar zeros à esquerda em números de meses, utilize "M." Para especificar o mês pelo nome, ou com uma abreviação, utilize "Month" ou "Mon."
Os especificadores de nome de mês (Month e Mon) fazem distinção entre maiúsculas e minúsculas. Os especificadores de número de mês (MM e M) não fazem distinção entre maiúsculas e minúsculas.

Nota: Se você cortar zeros à esquerda dos meses, deve cortá-los também dos dias.

Exemplo Resultado
MM 08
M 8
Month Agosto
Mon Ago
MONTH AGOSTO
MON AGO

Como especificar o ano

Quando especificar o ano, você pode especificar o ano completo ou os dois últimos dígitos do ano.

Atenção: A Tivoli aconselha que, para datas do ano 2000, você utilize os números de quatro dígitos completos.

Exemplo Resultado
mm/dd/yyyy 07/08/1999
mm/dd/yy 07/08/99

Separadores

Você pode utilizar os seguintes separadores para formatar datas:

Tipo de Separador Exemplo Resultado
nenhum yyyymmdd 19990626
pontos mm.dd.yyyy 06.26.1999
traços dd-mm-yyyy 26-06-1999
barras mm/dd/yyyy 06/26/1999

DBMS

Para drivers ODBC, uma lista de DBMS é requerida no arquivo de configuração SQL. Os bancos de dados possíveis que podem ser listados como entradas DBMS= são os seguintes:

DEFAULT

Se o valor for TRUE, esta origem de dados será considerada a origem dos dados padrão na conexão. Somente uma entrada DEFAULT é permitida por arquivo de configuração SQL. O valor padrão, se esta entrada não existir, será FALSE.

DRV

Este é o nome do driver DBMS e é requerido quando conectar-se.

DSN

Este atributo lista o nome da origem dos dados para o arquivo de configuração SQL (somente ODBC).

MANUAL_COMMITS

Esta entrada está disponível para interfaces diretas; ela deve ser definida para TRUE se você desejar que o controle de transação seja tratado no nível do TSD Developer's Toolkit.

MULTIPLE_CONNECT

Esta entrada é definida para TRUE se o DBMS aceitar múltiplas conexões simultâneas.

MULTIPLE_CONNECT_REQUIRED

Defina esta entrada para TRUE se o DBMS requerer múltiplas conexões para executar mais de uma instrução aberta por vez (por exemplo, loops de seleção/busca aninhados). O valor padrão para Sybase e SQLServer é TRUE. É FALSE para todos os outros bancos de dados.

Nota: Quando necessário, o TSD Script abre as conexões adicionais para você.

QUAL

Este é o qualificador utilizado para acesso à tabela. O SQL armazena o criador/proprietário da tabela na definição da tabela. Este nome do criador/proprietário é referido como o qualificador da tabela. Uma combinação do nome do qualificador e da tabela deve ser utilizada para identificar exclusivamente uma tabela em um banco de dados.

SYSQUAL

Esta entrada contém o nome do qualificador necessário para acessar as tabelas/exibições do catálogo do sistema. Como todos os produtos Tivoli fornecem uma exibição "delimitadora" para consistência, o valor padrão é igual ao qualificador atual (na cadeia de conexão padrão).

TABLE_DEFINITION_TABLE

Esta entrada contém o nome da exibição ou tabela do catálogo/dicionário de tabelas. Como todos os produtos Tivoli fornecem uma exibição "delimitadora" para consistência, o valor padrão é sempre SAI_SYSCOLUMNS.

As cinco entradas a seguir podem ser utilizadas para substituir os nomes de coluna esperados pelo TSD Script na exibição do catálogo de tabelas padrão:

Tab Nome Padrão

TAB_NAME_COLUMN NAME
TAB_REMARKS_COLUMN REMARKS
TAB_TYPE_COLUMN TYPE
TAB_CREATOR_COLUMN CREATOR
TAB_COLCOUNT_COLUMN COLCOUNT (para DB2/2 e SQLBase)

TIME_FORMAT

Esta entrada é o formato de hora esperado para a origem dos dados. O padrão para todas as entradas DBMS é hh:mm:ss. Embora a maioria dos especificadores de formato de hora sejam válidos, alguns não são. Por exemplo, hh:mm:ss é aceito, mas mm:hh:ss não é.

Consulte a seção no TSD 6.0 - Referência de Linguagem do Script sobre a instrução TimeFormat para obter mais informações sobre formatos de hora válidos.


Hora militar

Por padrão, a hora é especificada no formato militar (relógio de 24 horas). Para especificar a hora em um relógio de 12 horas, inclua o sufixo AM_PM:

Exemplo Resultado
hh:mmAM_PM 09:08 PM
hh:mm 21:08

Formatos de hora sem distinção de maiúsculas e minúsculas

O especificador do formato não faz distinção de maiúsculas e minúsculas. Por exemplo, hh:mm:ss é equivalente a HH:MM:SS

Como cortar zeros à esquerda

Para cortar zeros à esquerda, especifique somente um h, m e s. Por exemplo:

Exemplo Resultado
hh:mm:ss 08:35:09
h:m:s 8:35:9

Nota: Se você optar por cortar zeros à esquerda, deverá cortá-los das horas, minutos e segundos.

Como especificar os segundos

Para especificar os segundos, inclua a designação ss. Você pode, opcionalmente, omitir os segundos.

Exemplo Resultado
hh:mm:ss 08:35:09
h:m 8:35

Separadores

Você pode especificar dois-pontos ou pontos para formatar o especificador de hora:

Tipo de Separador Exemplo Resultado
nenhum hhmmss 121604
pontos hh.mm.ss 12.16.04
dois-pontos hh:mm:ss 12:16:04

UPPERCASE_FUNCTION

Esta entrada contém o nome de função específico do DBMS utilizado para converter colunas em uma consulta para maiúsculas (utilizada por SQLCreateSearchString). Os valores padrão são:

Como Conectar seu Aplicativo a um Banco de Dados

A conexão a um banco de dados é comum para todos os DBMSs SQL. Os meios para conexão variam dependendo do banco de dados utilizado. Por exemplo:

Para mascarar estas diferenças, o TSD Script fornece um conjunto de serviços de conexão que utilizam a instrução SQLCommand. SQLCommand permite que comandos externos sejam utilizados para informações de conexão específicas do DBMS em um arquivo de configuração SQL. Isto simplifica seu código de aplicativo e o torna portável.

Nome do arquivo de configuração SQL

O nome padrão do arquivo de configuração SQL do Developer's Toolkit é sai_sql.cfg. O Developer's Toolkit procura por um arquivo chamado sai_sql.cfg no subdiretório CFG do diretório raiz SAI.

Você pode substituir o nome do arquivo que o TSD Script procura definindo uma variável de ambiente chamada SAISQLCFG para conter um nome de arquivo diferente. O valor na variável de ambiente SAISQLCFG tem precedência sobre o caminho derivado de SAI_ROOT se ambos estiverem definidos. Um erro será retornado se o arquivo não for encontrado.

O arquivo de configuração SQL é dividido em seções que descrevem uma origem de dados. Considere uma origem de dados como o DBMS com o qual você está trabalhando. Normalmente, as origens dos dados correspondem aos servidores de banco de dados físicos, embora a idéia possa ser estendida para incluir origens lógicas em um servidor (uma origem por banco de dados, por exemplo).

Outras localizações para instruções de configuração

O Developer's Toolkit fornece uma série de interfaces diretas de banco de dados que você pode utilizar com base nos requisitos do seu banco de dados. Estas interfaces diretas de banco de dados são o método padrão de conectividade de banco de dados para o Developer's Toolkit.

Se você desejar utilizar o ODBC, em vez das interfaces diretas de bancos de dados, pode encontrar mais informações sobre drivers ODBC no Apêndice A "Configurações ODBC" do Tivoli Service Desk 6.0 - Guia de Instalação.

Se você utiliza as interfaces diretas de banco de dados padrão do Developer's Toolkit, consulte "Processo de Configuração" no Tivoli Service Desk 6.0 - Guia de Instalação para obter instruções completas de configuração e teste.

Exemplo de configuração de banco de dados

Para incluir um cliente de banco de dados para sua utilização inicial, siga estas etapas:

  1. A partir do grupo de programas do Developer's Toolkit, escolha o Editor de Configuração SQL.
    Resultado: A caixa de diálogo Editor de Configuração SQL é exibida.

Os seguintes componentes são encontrados na caixa de diálogo Editor de Configuração SQL:

  1. Se já não estiver inserido na caixa de texto Arquivo, digite a unidade, caminho e nome do arquivo para o arquivo sai_sql.cfg (a localização padrão é c:\sai\cfg\sai_sql.cfg) e escolha Incluir.
    Resultado: Você criou um arquivo de configuração e incluiu a primeira origem dos dados. A caixa de diálogo Seleção de Driver é exibida.
  2. Selecione o driver de banco de dados que você deseja utilizar a partir da lista de botões de rádio e escolha OK.
    Resultado: A caixa de diálogo Configuração da Origem é exibida.
  3. Digite as informações relevantes para seu cliente de banco de dados nas caixas de texto apropriadas e escolha OK ou Avançado.

Resultado: Se você escolher OK, concluirá o procedimento. Se escolher Avançado na caixa de diálogo Configuração da Origem, a caixa de diálogo Configuração de Opções Avançadas será exibida.

  1. Escolha Incluir.
    Resultado: A caixa de diálogo Seleção de Opção é exibida.
  2. Selecione a opção que você deseja configurar e escolha Selecionar.
    Resultado: A caixa de diálogo Entrada de Valor de Opção é exibida.
  3. Na caixa de diálogo Entrada de Valor de Opção, digite a opção de atributo e o valor de atributo para a origem que você está configurando. Se precisar de mais informações, escolha Auxílio.
  4. Escolha OK e saia do Editor de Configuração SQL.

Como testar a conexão do cliente de banco de dados

Após incluir uma nova conexão de banco de dados, você deve testar a conexão para garantir que ela funciona corretamente. Conclua estas etapas para testar uma conexão de banco de dados:

  1. A partir do grupo de programas do Developer's Toolkit, escolha o Editor de Configuração SQL.
  2. Selecione a origem dos dados que você deseja testar e escolha Testar Conexão. Se a função Testar Conexão retornar uma mensagem de erro, verifique os parâmetros digitados na caixa de diálogo Configuração da Origem ou teste a conectividade.

Informações de conexão no arquivo de configuração SQL

Há um problema de segurança potencial se você mantiver IDs de usuário e senhas no arquivo de configuração SQL. Pode haver também dificuldade se você mantiver informações específicas da conexão para mais de um usuário já que o arquivo é facilmente acessado por todos os usuários e as senhas armazenadas não são, por padrão, criptografadas.
O usuário deve selecionar a criptografia utilizando o Editor de Configuração SQL. Consulte Exemplo de configuração de banco de dados neste guia para obter mais informações.

O TSD Script fornece um método simples de fornecer informações específicas da conexão na própria instrução connect:

ret := SQLCommand('CONNECT SOURCE=DB2_TEST;
UID=FRED; PWD=DERF;'); 

Quando o TSD Script encontra este tipo de pedido de conexão, ocorre o seguinte:

A cadeia de conexão padrão para DB2_TEST é localizada (DB2_TEST deve ser uma origem no arquivo de configuração SQL). Se uma entrada SOURCE= não for encontrada, o TSD Script utilizará o padrão.

Nota: Quando outros atributos estão presentes, você precisa colocar o SOURCE= antes do nome da origem dos dados.

Uma nova cadeia de conexão é formada pela sobreposição de pares ATRIBUTO=VALOR restantes nas entradas correspondentes na cadeia de conexão padrão e pela inserção de novos pares que não estão na cadeia de conexão padrão.

Você pode substituir qualquer entrada da cadeia de conexão padrão, exceto o driver (DRV=). Isto permite que você tenha informações de conexão padrão (banco de dados, qualificador de tabela e etc) que podem ser substituídas conforme necessário. Você pode também obter um pouco deste efeito criando novas origens de dados (uma origem por banco de dados, por exemplo).

Como excluir o arquivo de configuração SQL

É possível fornecer todas as informações de conexão para SQLCommand e eliminar o arquivo de configuração SQL. No entanto, você deve estar disposto a aceitar todos os valores de origem padrão (como MULTI_CONNECT, e etc).

Externalizar as informações específicas do DBMS normalmente é uma boa coisa a se fazer. No entanto, há algumas vezes em que você precisa eliminar o arquivo de configuração SQL. Para tratar destes casos, o TSD Script permite que você se conecte e registre uma nova origem não encontrada em um arquivo de configuração SQL:

ret := SQLCommand('CONNECT NEWSOURCE=MYAPP; 
                   DRV=XOORA;SRVR=X:ORASERV; 
                   UID=MARY; PWD='); 

Exemplo de banco de dados

Tabelas e exibições de banco de dados

O restante deste capítulo se refere a um banco de dados de exemplo chamado COMPANY. Este banco de dados consiste nas seguintes tabelas e exibições. Os atributos de coluna são listados sob cada nome de tabela ou exibição.

Tabela DEPARTMENT

Tabela EMPLOYEE

Tabela MANAGER

Como Recuperar Dados com o SQLSelectInto

SQLSelectInto

A instrução SQLSelectInto fornece um modo fácil para obter informações de uma tabela ou exibição SQL. Ela possui um número variável de argumentos.

Primeiro argumento

O primeiro argumento é sempre uma expressão de cadeia que representa uma instrução SQLSelect, tal como:

SELECT * FROM EMPLOYEE WHERE EMPLOYEE_ID='305-83-3811'. 

Na maioria dos casos, SQLSelectInto é utilizada para recuperar uma linha exclusiva de uma tabela. A expressão select passada como o primeiro argumento geralmente contém uma cláusula no formato:

WHERE <primary-key>=<value> 

Em geral, o formato de uma instrução select é:

SELECT <column-list> FROM <table-or-view name> WHERE <condition>. 

<column-list> é uma lista de um ou mais nomes de coluna separados por vírgulas (tais como "FIRST_NAME, LAST_NAME"). Se você desejar obter todas as colunas de uma tabela, poderá utilizar o asterisco (*) no lugar.

<condition> é uma condição TRUE/FALSE geralmente formada pela utilização de um nome de coluna, um operador relacional (=, >, <, >=, <=) e um valor (tal como 'SMITH').

Exemplos de instruções select válidas são mostrados abaixo:

SELECT EMPLOYEE_ID,LAST_NAME FROM EMPLOYEE WHERE 
    DEPARTMENT_ID='SALES' 
SELECT FIRST_NAME,LAST_NAME,PHONE FROM EMPLOYEE 
SELECT * FROM MANAGER 

Argumentos subseqüentes

O segundo argumento, e subseqüentes, para SQLSelectInto são variáveis do TSD Script. Os nomes destas variáveis devem corresponder aos nomes de colunas na tabela ou exibição SQL que está sendo acessada, conforme mostrado neste exemplo:

VARIABLES
  last_name, first_name: String;
ACTIONS
  SQLSelectInto('SELECT LAST_NAME,FIRST_NAME FROM
               EMPLOYEE WHERE EMPLOYEE_ID=123',
               last_name,first_name); 

A distinção entre maiúsculas e minúsculas das variáveis do TSD Script não é importante para o processamento nestes exemplos. O valor da coluna LAST_NAME é extraído da variável de cadeia last_name. O valor da coluna FIRST_NAME é extraído da coluna first_name.

Como Utilizar uma Variável de Registro

Um modo mais fácil para extrair informações de tabelas SQL é utilizar as variáveis de registro do TSD Script. Você define um tipo de registro onde os campos correspondem aos nomes de coluna em uma tabela SQL. Você pode, então, passar um registro desse tipo para SQLSelectInto, conforme mostrado abaixo:

TYPES 
  EmployeeRec IS RECORD 
    employee_ID: Integer; 
    last_name: String; 
    first_name: String; 
    birth_date: Date; 
    salary: Real; 
END; 
VARIABLES 
  r: EmployeeRec; 
  SQLSelectInto('SELECT LAST_NAME,FIRST_NAME FROM 
                EMPLOYEE WHERE EMPLOYEE_ID=123',r);


Tipos de registro

Em geral, você declara um tipo de registro cujo nome é igual para toda tabela ou exibição em um banco de dados. Utilizar as funções de ligação de nome do TSD Script permite extrair informações do banco de dados, ou inserir informações nele, utilizando variáveis desse tipo de registro.

No exemplo anterior, o tipo de registro EmployeeRec é declarado de tal modo que os nomes e tipos de campo correspondam aos nomes e tipos de colunas na tabela SQL EMPLOYEE. Quando você passa um registro (r) deste tipo para SQLSelectInto, o Developer's Toolkit copia automaticamente as informações da linha selecionada para os campos correspondentes. Após a execução de SQLSelectInto, r tem o seguinte valor:

r.employee_ID = $Unknown 
r.last_name = 'Brown' 
r.first_name = 'Robert' 
r.birth_date = $Unknown 
r.salary = $Unknown 

Observe que somente as colunas r.LAST_NAME e r.FIRST_NAME têm valores. Todos os campos em um registro saem com o valor $Unknown. Como a instrução SQLSelectInto selecionou as colunas LAST_NAME e FIRST_NAME, somente r.LAST_NAME e r.FIRST_NAME foram valores atribuídos. Todos os campos r teriam sido concluídos se a seguinte instrução tivesse sido utilizada:

SQLSelectInto('SELECT * FROM EMPLOYEE WHERE EMPLOYEE_ID=123',r); 

Como Utilizar Instruções Import do TSD Script

O mapeamento entre os tipos de registro do TSD Script e as tabelas SQL é um processo intuitivo. O TSD Script permite criar uma associação automática entre uma tabela, uma exibição e um tipo de registro através de instruções import.

Isso significa que você não tem que declarar manualmente um campo de registro para cada coluna de uma tabela ou exibição. Veja o exemplo a seguir:

TYPES
  EmployeeRec IS RECORD 
    IMPORT('EMPLOYEE'); 
END; 

Instruções import

As instruções import podem ser utilizadas em uma declaração de registro para criar declarações de campo diretamente dos nomes e tipos de uma tabela ou exibição SQL.
Se a tabela ou exibição for alterada, a declaração de registro acompanhará automaticamente a alteração. Ou seja, se você incluiu uma nova coluna ADDRESS à tabela EMPLOYEE, não tem que incluir um novo campo

address: String; 

para EmployeeRec. IMPORT é uma instrução de tempo de análise. Quando um módulo contendo uma instrução IMPORT é reconstruído (analisado), a tabela ou exibição SQL indicada é lida e suas colunas utilizadas para criar declarações de campo.

Cadeia de conexão

As instruções import recebem uma cadeia de conexão que é especificada junto com o nome da tabela ou exibição. Esta cadeia de conexão substitui a cadeia de conexão padrão especificada no arquivo sai_sql.cfg. Com o objetivo de compatibilidade anterior, você pode especificar o nome do banco de dados no formato 'DATABASE xxx', em que xxx é o nome do banco de dados.

Como analisar com a opção /S

Ao analisar, você deve passar a opção /S para o Analisador do TSD Script substituir quaisquer informações de banco de dados ou conexão protegidas na instrução import.

A opção /S permite especificar um banco de dados no tempo de análise, para que não haja necessidade de proteger o nome da origem dos dados. Também permite especificar o ID do usuário e a senha quando você executa o Analisador do TSD Script a partir do prompt de comandos. Estes valores são substituídos pelos padrões especificados no arquivo sai_sql.cfg.

O método recomendado para utilizar a opção /S é especificar todos os valores, exceto o ID do usuário e a senha no arquivo sai_sql.cfg. Depois, quando você analisar, estes valores poderão ser passados. Por exemplo:

/S"UID=UserId;PWD=Password" 

(em que UserId é o ID do usuário e Password é a senha exclusiva do usuário.)

Como utilizar palavras-chave

Quando você utiliza IMPORT, pode utilizar palavras-chave opcionais para esclarecer a disposição do conteúdo de IMPORT. As palavras-chave são:

Se você não especificar quaisquer palavras-chave, a ordem da cadeia import é assumida como sendo o nome da tabela primeiro, seguido pela cadeia de conexão.

Utilize espaço em branco e/ou vírgulas para separar as informações de nome de tabela e de conexão.

Nota: Você pode utilizar a palavra-chave TABLE ou VIEW para identificar nomes de tabela ou exibição. Elas são tratadas de modo igual.

Neste manual, as palavras-chave aparecem todas em letras maiúsculas e não há distinção entre maiúsculas e minúsculas. No entanto, os nomes de tabela e as informações de conexão podem fazer distinção entre maiúsculas e minúsculas, dependendo de sua instalação do DBMS. Consulte um administrador de rede local ou administrador de banco de dados para obter estas informações. Você pode também consultar os manuais fornecidos com o DBMS para determinar se a distinção entre maiúsculas e minúsculas é um problema.

Exemplos da instrução IMPORT

Há vários modos para construir uma cadeia import válida. Os seguintes exemplos foram desenvolvidos para fornecer diversas opções. No entanto, recomenda-se que você escolha um estilo e utilize-o consistentemente.

O método recomendado para utilização de IMPORT é mostrado abaixo:

Import('ALARMS'); 

A sintaxe a seguir foi aceita no SA-ASE 4.1:

Import('DATABASE ADVISOR TABLE ALARMS');

Para SA-ASE 4.2 e posterior, esta sintaxe é:

'CONNECT DB=ADVISOR' 

Os seguintes exemplos também são equivalentes ao exemplo anterior:

Import ('CONNECT DB=ADVISOR TABLE ALARMS'); 
Import('TABLE ALARMS CONNECT DB=ADVISOR'); 
Import('ALARMS, CONNECT'); 
Import('TABLE ALARMS'); 
Import('VIEW PROBLEM_VIEW'); 

No exemplo a seguir, observe a não disposição de espaços na cadeia de conexão:

Import('ALARMS, SRVR=X:ORASRV;DB=ADVISOR'); 

O exemplo a seguir também está correto:

Import('TABLE ALARMS, CONNECT SRVR=X:ORASRV; DB=ADVISOR); 

No exemplo a seguir, o "'" é opcional.

Import('TABLE ALARMS CONNECT SRVR=X:ORASRV; DB=ADVISOR'); 

O exemplo a seguir também está correto:

Import('CONNECT SOURCE=ADVTEST;SRVR=X:ORASRV; DB=ADVISOR, TABLE ALARMS);

Exemplo incorreto

Observe que a sintaxe a seguir está incorreta, porque a cadeia 'ADVISOR' não é uma cadeia de conexão válida ('DB=ADVISOR' é uma cadeia de conexão válida).

Import('ALARMS,ADVISOR'); (*isto está ERRADO!*)

Tipos de dados

O TSD Script tem seis tipos de dados simples:

A instrução IMPORT possui uma abordagem genérica para mapear colunas para campos baseados em seu tipo de dados.

Coluna Mapeia...
CHAR, VARCHAR e LONG VARCHAR TSD Script STRINGS
INTEGER TSD Script INTEGERS
DATE TSD Script DATES
TIME TSD Script TIMES
Tipos SQL contendo vírgulas decimais (fixas ou flutuantes) TSD Script REALS

O tipo BOOLEAN não é aceito na maioria das implementações de SQL. No entanto, se você utilizar o Oracle ou o DB2/2 da IBM, pode incluir $ASETYPE=BOOLEAN no comentário para uma coluna gerar um campo Booleano com a instrução IMPORT. Para o SQLServer, o Developer's Toolkit cria um tipo BOOLEAN definido pelo usuário.

O Developer's Toolkit cria uma tabela de tipos que se liga à exibição SYSCOLUMNS para Informix.


Recuperação de Múltiplas Linhas

SQLSelectInto é um modo fácil para recuperar uma linha exclusiva de uma tabela ou exibição. SQLSelectInto pode ser utilizado para localizar uma linha, mas não pode fazer varredura em uma tabela.

O TSD Script fornece uma variável de cursor para recuperar múltiplos itens de um banco de dados dentro de um loop. O cursor controla a posição atual em uma lista recuperada.

Processo

O processo básico para recuperar múltiplas linhas é o seguinte:

Para permitir a recuperação de múltiplas linhas, o TSD Script fornece três instruções:

O TSD 6.0 Developer's Toolkit - Referência de Linguagem do Script fornece informações adicionais sobre as instruções precedentes.

Exemplo

As instruções são utilizadas no exemplo a seguir:

VARIABLES 
  cursor: SQLCursor; 
  r: EmployeeRec; 
ACTIONS 
 IF SQLSelect(cursor,'SELECT * FROM EMPLOYEE WHERE 
              SALARY>>0000.00') > 0 THEN 
    WHILE SQLFetch(cursor,r) > 0 DO 
      ProcessEmployee(r); 
END; 
    SQLCloseCursor(cursor); 
 END; 

Este exemplo faz o seguinte:

A operação SQLCloseCursor é muito importante. Quando um cursor SQL é aberto, a maioria das implementações de SQL bloqueia todas as linhas na tabela de resultados. Estas linhas não são desbloqueadas até que a instrução SQLCloseCursor seja processada.

Nota: Normalmente você não quer executar quaisquer operações de interface com o usuário entre as instruções SQLSelect e SQLCloseCursor. Adicionalmente, o TSD Script fornece um número limitado de cursores simultâneos. Se você se esquecer de fechar os cursores, eventualmente excederá este limite.

Qualificadores

Como utilizar qualificadores

O SQL permite múltiplas tabelas com o mesmo nome em um banco de dados. Para diferenciá-las, o SQL armazena o criador/proprietário da tabela na definição da tabela. Este nome do criador/proprietário é referido como o qualificador da tabela. Uma combinação do nome do qualificador e da tabela deve ser utilizada para identificar exclusivamente uma tabela em um banco de dados. Por exemplo:

mary.address

A maioria dos gerenciadores de banco de dados do SQL utiliza o ID do usuário atual como o qualificador se nenhum for fornecido. Se você não iniciou sessão como o usuário que criou o banco de dados e não fornecer um qualificador, algumas implementações de SQL continuam a pesquisar o banco de dados utilizando o proprietário do banco de dados como o qualificador. Em outras implementações de SQL (como DB2/2), você precisa fornecer o qualificador toda vez.

Substituição de qualificação

O TSD Script executa as substituições de qualificação apropriadas desde que você forneça uma entrada QUAL= na cadeia de conexão.

O TSD Script executa a substituição em todas as instruções, exceto:

Se você utiliza consultas complexas contendo nomes de correlação, a substituição pode não ser executada corretamente. Para tratar destes casos, o TSD Script fornece um pseudo-qualificador, $QUAL, que é substituído pelo qualificador atual (ou seja, aquele definido com a entrada QUAL= da cadeia de conexão).

Por exemplo, para evitar proteger o qualificador, o seguinte fragmento de código utiliza $QUAL como o qualificador:

ret := SQLExecuteImmediate('DROP TABLE $QUAL.ADDRESS'); 

Aspas

No TSD Script, todas as cadeias são delimitadas por aspas simples (ou apóstrofos). No SQL, literais de caractere, data e hora também devem ser delimitados por aspas simples. Por exemplo, para emitir a consulta SQL,

SELECT * FROM EMPLOYEE WHERE LAST_NAME='BROWN' 

você utilizaria a seguinte instrução do TSD Script:

SQLSelectInto('SELECT * FROM EMPLOYEE WHERE
LAST_NAME=''BROWN''',r); 

Vendo o exemplo anterior de SQLSelectInto, você pode notar que as duas aspas simples à esquerda do "B" em "BROWN" resulta em uma aspa simples. Há duas aspas simples após o "N" em "BROWN." Isto faz com que uma aspa simples seja inserida nesta posição. A terceira aspa simples após o "N" em "BROWN" é utilizada para terminar a cadeia.

Para incluir uma aspa simples em um literal de cadeia do TSD Script, você deve incluir duas aspas simples. Por exemplo, para atribuir a cadeia "Tom's Place" a uma variável do TSD Script, você deve utilizar o seguinte:

s := 'Tom''s Place';

Como concatenar cadeias com aspas

Quando você concatena cadeias que utilizam aspas, isso pode tornar-se mais complicado. Neste exemplo, o sobrenome real pelo qual você deseja procurar é armazenado em uma variável de cadeia chamada last_name:

last_name := 'BROWN'; 
SQLSelectInto('SELECT * FROM EMPLOYEE WHERE 
             LAST_NAME=''' & last_name & '''',r); 

Quando você criar uma cadeia select utilizando o operador de concatenação do TSD Script (&), tome cuidado para posicionar as aspas simples em ambos os lados do valor de literal que deseja pesquisar. A consulta resultante é semelhante à seguinte:

SELECT * FROM EMPLOYEE WHERE LAST_NAME = 'BROWN' 

As aspas simples à esquerda do valor last name é obtida através das três aspas simples após "LAST_NAME=''.

As duas primeiras são utilizadas para inserir a aspa simples necessário, enquanto a terceira simplesmente termina a primeira constante em cadeia, 'SELECT * ... ='.

A segunda aspa simples necessária é obtida concatenando o literal '''' para o final da expressão inteira.

Ao criar expressões select em que o valor procurado é uma cadeia, data ou hora, você precisa incluir três aspas antes da variável que retém o valor de pesquisa e quatro aspas depois.

Exceções

As aspas não são necessárias para procurar outros tipos de dados, conforme mostrado abaixo:

SQLSelectInto('SELECT * FROM EMPLOYEE WHERE 
              AGE=30',r); 

Você não precisa colocar aspas em torno de 30 porque este é um valor inteiro. Se o 30 tivesse sido retido em uma variável integer, sua instrução seria semelhante à seguinte:

age := 30; 
SQLSelectInto('SELECT * FROM EMPLOYEE WHERE AGE=' & age,r);

Formatação de Dados com a Instrução SQLFormat

Como Utilizar o SQLFormat

A instrução SQLFormat é uma instrução do TSD Script utilizada na manipulação de SQL. SQLFormat converte um valor de dados para uma cadeia que corresponde ao formato de dados para o DBMS que você está utilizando atualmente.

A instrução SQLFormat é especialmente útil para variáveis de data e hora e utiliza a seguinte sintaxe:

SQLFormat(value: SIMPLE EXPRESSION): STRING;

Nota: Seu DBMS pode requerer formatos de data e hora que são diferentes dos formatos padrão utilizados para exibição pelo Developer's Toolkit. Por exemplo, o formato de data padrão Oracle é DD-MON-YY, enquanto o formato de data padrão do Developer's Toolkit é MM/DD/YYYY.

O valor que o argumento SQLFormat recebe deve ser de um tipo simples, como DATE ou STRING. SQLFormat retorna a cadeia formatada, não um código de retorno, que indica se a operação foi bem-sucedida. Se o valor passado for $Unknown, a cadeia 'NULL' será retornada. A formatação específica da cadeia depende do tipo da cadeia:

Exemplo

Um exemplo de base de informações utilizando SQLFormat é mostrado abaixo:

Exemplo de KNOWLEDGEBASE;
--PUBLIC 
ROUTINES 
 FUNCTION GetCount(VAL d: DATE): INTEGER; 
PRIVATE 
ROUTINES 
 FUNCTION GetCount(VAL d: DATE): INTEGER IS 
 VARIABLES
   retCd : INTEGER; 
   cmd : STRING; 
   $SQLColumn_1 : INTEGER; 
 ACTIONS
   cmd := 'SELECT COUNT(*) FROM COMPANIES WHERE name = 
          ' & SQLFormat('Joe''s place') & 
          ' AND founded_date='& SQLFormat(d); 
   retCd := SQLSelectInto(cmd, $SQLColumn_1); 
   IF retCd < 0 THEN 
     Exit( retCd ); 
   ELSE 
     Exit( $SQLColumn_1 ); 
   END;
 END; 

Para obter mais informações sobre instruções do TSD Script utilizadas na formatação de dados, consulte o TSD 6.0 Developer's Toolkit - Referência de Linguagem do Script.

Substituições de Nomes

O TSD Script utiliza a equivalência de nomes de variável e nomes de coluna para tornar simples a recuperação de dados. No entanto, às vezes o mapeamento baseado no nome é inconveniente ou não pode ser utilizado.

Considere a seguinte consulta SQL que pode ser utilizada para determinar o número de funcionários (linhas) na tabela EMPLOYEE:

SELECT COUNT(*) FROM EMPLOYEE

Como recuperar dados sem corresponder nomes

O TSD Script fornece um método simples para recuperar dados de uma coluna do SQL sem contar com nomes correspondentes. Tudo o que você deve fazer é declarar uma variável nomeada $SQLCOLUMN_n, em que "n" é o número da coluna a ser recuperada. O tipo desta variável deve mapear a coluna que está sendo recuperada.

Para recuperar o número de funcionários (linhas) na tabela EMPLOYEE, você pode utilizar o seguinte código:

VARIABLES
  $SQLCOLUMN_1: INTEGER;
ACTIONS
  SQLSelectInto('SELECT COUNT(*) FROM
                 EMPLOYEE',$SQLCOLUMN_1);

$SQLCOLUMN_1 é uma variável normal. Você pode atribuí-la, testá-la, utilizá-la em expressões e etc.

Como Atualizar os Dados

Introdução

Esta seção descreve como inserir dados em um banco de dados SQL, excluir dados de um banco de dados SQL e modificar dados em um banco de dados SQL.

Como inserir dados

A instrução SQLInsert pode ser utilizada para inserir novas linhas em uma tabela. Tudo o que você precisa fazer é fornecer um nome de tabela seguido pelas variáveis que retêm os dados a serem inseridos. Como a função de recuperação, o TSD Script executa um mapeamento entre os nomes de variável do TSD Script e os nomes de coluna do SQL.

No exemplo a seguir, os valores são atribuídos a vários campos de uma variável do tipo EmployeeRecord. Para inserir estas informações na tabela EMPLOYEE, SQLInsert é chamado com o nome da tabela de destino e a variável.

VARIABLE 
  r: EmployeeRecord; 
ACTIONS 
  r.employee_ID:'312-34-3444'; 
  r.last_name:'Brown' 
  r.first_name:'Robert' 
  r.birth_date:'08/05/1964'; 
  r.salary:  $Unknown 
  SQLInsert('EMPLOYEE',r); 

SQLInsert, como SQLSelectInto e SQLSelect, possui um número variável de argumentos. O primeiro argumento é o nome da tabela. Os argumentos restantes representam valores a serem colocados em cada coluna da nova linha. Você pode passar um registro simples ou uma série de variáveis simples, conforme mostrado no exemplo a seguir.

VARIABLE
  employee_ID: STRING; 
  last_name: STRING; 
  first_name: STRING; 
  birth_date: DATE; 
  salary: REAL; 
ACTIONS 
  employee_ID:'312-34-3444'; 
  last_name:'Brown'; 
  first_name:'Robert'; 
  birth_date:'08/05/1964'; 
  salary:$Unknown; 
  SQLInsert('EMPLOYEE',employee_ID,last_name,
            first_name,birth_date,salary); 

Como excluir dados

SQLDelete pode ser utilizado para excluir uma ou mais linhas de uma tabela. Ele possui dois argumentos: o nome da tabela e a cláusula SQL WHERE que identifica as linhas a serem excluídas. A palavra WHERE nesta cláusula é opcional.

Este exemplo exclui todo funcionário cujo sobrenome seja "Smith."

SQLDelete('EMPLOYEE','LAST_NAME=''Smith'''); 

O exemplo a seguir exclui um funcionário com um número de ID de funcionário específico.

SQLDelete('EMPLOYEE','EMPLOYEE_ID=''123-45-
           6789''');

Como modificar dados

SQLUpdate pode ser utilizado para alterar as informações armazenadas nas linhas existentes de uma tabela. Esta instrução possui os seguintes argumentos:

Por exemplo, suponha que sua empresa tenha um funcionário com um ID de 345-67-8901 que tenha recebido um aumento de 10%. Você atualizaria o banco de dados para refletir esse fato, conforme mostrado neste exemplo:

VARIABLES 
  salary: REAL; 
ACTIONS 
  IF SQLSelectInto('SELECT SALARY FROM EMPLOYEE 
                  WHERE EMPLOYEE_ID=
                  ''345-67-8901''', 
                  salary) > 0 THEN 
  salary := salary * 1.10; 
  SQLUpdate('EMPLOYEE','EMPLOYEE_ID='
            '345-67- 8901''',salary); 
END; 

No próximo exemplo, a empresa decidiu conceder um aumento de 10% para todos. Este exemplo mostra como atualizar o banco de dados com essas informações:

VARIABLES 
  salary: REAL; 
  cursor: SQLCursor; 
ACTIONS 
  IF SQLSelect(cursor, 
               'SELECT SALARY FROM EMPLOYEE 
               ') > 0 THEN 
WHILE SQLFetch(cursor,salary) > 0 DO 
      salary := salary * 1.10; 
      SQLUpdateCurrent(cursor,salary); 
END; 
    SQLCloseCursor(cursor); 
END; 

SQLUpdateCurrent é uma versão especial de SQLUpdate que pode ser utilizada para atualizar a linha buscada mais recentemente de um cursor. Ela recebe a variável de cursor e os valores a serem atualizados como argumentos.

Finalmente, SQLUpdate (e SQLUpdateCurrent) pode receber um registro no lugar de uma seqüência de algumas variáveis simples. O próximo exemplo assume que:

VARIABLE 
  r: EmployeeRecord; 
ACTIONS 
  r.employee_ID: = '312-34-3444'; 
  IF SQLSelectInto('SELECT * FROM EMPLOYEE 
                   WHERE EMPLOYEE_ID=''' & 
r.employee_ID & '''',r) > 0 THEN 
    EditEmployee(r); 
    SQLUpdate('EMPLOYEE',
              'EMPLOYEE_ID=''' & r.employee_ID & '''',r);
END; 

Em resumo, as seguintes etapas são executadas neste exemplo:

Concorrência passiva

Você pode ter observado nos exemplos que os registro não foram bloqueados, nem quaisquer etapas foram seguidas para evitar que vários usuários acessem os mesmos registros.

O recurso de concorrência passiva do Developer's Toolkit trata dos problemas típicos de concorrência que ocorrem em aplicativos multiusuário, conforme resumido na lista a seguir:

A mensagem de erro tem um código de erro negativo. Em alguns casos, você pode querer testar este código de erro e executar ações diferentes dependendo de seu valor.

Por exemplo, se uma seção de código depende do sucesso de uma operação inserir, você deve envolver esse código com um teste para um retorno positivo de SQLInsert.

O Developer's Toolkit gera uma mensagem de erro para o segundo usuário que tenta uma exclusão.

Nota: Para implementar a verificação de concorrência passiva, inclua um argumento adicional para SQLUpdate.

Considere o exemplo a seguir:

VARIABLE 
  r, oldR: EmployeeRecord; 
ACTIONS 
  r.employee_ID: = '312-34-3444'; 
  IF SQLSelectInto('SELECT * FROM EMPLOYEE WHERE 
                    EMPLOYEE_ID=''' & r.employee_ID 
                    & '''', r, oldR) > 0 THEN 
    EditEmployee(r); 
    SQLUpdate('EMPLOYEE',
              'EMPLOYEE_ID=''' & r.employee_ID & 
              '''',r,oldR); 
END; 

Neste exemplo ocorreram os seguintes eventos:

Quando o TSD Script começa a processar a instrução SQLUpdate, ele detecta a variável de registro extra, oldR. Isso faz com que ele:

Se forem detectadas quaisquer diferenças, significa que alguém já alterou aquela linha e a atualização é cancelada. SQLUpdate retorna um código de erro negativo e uma mensagem de erro de nível de usuário é exibida na tela. Além disso, o valor atual da linha é colocado em oldR (para que o usuário não tenha que obter a versão atual do registro).

A concorrência passiva representa um meio fácil e eficaz de garantir operação adequadas em um ambiente multiusuário. Há um pouco de sobrecarga porque há uma segunda recuperação da linha a ser atualizada. No entanto, a proteção adicional fornecida é conveniente.

Nota: Em geral, você deve sempre utilizar a forma de concorrência passiva de SQLUpdate a menos que tenha certeza de que não há possibilidade de atualizações perdidas.

Processamento Orientado a Transações

A maioria dos mecanismos de banco de dados SQL oferece um recurso que permite agrupar operações SQL em unidades de trabalho. Você pode, então, utilizar recursos internos para garantir que cada unidade de trabalho seja totalmente bem-sucedida ou falhe como um todo.

No processamento normal, todas as alterações são consolidadas no banco de dados assim que ocorrem. No processamento orientado a transações, as alterações feitas aos dados são manipuladas de modo diferente.

Descrição

A instrução SQLBeginWork indica o início de uma unidade de trabalho SQLBeginWork indica ao mecanismo de banco de dados do SQL que ele não deve chamar SQLCommit nem SQLRollback até que você informe a ele para que o faça.

A instrução SQLCommit indica que todas as alterações feitas ao banco de dados desde a última instrução SQLBeginWork devem ser aplicadas ao banco de dados e tornadas permanentes.

A operação SQLRollback ocorre quando um dos processos definidos para a unidade de trabalho falhou. Uma instrução SQLRollback indica que todas as alterações feitas ao banco de dados desde a última instrução SQLBeginWork devem ser desfeitas.

Por exemplo, em um aplicativo de banco, uma transferência pode ser feita de uma conta de poupança para uma conta corrente do cliente. Tal transferência pode envolver a redução da coluna de saldo em uma tabela (SAVINGS_ACCOUNTS) e o aumento em uma outra tabela (CHECKING_ACCOUNTS). Isso seria um problema se uma operação fosse bem-sucedida enquanto outra falhasse. Para evitar esta possibilidade, um aplicativo orientado a transações faz o seguinte:

Exemplo

O fragmento de código que se segue ilustra os princípios discutidos anteriormente. Conforme indicado, este é um caso em que várias operações de SQL devem ser bem-sucedidas antes de consolidar as alterações no banco de dados. Especificamente, você não pretende consolidar após a primeira atualização pois o cliente será deixado com um saldo de poupança inferior e nenhum aumento compensatório no saldo da conta se a segunda atualização falhar.

PROCEDURE SavingsToCheckingTransfer( 
  VAL savings_ID: STRING, 
  VAL checking_ID: STRING, 
  VAL amount: REAL) IS 
VARIABLES 
  debited, credited: BOOLEAN; 
  balance: REAL; 
ACTIONS 
  SQLBeginWork; 
  debited := FALSE; 
   IF SQLSelectInto('SELECT BALANCE FROM 
                     SAVINGS WHERE ACCOUNT_ID=''' &
                     savings_ID & ''''  
                     ,balance) > 0 THEN 
   balance := balance - amount; 
   IF SQLUpdate('SAVINGS', 
                'ACCOUNT_ID=''' & savings_ID & 
'''', balance) > 0 THEN 
     debited := TRUE; 
END; 
END; 
  IF debited THEN 
    credited := FALSE; 
    IF SQLSelectInto('SELECT BALANCE FROM CHECKING 
                      WHERE ACCOUNT_ID=''' & 
checking_ID & '''',balance) > 
                     0 THEN 
      balance := balance + amount; 
  IF SQLUpdate('CHECKING', 
               'ACCOUNT_ID=''' & checking_ID & 
              '''' , 
balance) > 0 THEN 
      credited := TRUE; 
END; 
END; 
  IF credited THEN 
    SQLCommit; 
  ELSE 
    SQLRollback; 
END; 
 END;
END; 

Valores Desconhecidos em Colunas SQL

Como utilizar valores nulos

Quando você define uma tabela de banco de dados, pode especificar se cada coluna pode ter valores nulos. Declarar que uma coluna pode conter valores nulos significa que a coluna não tem que conter um valor. (Isto é diferente de ter um valor de cadeia vazio.)

Nota: O NULL do SQL mapeia também para suporte do TSD Script para valores desconhecidos. No TSD Script, toda variável inicia com o valor $Unknown. As variáveis de registro são uma exceção para isto: todos os campos de uma variável de registro começam com o valor $Unknown.

Como mapear valores desconhecidos

Como os valores são trocados entre o TSD Script e o SQL, o mapeamento entre $Unknown e NULL é preservado. Considere este exemplo:

SQLInsert('EMPLOYEE',r); 

Neste exemplo, se r.salary fosse $Unknown, a coluna SALARY para a linha inserida conteria um valor NULL.

Do mesmo modo, se a coluna PHONE fosse NULL para uma determinada linha, a recuperação dessa linha para uma variável de registro com SQLSelectInto ou SQLSelect/SQLFetch faria o campo de telefone dessa variável ser $Unknown.

No sistema de formulários do Developer's Toolkit, os valores nulos também são aceitos. Se um usuário deixa um campo de diálogo em branco, o campo de registro correspondente é definido para $Unknown.

Nota: Você recebe um erro se tentar inserir um valor $Unknown em uma coluna que não foi declarada para aceitar valores nulos. Isto geralmente ocorre somente quando os campos do formulário são deixados em branco.

Identificação de Erros

Nos aplicativos de negócios, grandes quantidades de código são escritas para tratar condições de erro. Após o código ser escrito, ele deve ser testado. Muitas vezes, isso significa avaliar o código de retorno de cada instrução.

O Developer's Toolkit inclui um mecanismo de identificação de erros automático que reduz a carga de identificação de erros. Isso significa que:

Como detectar mensagens de erro

Por padrão, o Developer's Toolkit detecta operações SQL malsucedidas e exibe mensagens de erro para usuários finais.

O Developer's Toolkit exibe tantas informações contextuais quanto forem possíveis para identificar a causa do erro (erro de coluna duplicada, erro de E/S, disco cheio e etc). Se o sucesso ou falha de uma operação não tiver significado, não será necessário verificar o valor de retorno. Neste caso, um novo funcionário é inserido na tabela EMPLOYEE:

SQLInsert('EMPLOYEE',r);

Como filtrar mensagens de erro

Há algumas vezes em que você deseja desativar temporariamente o recurso de mensagem de erro automática. $ErrorFilter é uma função de inteiro do sistema que permite especificar um limite de nível de erro. Os erros com níveis abaixo do limite especificado não geram mensagens de erro.

Os seguintes níveis de gravidade geram mensagens de código de erro automáticas:

Código de Gravidade de Erro Descrição
0 Erro fatal
1 Erro não-fatal
2 Mensagem de aviso
3 Mensagem informativa

Por exemplo, definir $ErrorFilter(3) significa que somente erros e avisos com um nível de código de gravidade de três ou inferior geram mensagens automáticas. Erros com um nível de código de gravidade superior não causam o aparecimento de mensagens de erro e são discerníveis somente através da examinação dos códigos de retorno da instrução.

Os níveis de código de gravidade diminuem com o aumento da gravidade. Portanto, você pode chamar ErrorFilter(0) para desativar tudo, exceto mensagens de erro fatais.

Como Utilizar Comandos para Múltiplas Execuções

Como preparar os comandos de loop do SQL

Se você pretende executar um comando SQL várias vezes em um loop, pode ser mais eficiente preparar (pré-compilar) o comando uma vez fora do loop e, em seguida, executar a forma preparada no loop.

O Developer's Toolkit permite preparar a maioria dos comandos SQL com exceção de instruções e comandos Select que não podem ser preparados dinamicamente. Consulte a documentação do SQL para obter informações sobre comandos específicos que não podem ser preparados dinamicamente.

O Developer's Toolkit fornece dois comandos para a preparação de um comando SQL:

Nota: SQLPrepare e SQLExecute são aceitos somente em DB2/2, DB2/6000 e Oracle.

Utilizar SQLPrepare e SQLExecute é como utilizar SQLExecuteImmediate exceto que a execução é adiada até que você precise dela. O exemplo a seguir mostra como inserir uma lista de novos usuários na tabela USER com a combinação SQLPrepare/SQLExecute:

FUNCTION InsertNewUsers(REF users: LIST OF 
                        STRING):INTEGER IS 
VARIABLES 
  stmt: SQLStatement; 
  retCd: INTEGER; 
ACTIONS 
  (* inserir os nomes de usuário reconhecidos *)
  retCd := SQLPrepare(stmt,'INSERT INTO USERS
                      VALUES (?)'); 
  IF retCd <= 0 THEN 
    EXIT retCd; 
END; 
  (* executar as inserções *)
  FOR users DO 
    retCd := SQLExecute(stmt,users[$current]); 
    IF retCd <= 0 THEN 
      SQLRollback; (* reverter alterações e
                    liberar bloqueios *)
      EXIT retCd; 
END; 
   END; (* para *)
  (* liberar os recursos utilizados por esta instrução
   preparada *)
  SQLCloseStatement(stmt); 
END; 

Nota: Como o TSD Script tem recursos limitados para instruções preparadas simultâneas, você precisa assegurar-se de fechar a instrução preparada chamando SQLCloseStatement.

Como substituir os marcadores de parâmetro

A substituição do marcador do parâmetro é integral para o processo de utilização de instruções preparadas. Os marcadores de parâmetro, representados por pontos de interrogação (?), são marcadores para valores que são substituídos posteriormente.

Para cada valor, um ponto de interrogação é inserido na cadeia da instrução (fornecida para SQLPrepare). As diretrizes para estes valores são:

Nota: O TSD Script não pode fornecer conversões de tipo robustas de modo igual com marcadores de parâmetro como faz com os parâmetros normais (aqueles utilizados em SQLInsert, SQLUpdate, SQLSelectInto e SQLFetch).

Instruções SQL aninhadas

Nota: Estas instruções se aplicam somente ao Sybase e Microsoft SQLServer.

Alguns DBMSs aceitam somente uma instrução SQL ativa por vez em uma conexão. Por exemplo, colocar uma instrução SQLSelectInto no corpo de um loop SQLFetch requer duas instruções SQL simultâneas com o SQLServer. O Developer's Toolkit compensa isto replicando as conexões. As conexões replicadas ou "secundárias" têm seu próprio espaço de transação.

O modelo de transação do Developer's Toolkit faz com que todas as conexões se comportem como se pertencessem a mesma transação. Embora isto seja heterodoxo (nenhum protocolo de registro de duas fases é utilizado), ele funciona confiavelmente na prática. Há um requisito existente que adia as consolidações "automáticas" implícitas até que o cursor externo seja fechado para ambientes onde os cursores abertos e as instruções preparadas são fechadas em consolidações ou retrocessos.

Em versões anteriores do Developer's Toolkit, todas as operações de SQL aninhadas ou simultâneas eram executadas dentro de uma transação. Naquelas versões, SQLBeginWork era chamado antes do cursor mais externo ser aberto e uma consolidação (ou retrocesso) tinha que ser executada quando este cursor mais externo era fechado.

Se desejasse que as instruções executassem em seus próprios espaços de transação, você tinha que abrir conexões principais adicionais com SQLCommand para as instruções.

O Developer's Toolkit 6.0 não requer mais o reinício cíclico de transações para execução de instruções simultâneas no modo de consolidação "manual". No entanto, o reinício cíclico de transações é ainda requerido ao utilizar o modo de consolidação "automática" se o DBMS não permitir que os cursores estendam as transações.

Devido as complexidades e efeitos secundários envolvidos com instruções SQL aninhadas (como sobrecarga de conexão, o potencial de bloqueio ao acessar a mesma tabela a partir de duas conexões em espaços de transação diferentes e etc), recomendamos rigorosamente que você evite-as onde for possível.

É quase sempre possível dividir as operações SQL em duas partes:

Além de evitar vários efeitos secundários de instruções aninhadas, esta abordagem tem a vantagem de concorrência aumentada porque você não é forçado a executar as operações dentro de uma transação. No entanto, dependendo do aplicativo, você pode ainda precisar de uma transação para a segunda parte.


Tivoli Service Desk 6.0 Developer's Toolkit - Guia de Programação do Script

Retornar ao Índice

Copyright