| Bellacosa Mainframe e o spufi sem misterios |
☕ Um Café no Bellacosa Mainframe
SPUFI sem Mistérios: do Primeiro SELECT ao Dataset de Saída no Db2 for z/OS
O guia do programador COBOL Padawan para entender SQL, datasets, isolamento, CCSID, commit, JCL e tudo o que acontece por trás da tela verde
Imagine a cena.
Você acabou de entrar no TSO, abriu o ISPF, navegou até o DB2I e escolheu a opção SPUFI. Diante de você aparece aquela clássica tela preta, com letras verdes e azuis, campos numerados e algumas opções que parecem inocentes:
EDIT INPUT . . . . ===> YES
EXECUTE . . . . . . ===> YES
AUTOCOMMIT . . . . . ===> YES
BROWSE OUTPUT . . . ===> YES
O programador COBOL Padawan olha para aquilo e pensa:
“Eu só queria executar um SELECT. Por que preciso informar dataset, volume, senha, isolamento, formato, espaço primário, espaço secundário, LRECL, BLKSIZE e CCSID?”
Essa pergunta é perfeita.
Ela revela uma diferença fundamental entre o mundo distribuído e o universo IBM Mainframe.
Em muitas ferramentas modernas, você abre uma janela, digita SQL e recebe o resultado em uma grade gráfica. No z/OS, entretanto, cada etapa foi construída para ser explícita, controlável, auditável e reutilizável. O SPUFI não trabalha apenas com uma “caixa de texto”. Ele trabalha com datasets reais, parâmetros de execução, formatos de registro, controle transacional e integração direta com o subsistema Db2.
O SPUFI é simples na aparência, mas por trás daquela tela existe uma pequena cadeia de processamento digna de uma aplicação batch.
Prepare o café, abra o caderno de anotações e ajuste os óculos de programador Jedi. Vamos desmontar o SPUFI peça por peça.
| Bellacosa Mainframe o que é o Spufi? |
1. O que é SPUFI?
SPUFI significa:
SQL Processor Using File Input
Em uma tradução livre:
Processador SQL usando um arquivo como entrada.
Esse nome descreve exatamente o que a ferramenta faz.
O SPUFI:
lê comandos SQL de um dataset;
envia esses comandos ao Db2;
recebe o resultado;
grava as mensagens e linhas retornadas em outro dataset;
opcionalmente abre o resultado para consulta.
Seu fluxo básico é:
Programador
|
v
Dataset com SQL
|
v
SPUFI
|
v
Plano/Pacote do DB2I
|
v
Subsistema Db2
|
v
Parser + Otimizador + Executor
|
v
Dataset de saída
Perceba um detalhe importante: o SPUFI não é o banco de dados, nem o otimizador e nem o mecanismo responsável por acessar as tabelas.
Ele é uma interface.
Quem realmente valida, otimiza e executa o SQL é o Db2.
2. Por que o SPUFI continua importante?
Mesmo existindo ferramentas gráficas, IDEs, plugins para VS Code, interfaces web e utilitários distribuídos, o SPUFI continua extremamente útil porque:
executa SQL diretamente dentro do ambiente z/OS;
usa a autenticação do usuário TSO;
acessa o subsistema Db2 local;
não depende de configuração ODBC ou JDBC externa;
grava a entrada e a saída em datasets;
facilita auditoria e repetição dos testes;
funciona bem em ambientes restritos;
é familiar para DBAs, sysprogs e desenvolvedores veteranos.
Além disso, o SPUFI é uma excelente escola.
Quem aprende SPUFI acaba aprendendo, mesmo sem perceber:
PDS e membros;
datasets sequenciais;
atributos DCB;
alocação em DASD;
CCSID;
terminadores SQL;
níveis de isolamento;
commits;
planos e pacotes;
códigos SQL;
organização de scripts.
Portanto, o SPUFI não é apenas uma ferramenta antiga. Ele é uma ponte entre SQL e a cultura operacional do mainframe.
3. A primeira tela: o painel principal do SPUFI
Na tela mostrada, temos algo semelhante a:
SPUFI SSID: DB9G
Enter the input data set name:
1 DATA SET NAME ... ===> 'IBMUSER.WORKBOOK.SQL(SELCOPA)'
2 VOLUME SERIAL .... ===>
3 DATA SET PASSWORD ===>
Enter the output data set name:
4 DATA SET NAME ... ===> 'INEFE00.OUTPUT.SAIDA'
Specify processing options:
5 CHANGE DEFAULTS .. ===> YES
6 EDIT INPUT ....... ===> YES
7 EXECUTE .......... ===> YES
8 AUTOCOMMIT ....... ===> YES
9 BROWSE OUTPUT .... ===> YES
For remote SQL processing:
10 CONNECT LOCATION . ===>
No canto superior direito aparece:
SSID: DB9G
SSID significa Subsystem Identifier.
É o identificador do subsistema Db2 ao qual o DB2I está conectado.
Em uma instalação, podem existir vários subsistemas:
DB2D Desenvolvimento
DB2T Testes
DB2H Homologação
DB2P Produção
DB9G Laboratório ou ambiente específico
O nome não possui significado universal. Cada empresa define sua convenção.
Um Padawan deve sempre observar o SSID antes de executar qualquer comando destrutivo.
Um DELETE no ambiente errado pode transformar uma aula tranquila em uma reunião extraordinária com DBA, gestor, auditoria, segurança e provavelmente alguém perguntando por que não havia WHERE.
4. Campo 1 — DATA SET NAME de entrada
No exemplo:
'IBMUSER.WORKBOOK.SQL(SELCOPA)'
Esse nome possui duas partes:
IBMUSER.WORKBOOK.SQL
É o dataset.
SELCOPA
É o membro.
Isso indica que o dataset provavelmente é um PDS ou PDSE.
Podemos visualizá-lo como uma pasta:
IBMUSER.WORKBOOK.SQL
|
+-- SELCOPA
+-- SELCLIENT
+-- UPDTEST
+-- CREATE01
+-- JOIN001
Cada membro contém um ou mais comandos SQL.
Por exemplo, o membro SELCOPA pode conter:
SELECT EMPNO,
FIRSTNME,
LASTNAME,
WORKDEPT
FROM DSN8C10.EMP
WHERE WORKDEPT = 'A00'
ORDER BY LASTNAME;
Por que usar um PDS ou PDSE?
Porque ele permite organizar vários scripts dentro do mesmo dataset.
Uma estrutura interessante seria:
IBMUSER.DB2.SQL
|
+-- SEL001
+-- SEL002
+-- INS001
+-- UPD001
+-- DEL001
+-- DDL001
+-- EXPLAIN
+-- CATALOG
É como possuir uma biblioteca de scripts SQL, só que usando a estrutura tradicional do z/OS.
PDS ou PDSE?
Os dois funcionam, mas o PDSE costuma ser preferível em ambientes modernos porque:
não exige compressão;
reutiliza espaço interno de forma mais eficiente;
possui melhor gerenciamento de diretório;
reduz alguns problemas clássicos de fragmentação.
5. Criando o dataset de entrada
Você pode criar o dataset pelo ISPF 3.2 ou por JCL.
Exemplo:
//CRIASQL JOB (ACCT),'CRIA PDS SQL',
// CLASS=A,
// MSGCLASS=X,
// NOTIFY=&SYSUID
//*
//ALLOC EXEC PGM=IEFBR14
//SQLLIB DD DSN=IBMUSER.WORKBOOK.SQL,
// DISP=(NEW,CATLG,DELETE),
// UNIT=SYSDA,
// SPACE=(TRK,(2,2,20)),
// DCB=(DSORG=PO,RECFM=FB,LRECL=80,BLKSIZE=0)
//
Agora vamos explicar cada linha.
JOB
//CRIASQL JOB (ACCT),'CRIA PDS SQL',
Define o início do job.
CRIASQLé o nome do job;(ACCT)é a informação contábil;'CRIA PDS SQL'é uma descrição.
CLASS
// CLASS=A,
Indica a classe de execução.
A classe controla aspectos como:
fila;
prioridade;
recursos;
regras locais de execução.
MSGCLASS
// MSGCLASS=X,
Indica a classe de saída das mensagens JES.
NOTIFY
// NOTIFY=&SYSUID
Solicita que o usuário que submeteu o job seja notificado quando ele terminar.
EXEC PGM=IEFBR14
//ALLOC EXEC PGM=IEFBR14
IEFBR14 é um programa praticamente vazio, tradicionalmente usado para permitir que o sistema processe instruções DD.
Ele não “cria” o dataset diretamente. Quem faz a alocação é o gerenciamento de datasets do z/OS ao interpretar a DD com DISP=NEW.
Esse é um dos grandes easter eggs do mainframe: um programa que praticamente não faz nada tornou-se uma das peças mais famosas do JCL.
DSN
//SQLLIB DD DSN=IBMUSER.WORKBOOK.SQL,
Define o nome do dataset.
DISP
// DISP=(NEW,CATLG,DELETE),
Significa:
NEW: o dataset será criado;CATLG: se o step terminar normalmente, será catalogado;DELETE: se houver falha, será excluído.
UNIT
// UNIT=SYSDA,
Solicita uma unidade DASD genérica.
SPACE
// SPACE=(TRK,(2,2,20)),
Significa:
unidade de alocação: tracks;
espaço primário: 2 tracks;
espaço secundário: 2 tracks;
diretório: 20 blocos.
O terceiro valor é relevante porque o dataset é particionado.
DCB
// DCB=(DSORG=PO,RECFM=FB,LRECL=80,BLKSIZE=0)
DSORG=PO: organização particionada;RECFM=FB: registros fixos blocados;LRECL=80: cada registro possui 80 bytes;BLKSIZE=0: o sistema escolhe um tamanho de bloco adequado.
O formato FB 80 é clássico para código-fonte, JCL e scripts SQL.
6. Campo 2 — VOLUME SERIAL
VOLUME SERIAL ===>
Esse campo normalmente fica em branco quando o dataset está catalogado.
O catálogo do z/OS já informa em qual volume ele reside.
Você só precisa preencher o VOLSER quando trabalha com um dataset não catalogado ou quando há uma razão operacional específica.
Exemplo:
VOLUME SERIAL ===> VOL001
Na maioria dos ambientes modernos, deixar em branco é correto.
7. Campo 3 — DATA SET PASSWORD
DATA SET PASSWORD ===>
Esse campo remete a mecanismos antigos de proteção por senha de dataset.
Atualmente, o acesso normalmente é controlado por um produto de segurança como:
RACF;
ACF2;
Top Secret.
Em ambientes modernos, esse campo quase sempre permanece vazio.
É quase uma peça arqueológica viva: continua presente porque o mainframe preserva compatibilidade com décadas de história.
8. Campo 4 — dataset de saída
No exemplo:
'INEFE00.OUTPUT.SAIDA'
A tela informa:
Must be a sequential data set
Isso significa que o dataset de saída deve ser sequencial.
O SPUFI grava:
o SQL executado;
mensagens do Db2;
SQLCODE;
SQLSTATE;
linhas retornadas;
quantidade de registros;
informações de commit;
eventuais erros.
Exemplo de saída:
---------+---------+---------+---------+---------+---------
SELECT EMPNO, FIRSTNME, LASTNAME
FROM DSN8C10.EMP
WHERE WORKDEPT = 'A00';
EMPNO FIRSTNME LASTNAME
------ ------------ ---------------
000010 CHRISTINE HAAS
000110 VINCENZO LUCCHESSI
000120 SEAN O'CONNELL
DSNE610I NUMBER OF ROWS DISPLAYED IS 3
DSNE616I STATEMENT EXECUTION WAS SUCCESSFUL, SQLCODE IS 0
Criando o dataset de saída
//CRIAOUT JOB (ACCT),'CRIA SAIDA SPUFI',
// CLASS=A,
// MSGCLASS=X,
// NOTIFY=&SYSUID
//*
//ALLOC EXEC PGM=IEFBR14
//OUTPUT DD DSN=IBMUSER.OUTPUT.SPUFI,
// DISP=(NEW,CATLG,DELETE),
// UNIT=SYSDA,
// SPACE=(TRK,(5,5)),
// DCB=(DSORG=PS,RECFM=VB,LRECL=4092,BLKSIZE=0)
//
Aqui temos:
DSORG=PS
Physical Sequential, ou seja, sequencial.
RECFM=VB
Registros variáveis e blocados.
LRECL=4092
Permite linhas grandes de saída.
BLKSIZE=0
O sistema calcula um valor apropriado.
9. Campo 5 — CHANGE DEFAULTS
CHANGE DEFAULTS ===> YES
Com YES, o SPUFI abre a tela de parâmetros padrão.
Com NO, utiliza os valores já salvos no perfil do usuário ou na configuração da instalação.
Essa opção é útil quando você precisa alterar:
nível de isolamento;
número máximo de linhas;
terminador SQL;
atributos do dataset de saída;
largura das colunas;
formato dos cabeçalhos.
Para uma consulta simples, você pode usar NO.
Para aprender ou ajustar comportamento, use YES.
10. Campo 6 — EDIT INPUT
EDIT INPUT ===> YES
Com YES, o SPUFI abre o membro de entrada no editor ISPF antes da execução.
O fluxo será:
SPUFI
|
+--> abre ISPF Edit
|
+--> você grava o SQL
|
+--> pressiona PF3
|
+--> SPUFI executa
Com NO, ele executa diretamente o conteúdo atual do dataset.
Isso é útil quando o script já está pronto e não precisa ser revisado.
Exemplo de SQL para iniciantes
SELECT CURRENT DATE,
CURRENT TIME,
CURRENT TIMESTAMP
FROM SYSIBM.SYSDUMMY1;
A tabela SYSIBM.SYSDUMMY1 é uma tabela especial com uma única linha, muito usada para testar expressões.
É o equivalente Db2 de uma pequena bancada de laboratório.
11. Campo 7 — EXECUTE
EXECUTE ===> YES
Com YES, o SQL será enviado ao Db2.
Com NO, o SPUFI pode permitir que você apenas edite o input sem executar.
Parece inútil, mas é interessante quando o SPUFI está sendo usado apenas como uma forma rápida de localizar e modificar um membro SQL.
12. Campo 8 — AUTOCOMMIT
AUTOCOMMIT ===> YES
Esse é um dos campos mais perigosos da tela.
Com YES, o SPUFI confirma automaticamente uma unidade de trabalho bem-sucedida.
Exemplo:
UPDATE CORP.CLIENTE
SET STATUS = 'I'
WHERE CLIENTE_ID = 100;
Se o comando funcionar e AUTOCOMMIT=YES, a alteração será confirmada.
Um ROLLBACK posterior não desfará essa atualização.
Para SELECT
Em consultas, o risco é pequeno.
Para INSERT, UPDATE e DELETE
Atenção máxima.
Durante testes, uma prática mais segura é:
AUTOCOMMIT ===> NO
E incluir comandos explícitos:
UPDATE CORP.CLIENTE
SET STATUS = 'I'
WHERE CLIENTE_ID = 100;
SELECT CLIENTE_ID,
STATUS
FROM CORP.CLIENTE
WHERE CLIENTE_ID = 100;
ROLLBACK;
Assim você verifica o resultado e depois desfaz.
Quando estiver absolutamente certo:
UPDATE CORP.CLIENTE
SET STATUS = 'I'
WHERE CLIENTE_ID = 100;
COMMIT;
Cuidado especial com DELETE
Nunca execute casualmente:
DELETE FROM CORP.CLIENTE;
Sem WHERE, todas as linhas elegíveis podem ser removidas.
Antes de executar um DELETE, transforme-o em SELECT:
SELECT *
FROM CORP.CLIENTE
WHERE STATUS = 'I';
Confira a quantidade.
Depois:
DELETE
FROM CORP.CLIENTE
WHERE STATUS = 'I';
Esse pequeno ritual salva carreiras.
13. Campo 9 — BROWSE OUTPUT
BROWSE OUTPUT ===> YES
Com YES, o dataset de saída é aberto automaticamente após a execução.
Com NO, o resultado é gravado, mas você precisará abri-lo manualmente.
Por exemplo, usando:
ISPF 3.4
ou um comando:
BROWSE 'IBMUSER.OUTPUT.SPUFI'
Usar YES é conveniente para testes interativos.
Usar NO pode ser útil quando o resultado é muito grande ou quando o processamento será revisado posteriormente.
14. Campo 10 — CONNECT LOCATION
CONNECT LOCATION ===>
Esse campo permite direcionar a execução para uma localização Db2 remota.
Em ambientes distribuídos, o Db2 pode usar DRDA para comunicação entre subsistemas.
Exemplo conceitual:
Db2 local DB2D
|
| DRDA
v
Db2 remoto DB2P
O valor usado depende da configuração de localização no catálogo Db2.
Para consultas locais, deixe em branco.
15. O aviso DSNE345I e a guerra dos CCSIDs
Na segunda tela aparece:
DSNE345I WARNING: DB2 DATA CORRUPTION CAN RESULT
FROM THIS SPUFI SESSION BECAUSE THE
CCSID USED BY THE TERMINAL IS NOT THE
SAME AS THE CCSID USED BY SPUFI
TERMINAL CCSID: 37
SPUFI CCSID : 1047
Esse não é um simples aviso cosmético.
CCSID significa:
Coded Character Set Identifier
Ele identifica a tabela de codificação de caracteres.
No mundo z/OS, “EBCDIC” não é uma única tabela universal. Existem diferentes variantes.
Entre elas:
CCSID 37;
CCSID 500;
CCSID 1047;
CCSID 1140.
O terminal está usando CCSID 37, enquanto o SPUFI espera 1047.
Caracteres alfabéticos simples podem aparecer corretamente, mas símbolos especiais podem ocupar posições diferentes.
Os maiores suspeitos são caracteres como:
[
]
{
}
|
\
^
~
Imagine uma expressão SQL com texto:
INSERT INTO TESTE.TABELA
(DESCRICAO)
VALUES ('ARQUIVO [TEMP]');
Se houver conversão incorreta, os colchetes podem ser gravados como outros símbolos.
Em um SELECT, você pode apenas ver uma saída estranha.
Em um INSERT ou UPDATE, porém, dados incorretos podem ser persistidos.
O que fazer?
O aviso diz:
NOTIFY THE DB2 SYSTEM ADMINISTRATOR
Isso significa que a solução definitiva normalmente envolve revisar:
configuração do emulador 3270;
code page da sessão;
parâmetros do DB2I;
CCSID do subsistema;
perfil do usuário;
configuração do SPUFI.
No emulador TN3270, procure opções relacionadas a:
host code page;
EBCDIC code page;
character set;
CCSID;
language;
keyboard mapping.
Não altere aleatoriamente em produção. Uma mudança incorreta pode resolver um símbolo e quebrar outro.
16. A tela CURRENT SPUFI DEFAULTS
A terceira tela apresenta os parâmetros internos do SPUFI.
CURRENT SPUFI DEFAULTS
Vamos examinar cada um.
17. SQL TERMINATOR
SQL TERMINATOR ===> ;
O ponto e vírgula indica o fim de cada instrução SQL.
Exemplo:
SELECT COUNT(*)
FROM SYSIBM.SYSTABLES;
Vários comandos:
SELECT CURRENT DATE
FROM SYSIBM.SYSDUMMY1;
SELECT CURRENT TIME
FROM SYSIBM.SYSDUMMY1;
Alterando o terminador
Em alguns scripts, especialmente com rotinas SQL PL, o ponto e vírgula também aparece dentro de blocos.
Pode ser conveniente trocar o terminador externo:
SQL TERMINATOR ===> #
Então:
CREATE PROCEDURE TESTE.PROC1()
LANGUAGE SQL
BEGIN
INSERT INTO TESTE.LOG
VALUES (CURRENT TIMESTAMP);
UPDATE TESTE.CONTROLE
SET STATUS = 'F';
END
#
O # encerra a instrução completa, enquanto os pontos e vírgulas continuam dentro do bloco.
18. ISOLATION LEVEL
Na tela:
ISOLATION LEVEL ===> CS
Os valores mais comuns são:
UR
CS
RS
RR
UR — Uncommitted Read
É a leitura com menor compromisso de consistência.
Permite ler dados que outra transação modificou, mas ainda não confirmou.
Exemplo:
SELECT *
FROM CORP.MOVIMENTO
WITH UR;
Vantagens:
poucos locks;
boa concorrência;
útil para relatórios não críticos.
Riscos:
dirty read;
dados podem desaparecer após rollback;
totais podem não representar um estado confirmado.
Use UR para consultas informativas, nunca como base cega para decisões financeiras ou atualizações dependentes.
CS — Cursor Stability
É o valor mostrado na tela.
O Db2 protege a linha atualmente posicionada pelo cursor e libera locks conforme a navegação, dependendo do plano e da execução.
É um bom equilíbrio entre:
consistência;
concorrência;
desempenho.
É muito comum em aplicações online.
RS — Read Stability
Garante maior estabilidade para as linhas qualificadas já lidas.
Evita que elas sejam modificadas de forma conflitante durante a unidade de trabalho.
Pode manter mais locks.
RR — Repeatable Read
É o nível mais restritivo.
A mesma consulta dentro da unidade de trabalho tende a reencontrar um conjunto estável de linhas, de acordo com as regras do isolamento.
Pode gerar:
muitos locks;
contenção;
timeout;
deadlock;
escalonamento de locks.
Comparação conceitual
| Isolamento | Consistência | Concorrência | Locks |
|---|---|---|---|
| UR | baixa | muito alta | mínimos |
| CS | equilibrada | alta | moderados |
| RS | alta | média | maiores |
| RR | muito alta | menor | elevados |
19. MAX SELECT LINES
MAX SELECT LINES ===> 250
Esse parâmetro limita a quantidade de linhas exibidas pelo SPUFI.
Ele funciona como um cinto de segurança.
Imagine:
SELECT *
FROM SYSIBM.SYSCOLUMNS;
Dependendo do ambiente, isso pode retornar milhares de linhas.
O SPUFI interrompe a exibição ao atingir o limite configurado.
Atenção: isso não significa necessariamente que o Db2 sempre acessará apenas 250 linhas em todas as circunstâncias. O limite controla principalmente o processamento e apresentação do resultado pelo SPUFI.
Para consultas grandes, prefira filtros:
SELECT NAME,
CREATOR,
TYPE
FROM SYSIBM.SYSTABLES
WHERE CREATOR = 'IBMUSER'
ORDER BY NAME;
20. ALLOW SQL WARNINGS
ALLOW SQL WARNINGS ===> NO
SQL warnings são avisos que não representam necessariamente falha fatal.
O SQLCA pode trazer:
SQLCODE positivo
Exemplos comuns incluem:
truncamento;
eliminação de valores nulos em agregações;
nenhuma linha em certas operações;
condições especiais de processamento.
Com NO, o SPUFI pode interromper ou tratar de maneira mais conservadora.
Com YES, ele pode continuar buscando linhas após avisos.
Para aprendizado, deixar NO ajuda a perceber que algo especial ocorreu.
21. CHANGE PLAN NAMES
CHANGE PLAN NAMES ===> NO
O SPUFI executa sob estruturas Db2 previamente definidas, incluindo planos e pacotes do DB2I.
Essa opção permite trabalhar com nomes alternativos em configurações específicas.
Para o programador iniciante, a recomendação é manter:
NO
Alterar planos exige conhecimento de:
BIND;
PACKAGE;
PLAN;
COLLECTION;
autorização;
compatibilidade do ambiente.
22. SQL FORMAT
SQL FORMAT ===> SQL
Esse campo define o tratamento do conteúdo SQL.
As opções podem variar conforme versão e configuração, mas geralmente distinguem formatos como:
SQL convencional;
SQL com comentários;
SQL PL.
Para consultas normais:
SQL
é suficiente.
23. SPACE UNIT
SPACE UNIT ===> TRK
Define a unidade usada para alocar o dataset de saída.
Valores comuns:
TRK
CYL
TRK significa track.
CYL significa cylinder.
Para resultados pequenos, tracks são suficientes.
Para saídas muito grandes, cylinders podem ser mais apropriados.
24. PRIMARY SPACE e SECONDARY SPACE
PRIMARY SPACE ===> 6
SECONDARY SPACE ===> 5
O espaço primário é alocado inicialmente.
O secundário é solicitado quando o espaço inicial se esgota.
Neste exemplo:
SPACE=(TRK,(6,5))
Conceitualmente:
aloque 6 tracks inicialmente;
quando necessário, expanda em blocos de 5 tracks.
Muitas extensões pequenas podem causar fragmentação e atingir limites de extents.
Por outro lado, uma alocação primária exagerada desperdiça espaço.
O tamanho ideal depende do volume esperado.
25. RECORD LENGTH
RECORD LENGTH ===> 4092
É o LRECL do dataset de saída.
Como o resultado pode incluir colunas extensas, o SPUFI usa registros largos.
Um VARCHAR(2000) ou a combinação de várias colunas pode exigir linhas grandes.
Se o LRECL for pequeno demais, a saída pode ser truncada ou a alocação pode falhar, dependendo do cenário.
26. BLOCK SIZE
BLOCK SIZE ===> 4096
O BLKSIZE indica o tamanho dos blocos físicos usados na gravação.
Blocos reduzem a quantidade de operações de I/O.
Em alocações modernas, frequentemente usamos:
BLKSIZE=0
para permitir que o sistema determine um valor eficiente.
Na tela do SPUFI, valores predefinidos podem ser usados conforme a configuração local.
27. RECORD FORMAT
RECORD FORMAT ===> VB
VB significa:
Variable Blocked
Os registros possuem tamanho variável e são agrupados em blocos.
Isso é apropriado para resultados SQL, porque uma linha pode ter 20 bytes e outra 800 bytes.
Outros formatos citados na tela:
F
FB
FBA
V
VB
VBA
F: fixo;FB: fixo blocado;FBA: fixo blocado com controle ASA;V: variável;VB: variável blocado;VBA: variável blocado com controle ASA.
28. DEVICE TYPE
DEVICE TYPE ===> SYSDA
SYSDA é um nome genérico de unidade DASD.
O sistema e o SMS determinam o volume apropriado.
Em ambientes gerenciados por SMS, vários parâmetros físicos podem ser escolhidos automaticamente por classes de armazenamento.
29. MAX NUMERIC FIELD
MAX NUMERIC FIELD ===> 33
Define a largura máxima usada para apresentar campos numéricos.
Isso evita que números muito extensos destruam o alinhamento da saída.
Por exemplo:
SELECT DECIMAL(12345678901234567890,20,0)
FROM SYSIBM.SYSDUMMY1;
A configuração controla quanto espaço poderá ser reservado para exibição.
30. MAX CHAR FIELD
MAX CHAR FIELD ===> 80
Define a largura máxima de apresentação das colunas de caracteres.
Imagine uma coluna:
DESCRICAO VARCHAR(1000)
Sem limite, uma única coluna tornaria a saída enorme.
Com máximo 80, a apresentação fica mais administrável.
Atenção: isso pode significar que você não verá todo o conteúdo visualmente na linha formatada.
Quando precisar analisar o valor integral, selecione a coluna isoladamente ou use funções como:
SELECT LENGTH(DESCRICAO),
SUBSTR(DESCRICAO,1,200)
FROM TESTE.PRODUTO;
31. COLUMN HEADING
COLUMN HEADING ===> NAMES
Opções comuns:
NAMES
LABELS
ANY
BOTH
NAMES
Usa o nome técnico da coluna.
CUST_ID
CUST_NAME
LABELS
Usa o label definido no catálogo, se existir.
Código do Cliente
Nome do Cliente
BOTH
Pode mostrar nome e label.
Para desenvolvedores, NAMES costuma ser mais útil porque corresponde ao SQL e ao DCLGEN.
Para relatórios destinados a usuários, labels podem ser mais amigáveis.
32. Primeiro laboratório SPUFI: SELECT simples
Crie um membro chamado TESTE01 com:
SELECT CURRENT SERVER AS SERVIDOR,
CURRENT DATE AS DATA_ATUAL,
CURRENT TIME AS HORA_ATUAL,
CURRENT TIMESTAMP AS TIMESTAMP_ATUAL
FROM SYSIBM.SYSDUMMY1;
Configure:
EDIT INPUT YES
EXECUTE YES
AUTOCOMMIT YES
BROWSE OUTPUT YES
Pressione Enter.
O fluxo será:
o SPUFI abre o editor;
você confere o SQL;
pressiona PF3;
o Db2 recebe o comando;
o parser verifica a sintaxe;
o otimizador prepara a execução;
a tabela especial é acessada;
o resultado retorna;
o SPUFI formata a saída;
o dataset de saída é aberto.
33. Segundo laboratório: consultar o catálogo
SELECT CREATOR,
NAME,
TYPE
FROM SYSIBM.SYSTABLES
WHERE CREATOR = 'IBMUSER'
ORDER BY NAME;
O catálogo Db2 é um conjunto de tabelas que descreve os objetos do banco.
Ele contém informações sobre:
tabelas;
colunas;
índices;
tablespaces;
pacotes;
planos;
privilégios;
estatísticas.
Consultar o catálogo é como abrir o mapa interno do reino Db2.
34. Terceiro laboratório: UPDATE seguro com ROLLBACK
SELECT CLIENTE_ID,
STATUS
FROM TESTE.CLIENTE
WHERE CLIENTE_ID = 100;
UPDATE TESTE.CLIENTE
SET STATUS = 'I'
WHERE CLIENTE_ID = 100;
SELECT CLIENTE_ID,
STATUS
FROM TESTE.CLIENTE
WHERE CLIENTE_ID = 100;
ROLLBACK;
SELECT CLIENTE_ID,
STATUS
FROM TESTE.CLIENTE
WHERE CLIENTE_ID = 100;
Configure:
AUTOCOMMIT ===> NO
A sequência demonstra:
estado inicial;
alteração;
estado dentro da unidade de trabalho;
rollback;
restauração do valor anterior.
Esse é um excelente laboratório para compreender transações.
35. Executando SQL no Db2 por JCL
O SPUFI é interativo, mas o SQL também pode ser executado em batch usando o utilitário DSNTEP2 ou DSNTEP4, dependendo da instalação.
Exemplo:
//SQLBATCH JOB (ACCT),'EXECUTA SQL',
// CLASS=A,
// MSGCLASS=X,
// NOTIFY=&SYSUID
//*
//STEP01 EXEC PGM=IKJEFT01,DYNAMNBR=20
//STEPLIB DD DISP=SHR,DSN=DSN.V13R1M0.SDSNLOAD
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN DD *
DSN SYSTEM(DB9G)
RUN PROGRAM(DSNTEP2) PLAN(DSNTEP13) -
LIB('DSN.V13R1M0.RUNLIB.LOAD')
END
/*
//SYSIN DD *
SELECT CURRENT SERVER,
CURRENT DATE,
CURRENT TIME
FROM SYSIBM.SYSDUMMY1;
SELECT COUNT(*) AS TOTAL_TABELAS
FROM SYSIBM.SYSTABLES;
/*
IKJEFT01
//STEP01 EXEC PGM=IKJEFT01
IKJEFT01 permite executar comandos TSO em batch.
É como criar uma sessão TSO controlada pelo JCL.
DYNAMNBR
DYNAMNBR=20
Reserva capacidade para alocações dinâmicas.
STEPLIB
//STEPLIB DD DISP=SHR,DSN=DSN.V13R1M0.SDSNLOAD
Aponta para a biblioteca de load modules do Db2.
O nome real varia conforme a instalação.
SYSTSIN
DSN SYSTEM(DB9G)
Inicia o command processor do Db2 e conecta ao subsistema DB9G.
RUN PROGRAM(DSNTEP2)
Executa o programa DSNTEP2.
PLAN(DSNTEP13)
Informa o plano associado.
O nome também varia conforme versão e instalação.
LIB('DSN.V13R1M0.RUNLIB.LOAD')
Informa a biblioteca onde o programa será localizado.
SYSIN
Contém os comandos SQL.
Assim, a lógica lembra o SPUFI:
SPUFI DSNTEP2
------ -------
Dataset input SYSIN
Execução interativa Execução batch
Dataset output SYSPRINT
Tela ISPF JES/SDSF
36. JCL usando SQL em dataset externo
Em vez de escrever SQL dentro do JCL:
//SYSIN DD *
SELECT ...
/*
podemos usar um membro:
//SYSIN DD DISP=SHR,DSN=IBMUSER.WORKBOOK.SQL(SELCOPA)
Job completo:
//SQLBATCH JOB (ACCT),'SQL VIA PDS',
// CLASS=A,
// MSGCLASS=X,
// NOTIFY=&SYSUID
//*
//STEP01 EXEC PGM=IKJEFT01,DYNAMNBR=20
//STEPLIB DD DISP=SHR,DSN=DSN.V13R1M0.SDSNLOAD
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN DD *
DSN SYSTEM(DB9G)
RUN PROGRAM(DSNTEP2) PLAN(DSNTEP13) -
LIB('DSN.V13R1M0.RUNLIB.LOAD')
END
/*
//SYSIN DD DISP=SHR,DSN=IBMUSER.WORKBOOK.SQL(SELCOPA)
//
Essa estrutura permite usar o mesmo membro:
no SPUFI;
em batch;
em processos automatizados;
em pipelines;
em testes de implantação.
37. Erros comuns e possíveis soluções
SQLCODE -204
Objeto não encontrado.
Exemplo:
SQLCODE = -204
Possíveis causas:
tabela inexistente;
schema incorreto;
nome não qualificado;
ambiente errado.
Solução:
SELECT CREATOR,
NAME
FROM SYSIBM.SYSTABLES
WHERE NAME = 'CLIENTE';
Use o nome qualificado:
SELECT *
FROM CORP.CLIENTE;
SQLCODE -206
Coluna não encontrada.
Possíveis causas:
erro de digitação;
coluna pertence a outra tabela;
alias incorreto.
Verifique:
SELECT NAME,
COLNO,
COLTYPE
FROM SYSIBM.SYSCOLUMNS
WHERE TBNAME = 'CLIENTE'
AND TBCREATOR = 'CORP';
SQLCODE -104
Erro de sintaxe.
Exemplo incorreto:
SELECT NOME
CLIENTE;
Faltou FROM.
Correto:
SELECT NOME
FROM CLIENTE;
SQLCODE -551
Usuário sem autorização.
Pode faltar:
SELECT;
INSERT;
UPDATE;
DELETE;
EXECUTE;
uso de package ou plan.
A solução deve ser tratada com o administrador de segurança ou DBA.
SQLCODE -811
Um SELECT INTO retornou mais de uma linha.
No SPUFI isso aparece principalmente em testes de SQL que posteriormente serão usados em COBOL.
A consulta deveria retornar uma linha, mas encontrou várias.
Use filtro mais seletivo ou cursor.
SQLCODE -911
Rollback causado por deadlock ou timeout.
O Db2 desfez a unidade de trabalho.
Possíveis ações:
reduzir duração da transação;
acessar tabelas em ordem consistente;
melhorar índices;
revisar isolamento;
executar commit mais frequente;
investigar concorrência.
SQLCODE -913
Deadlock ou timeout sem rollback automático completo em certos contextos.
Exige análise semelhante ao -911.
38. SPUFI e programas COBOL
O SQL testado no SPUFI pode ser levado para um programa COBOL.
SPUFI:
SELECT FIRSTNME,
LASTNAME
FROM DSN8C10.EMP
WHERE EMPNO = '000010';
COBOL:
EXEC SQL
SELECT FIRSTNME,
LASTNAME
INTO :WS-FIRST-NAME,
:WS-LAST-NAME
FROM DSN8C10.EMP
WHERE EMPNO = :WS-EMPNO
END-EXEC.
A diferença está nas host variables:
:WS-FIRST-NAME
:WS-LAST-NAME
:WS-EMPNO
O SPUFI ajuda a validar:
nomes de tabela;
nomes de coluna;
joins;
filtros;
funções;
acesso esperado.
Mas ele não substitui os testes dentro do programa COBOL, porque o programa ainda envolve:
tipos de dados;
variáveis indicadoras;
SQLCA;
cursores;
commit;
lógica de tratamento de erro;
concorrência;
package e bind.
39. Curiosidades e easter eggs
O SPUFI é mais “batch” do que parece
Apesar de ser usado interativamente, sua lógica é baseada em arquivos de entrada e saída.
Ele se parece com uma pequena rotina batch controlada por painéis ISPF.
O dataset é parte da documentação
Como o SQL permanece salvo no PDS, ele pode servir como:
evidência de teste;
histórico;
material de treinamento;
script reutilizável;
base de automação.
O catálogo é o “Google interno” do Db2
Quando você não sabe se uma tabela existe, qual é a coluna, quem criou um índice ou qual package está ligado, o catálogo geralmente possui a resposta.
IEFBR14 não cria datasets sozinho
O programa é apenas uma moldura. A alocação ocorre pela interpretação do JCL.
Um SELECT também pode causar impacto
Muitos iniciantes acreditam que SELECT é sempre inofensivo.
Não é.
Um SELECT ruim pode:
fazer tablespace scan;
consumir CPU;
ler milhões de páginas;
ocupar buffer pools;
segurar locks;
gerar sort;
afetar outros usuários.
Leitura também é trabalho.
WITH UR não é magia de desempenho
Ele reduz locking de leitura, mas não corrige:
falta de índice;
predicado não indexável;
join ruim;
cardinalidade incorreta;
estatísticas antigas.
40. Checklist do Padawan antes de pressionar Enter
Antes de executar:
1. Estou no SSID correto?
2. O dataset de entrada é o membro correto?
3. O output pode ser sobrescrito?
4. O AUTOCOMMIT está adequado?
5. Existe UPDATE, DELETE ou INSERT?
6. O WHERE foi revisado?
7. Testei o filtro com SELECT?
8. O limite de linhas está razoável?
9. Existe aviso de CCSID?
10. Estou autorizado a executar isso?
Para comandos destrutivos, acrescente:
11. Tenho backup ou possibilidade de rollback?
12. Sei quantas linhas serão afetadas?
13. A unidade de trabalho está controlada?
14. Estou fora do horário crítico?
15. O DBA precisa ser avisado?
Conclusão
O SPUFI é uma das ferramentas mais didáticas do ecossistema Db2 for z/OS.
Na superfície, ele parece apenas uma tela para executar SQL. Em profundidade, porém, ele ensina quase todo o vocabulário operacional do mainframe:
datasets de entrada e saída;
PDS, PDSE e membros;
arquivos sequenciais;
DCB;
RECFM;
LRECL;
BLKSIZE;
espaço primário e secundário;
terminadores SQL;
planos;
pacotes;
isolamento;
commit e rollback;
CCSID;
catálogo;
SQLCODE;
execução interativa;
execução batch por JCL.
Para o programador COBOL Padawan, dominar o SPUFI é aprender a conversar diretamente com o Db2 antes de colocar o SQL dentro de um programa.
É nele que você experimenta.
É nele que você erra com segurança — desde que o AUTOCOMMIT esteja corretamente configurado.
É nele que você descobre que um SQL aparentemente simples pode esconder acesso a milhões de linhas.
E é nele que você começa a enxergar o banco não apenas como um lugar onde os dados vivem, mas como um sistema completo de armazenamento, concorrência, transações, segurança e otimização.
No mundo Bellacosa Mainframe, a tela verde nunca é apenas uma tela verde.
Cada campo é uma porta.
Cada parâmetro conta uma história.
Cada mensagem DSNE é um mestre antigo tentando impedir que o Padawan corrompa caracteres, bloqueie uma tabela ou execute um DELETE sem WHERE.
E cada SQLCODE 0 é o Db2 dizendo:
EXECUÇÃO CONCLUÍDA.
A FORÇA DO SQL ESTÁ COM VOCÊ.
Sem comentários:
Enviar um comentário