Nesta seção vamos organizar algumas informações sobre o uso do banco de dados SQLite com a linguagem Tcl/Tk.
As fontes de consulta para essa seção foram: The Definitive Guide to SQLite, 2010, Tcl 8.5 Networking Programming, 2010, The Tcl interface to the SQLite library e SQLite and Tcl.
O SQLite foi originalmente criado como uma extensão para o interpretador Tcl, por isso oferece suporte à Tcl desde o início, facilitando o seu uso a partir de um programa em Tcl.
Para começar instalamos a extensão da Tcl para acessar o SQLite:
apt-get
install
libsqlite3-tcl
Para carregar a extensão, dentro de um programa, basta usar o comando:
package require sqlite3
Para se conectar a um banco de dados use o comando sqlite3 que gera (ou retorna) um “descritor de arquivo” (ou identificador), ou seja, um nome para o canal que será usado para ler ou escrever dados no banco de dados.
Este comando tem dois argumentos: o primeiro é o nome do identificador de banco de dados (Ex: db) a ser criado e o segundo é o caminho para o arquivo de banco de dados (Ex: ./foods.db).
Criamos o programa foods.tcl
com o seguinte código inicial:
#!/usr/bin/env tclsh package require sqlite3 puts "\nConectando" sqlite3 db ./foods.db
Se passarmos o nome de um arquivo novo para o comando sqlite3 será criado um novo banco de dados. E se passarmos o argumento “:memory:” para o comando sqlite3 será criado um banco de dados apenas na memória.
O “identificador” do banco de dados é o meio de conexão com o banco de dados especificado. No entanto a conexão ainda não está aberta. A conexão só será aberta quando você tentar usá-la.
A escolha do nome do identificador de banco de dados é livre, e ele é o único objeto através do qual é possível acessar o banco de dados. Também é possível abrir o mesmo banco de dados várias vezes com identificadores diferentes.
O identificador é um “objeto” que oferece vários métodos, sendo o mais importante o eval.
O método eval permite a execução de consultas SQL no banco de dados com a sintaxe:
Para desconectar, basta usar o comando close do identificador do banco de dados. Isso automaticamente reverterá quaisquer transações pendentes.
nome_do_identificador eval {consulta_SQL} [nome_array] {[script]}
consulta_SQL é uma string contendo uma consulta SQL, geralmente colocada entre chaves “{}” para evitar substituição de variáveis pela Tcl já que o SQLite “entende” as variáveis Tcl e as substitui pelo seu conteúdo.
nome_array (opcional) é um array que irá armazenar os campos de cada registro retornado pela consulta, onde os nomes das colunas serão as chaves do array.
script (opcional) é um script que será executado para cada registro retornado pela consulta
Por padrão o SQLite não reconhece a restrição FOREIGN KEY, e por isso esse reconhecimento deve ser ativado logo após a conexão com o banco de dados com o comando:
db eval {PRAGMA foreign_keys = ON;}
As consultas são executadas com o método eval, o qual processa uma ou mais consultas de cada vez.
Uma das formas de uso do método eval é “iterar” todas as linhas em um script seguindo o código SQL. O script será executado uma vez para cada linha retornada no conjunto de resultados. E os campos em cada linha são considerados “variáveis locais” dentro do script.
Por exemplo, vamos acrescentar a seguinte consulta no programa foods.tcl
:
puts "\nSelecionando 5 registros" db eval {SELECT * FROM foods LIMIT 5} { puts "$id $name" }
É possível também atribuir os valores dos diferentes campos da tabela a um array:
puts "\nSelecionando 5 registros." db eval {SELECT * FROM foods LIMIT 5} values { puts "$values(id) $values(name)" }
A saída de ambas as consultas é:
~/SQLite$ ./foods.tcl Conectando Selecionando 5 registros 1 Bagels 2 Bagels, raisin 3 Bavarian Cream Pie 4 Bear Claws 5 Black and White cookies
O retorno do comando:
db eval {SELECT * FROM
foods
LIMIT 5}
é uma lista cujos elementos são os campos da tabela foods. A lista pode ser visualizada com o comando:
puts [db eval {SELECT * FROM
foods
LIMIT 5}]
Retorno:
1 1 Bagels 2 1 {Bagels, raisin} 3 1 {Bavarian Cream Pie} 4 1 {Bear Claws} 5 1 {Black and White cookies}
Essa lista corresponde a 5 registros, cada um dos quais possui 3 campos (id, type_id e name).
O exemplo seguinte mostra como realizar as operações de: inserção, modificação e remoção de dados e usamos o método changes para exibir o número de registros que sofreram modificações:
db eval begin puts "\nAtualizando o id de todos os registros." db eval { UPDATE foods SET type_id=0 } puts "Modificações : [db changes]" puts "\nRemovendo todas as linhas." #Remover todas as linhas db eval { DELETE FROM foods } puts "Modificações : [db changes]" puts "\nInserindo uma linha." #Inserindo uma linha db eval { INSERT INTO foods (type_id, name) VALUES (9, 'Junior Mints') } puts "Modificações : [db changes]" puts "last_insert_rowid() : [db last_insert_rowid]" puts "\nCancelando as operações." db eval ROLLBACK
Saída:
Atualizando o id de todos os registros. Modificações : 417 Removendo todas as linhas. Modificações : 417 Inserindo uma linha. Mudanças : 1 last_insert_rowid() : 1 Cancelando as operações.
Para fechar o banco de dados basta executar o comando CLOSE:
db CLOSE
Todo banco de dados SQLite possui uma tabela com o nome “SQLITE_MASTER” que define o esquema (schema) para o banco de dados com a seguinte estrutura: (Fonte: www.sqlite.org/faq.html#q7)
CREATE TABLE sqlite_master ( type TEXT, name TEXT, tbl_name TEXT, rootpage INTEGER, sql TEXT );
O campo “name” será o nome da tabela. Então, para obter uma lista de todas as tabelas no banco de dados, use o seguinte comando: (Fonte: https://www.tcl.tk/community/tcl2004/Presentations/D.RichardHipp/slides/slides-all.html)
puts [db eval {SELECT name FROM sqlite_master WHERE type='table'}] episodes foods foods_episodes food_types foods_copy
E para ver a estrutura de uma tabela, por exemplo “foods”:
puts [db onecolumn {SELECT sql FROM sqlite_master WHERE name='foods'}] CREATE TABLE foods( id integer primary key, type_id integer, name text )