Pular para o conteúdo principal

Query e Execute - Comandos diretos em Base de Dados

Antes de começar

Para poder compreender este tutorial com a maior eficácia possível, aconselhamos que se certifique que tem noções básicas em JavaScript, SQL e que saiba criar serviços no Netuno.

Caso não saiba criar serviços dirija-se a Serviços Web REST.

Criação de Queries

O Netuno traz consigo funções direccionadas para a criação de queries à base de dados, e neste tutorial iremos apresentar e descrever brevemente o efeito de cada uma e também as boas práticas para obter o melhor resultado.

_db.query('SELECT * FROM ...')

Esta função permite retornar dados de uma querie.

_out.json(
_db.query('SELECT * FROM tabela_nome')
)

Note que a função _out.json() é para permitir a visualização dos dados do serviço no ecrã ao chamar o mesmo no navegador

Esta função permite também a aceitação de argumentos, sendo que os mesmos são passados diretamente pela chamada ao serviço, como por exemplo, imaginemos que temos o serviço selecionar-todos.js, a chamada ao mesmo será feita por http://localhost:9000/services/selecionar-todos.netuno em que os argumentos a passar se colocam a seguir à chamada a seguir a um ponto de interrogação:

http://localhost:9000/services/selecionar-todos.netuno?argumento1=1&argumento2=nome

Note que para enviar múltiplos argumentos basta separar por um 'e' comercial (&)

Query com parâmetros

E por fim basta efetuar a declaração desta variável na querie da seguinte forma:

_out.json(
_db.query(
'SELECT * FROM tabela_nome WHERE id = ? AND nome = ?',
_req.getInt("argumento1"), _req.getString("argumento2")
)
)

No lugar das '?' (interrogações) será injetado o parâmetro correspondente de acordo com a sua ordem.

Query com parâmetros e tipos do PostgreSQL e H2DataBase

No entanto o H2Database e o PostgreSQL suportam uma sintaxe de conversão simples, e assim podemos atribuir tipos aos parâmetros da seguinte forma:

_out.json(
_db.query(
'SELECT * FROM tabela_nome WHERE id = ?::int AND nome = ?::varchar',
_req.getInt("id"), _req.getString("nome")
)
)

Tipos de parâmetros do H2Database e PostgreSQL

Como pode ter reparado anteriormente, quando se pretende executar uma consulta com argumentos tem de se definir o tipo dos mesmos. Segue agora uma lista com todos os tipos de variáveis e qual o tipo mais adequado para cada:

  • Adequado para parâmetros de números inteiros:
    • ?::int
  • Adequado para parâmetros números decimais:
    • ?::float
  • Adequado para parâmetros de identificador único global/universal mais conhecidos como guids ou uuid:
    • ?::uuid
  • Adequado para parâmetros de texto genérico, strings:
    • ?::varchar
    • ?::text
  • Adequado para parâmetros do tipo data:
    • ?::date
  • Adequado para parâmetros do tipo hora:
    • ?::time
  • Adequado para parâmetros com data e hora:
    • ?::datetime (H2Database)
    • ?::timestamp (PostgreSQL)

_db.execute('INSERT INTO | UPDATE | DELETE ...')

Esta função permite executar um comando de base de dados, como updates, inserts e deletes.

Retornar o número de registos afetados pelo comando e executado.

// Exemplo de Insert:
const nRecordsInserted = _db.execute(
"INSERT INTO tabela_nome(id, active, nome) " +
"VALUES(nextval('tabela_nome_id'), ?::int, ?::varchar)",
1, nome
)

//Exemplo de Update:
const nRecordsUpdated = _db.execute(
"UPDATE tabela_nome SET nome = ?::varchar WHERE id = ?::int",
_req.getString("nome"), _req.getInt("id")
)

// Exemplo de Delete:
const nRecordsDeleted = _db.execute(
"DELETE FROM tabela_nome WHERE id = ?::int",
_req.getInt("id")
)

Nota: Quando se faz um insert verificar se o campo active é igual a 1 senão não vai aparecer no resultado.

Exemplo de Interação com os Dados

Vamos agora apresentar normas aconselhadas para que obtenha os melhores resultados possíveis.

Query First

Veja abaixo como obter a primeira linha da query, ou será nulo caso não haja nenhuma linha obtida.

// Selecionar os dados:
const dbResult = _db.queryFirst(
'SELECT name FROM table_name WHERE uid = ?::uuid',
_req.getString("uid")
)
if (!dbResult) {
// Código de estado do HTTP:
_header.status(404)
// Indicação do erro:
_out.json(
_val.map()
.set('error', 'id-not-found')
)
// Finaliza a execução do serviço:
_exec.stop()
}

Validar a quantidade de registos

Quando efetua uma seleção à base de dados em que o resultado seja único, para ter acesso aos dados convém, proceder da seguinte forma:

Note que este é apenas um simples exemplo que garante que pelo menos 1 resultado é retornado e evita o erro caso não haja resultado.

// Selecão dos dados:
var dbResultados = _db.query(
'SELECT nome FROM tabela_nome WHERE id = ?::int',
_val.init()
.add(_req.getInt("id"))
)
let nome = null;
// Garante que existe dados, e pode ser utilizado o
// símbolo de maior (resultado.length > 1) no caso
// de haver mais que um registo:
if (dbResultados.size() >= 1) {
// Para aceder ao valor do nome diretamente basta:
nome = dbResultados.get(0).getString('nome');
}

Iteração em loop dos registos

Caso o resultado da seleção sejam múltiplos resultados, pode interagir com o ciclo 'for' para obter os dados da seguinte forma:

// Executar a query
const dbResultados = _db.query('SELECT id, nome FROM tabela_nome');

// Inicializar a variável para que esta possa receber valores
const items = _val.init();

// Iteração por todos os resultados para receber cada valor separado
for (const dbResultado of dbResultados) {
items.push(
_val.map()
.set("uid", dbResultado.getString("uid"))
.set("name", dbResultado.getString("name"))
);
}

// Envia na saída de dados a nova lista de dados:
_out.json(items);

Caso tenha alguma questão não hesite em contactar, veja as indicações no footer deste website.

Bom desenvolvimento!