Introduction to SQLite Visual Basic
last modified July 6, 2020
In the first chapter of the SQLite Visual Basic tutorial, we will provide necessary definitions. We will show, how to install Mono & Visual Basic. All the examples in this tutorial will be run on Mono. Later we create the first working examples.
About SQLite database
SQLite
is an embedded relational database engine. Its developers call it a
self-contained, serverless, zero-configuration and transactional SQL database
engine. It is very popular and there are hundreds of millions copies worldwide
in use today. SQLite is used in Solaris 10 and Mac OS operating systems, iPhone
or Skype. Qt4 library has a buit-in support for the SQLite as well as the Python
or the PHP language. Many popular applications use SQLite internally such as
Firefox or Amarok.
$ sudo apt-get install sqlite3
We need to install sqlite3
library if it is not installed already.
The SQLite comes with the sqlite3
command line utility. It can be used to
issue SQL commands against a database. Now we are going to use the
sqlite3
command line tool to create a new database.
$ sqlite3 test.db SQLite version 3.6.22 Enter ".help" for instructions Enter SQL statements terminated with a ";"
We provide a parameter to the sqlite3
tool. The test.db
is a database name. It is a single file on our disk. If it is present,
it is opened. If not, it is created.
sqlite> .tables sqlite> .exit $ ls test.db
The .tables
command gives a list of tables in the test.db
database. There are currently no tables. The .exit
command
terminates the interactive session of the sqlite3
command
line tool. The ls
Unix command shows the contents of the current
working directory. We can see the test.db
file. All data will
be stored in this single file.
Mono
Mono is an open source implementation of Microsoft's .NET Framework based on the ECMA standards for C# and the Common Language Runtime. We need to have Mono installed in order to compile and run the examples, in this tutorial.
Mono can be installed from the packages of our Linux distribution or we can install Mono from sources to get more up-to-date version.
$ bunzip2 mono-2.10.8.tar.bz2 $ tar -xf mono-2.10.8.tar $ cd mono-2.10.8/ $ ./configure $ make $ sudo make install
We download the mono-2.10.8.tar.bz2
tarball from the Mono
website. We uncompress it, build it and install the libraries.
We install the Mono runtime, C# language and the SQLite .NET data adapter
among others.
$ bunzip2 libgdiplus-2.10.9.tar.bz2 $ tar -xf libgdiplus-2.10.9.tar $ cd libgdiplus-2.10.9/ $ ./configure $ make $ sudo make install
For the example with the Winforms control, we need also the libgdiplus
library. It is located in a separate file. We build and install it.
$ sudo ldconfig $ ldconfig -p | grep libgdiplus libgdiplus.so.0 (libc6) => /usr/local/lib/libgdiplus.so.0 libgdiplus.so (libc6) => /usr/local/lib/libgdiplus.so
We also run the ldconfig
tool to update the database of
dynamic libraries. The ldconfig
scans a running system and
sets up the symbolic links that are used to load shared libraries.
The Mono.Data.Sqlite
assembly contains an ADO.NET data provider
for the SQLite database. It is written in C# and is available for all CLI
languages, including C#, Visual Basic, and Boo.
$ ls /usr/local/lib/mono/4.0/Mono.Data.Sqlite.dll /usr/local/lib/mono/4.0/Mono.Data.Sqlite.dll
From the technical point of view, we need a DLL. On our system, it was located under the above path. (In fact the above link is a soft link to the DLL, which is located in a gac subdirectory.)
Visual Basic
Visual Basic
is a modern, high-level, general-purpose, object-based programming language.
It is the second most important language of the .NET framework. The main design
goal of the language was to create an easy to use and learn programming language.
It was derived from the classic BASIC language. Mono brings Visual Basic to the
Unix platform. It has a Visual Basic compiler in a separate package.
$ bunzip2 mono-basic-2.10.tar.bz2 $ tar xvf mono-basic-2.10.tar $ cd mono-basic-2.10/
We download the sources from the Mono project website. We upack the file and go into the newly created subdirectory.
$ ./configure $ make $ sudo make install
We build & install the compiler.
$ ls /usr/local/bin/vbnc* /usr/local/bin/vbnc /usr/local/bin/vbnc2
The compiler is called vbnc and is located in the /usr/local/lib/bin directory by default.
ADO.NET
ADO.NET
is an important part of the .NET framework. It is a specification
that unifies access to relational databases, XML files and other application data.
From the programmer's point of view it is a set of libraries
and classes to work with database and other data sources.
A Mono.Data.SQLite
is an implementation of the ADO.NET specification
for the SQLite database. It is a driver written in C# language and is available for
all .NET languages.
SqliteConnection
, SqliteCommand
, SqliteDataReader
,
SqliteDataAdapter
are the core elements of the .NET data provider model.
The SqliteConnection
creates a connection to a specific data source.
The SqliteCommand
object executes an SQL statement against a data source.
The SqliteDataReader
reads streams of data from a data source.
A SqliteDataAdapter
is an intermediary between the DataSet
and
the data source. It populates a DataSet
and resolves
updates with the data source.
The DataSet
object is used for offline work with a mass of data. It is a
disconnected data representation that can hold data from a variety of different
sources. Both SqliteDataReader
and DataSet
are used to
work with data; they are used under different circumstances. If we only need to
read the results of a query, the SqliteDataReader
is the better choice.
If we need more extensive processing of data, or we want to bind a Winforms control
to a database table, the DataSet
is preferred.
SQLite version
If the first program, we check the version of the SQLite database.
Option Strict On Imports Mono.Data.Sqlite Module Example Sub Main() Dim con As SqliteConnection Dim cmd As SqliteCommand Try Dim cs As String = "Data Source=:memory:" con = New SqliteConnection(cs) con.Open() Dim stm As String = "SELECT SQLITE_VERSION()" cmd = New SqliteCommand(stm, con) Dim version As String = Convert.ToString(cmd.ExecuteScalar()) Console.WriteLine("SQLite version : {0}", version) Catch ex As SqliteException Console.WriteLine("Error: " & ex.ToString()) Finally If cmd IsNot Nothing cmd.Dispose() End If If con IsNot Nothing Try con.Close() Catch ex As SqliteException Console.WriteLine("Failed closing connection") Console.WriteLine("Error: " & ex.ToString()) Finally con.Close() con.Dispose() End Try End If End Try End Sub End Module
We connect to an in-memory database and select the SQLite version.
Imports Mono.Data.Sqlite
The Mono.Data.SqliteClient
assembly contains an ADO.NET
data provider for the SQLite database engine. We import the elements
of the SQLite data provider.
Dim con As SqliteConnection Dim cmd As SqliteCommand
We declare two variables. They are placed before the Try
keyword, since we will later call Dispose
, and
Close
method on them.
Dim cs As String = "Data Source=:memory:"
This is the connection string. It is used by the data provider to establish a connection to the database. We create an in-memory database.
con = New SqliteConnection(cs)
A SqliteConnection
object is created. This object is used to
open a connection to a database.
con.Open()
This line opens the database connection.
Dim stm As String = "SELECT SQLITE_VERSION()"
This is the SQL SELECT
statement. It returns the version
of the database. The SQLITE_VERSION
is a built-in
SQLite function.
Dim cmd As New SqliteCommand(stm, con)
The SqliteCommand
is an object, which is used to execute a
query on the database. The parameters are the SQL statement and the
connection object.
Dim version As String = Convert.ToString(cmd.ExecuteScalar())
There are queries which return only a scalar value. In our case, we want a simple
string specifying the version of the database. The ExecuteScalar
is
used in such situations. We avoid the overhead of using more complex objects.
Console.WriteLine("SQLite version : {0}", version)
The version of the database is printed to the console.
Catch ex As SqliteException Console.WriteLine("Error: " & ex.ToString())
In case of an exception, we print the error message to the console.
Finally If cmd IsNot Nothing cmd.Dispose() End If
The SqliteCommand
class implements the IDisposable
interface. Therefore it must be explicitly disposed in the Finally
block.
If con IsNot Nothing Try con.Close() Catch ex As SqliteException Console.WriteLine("Failed closing connection") Console.WriteLine("Error: " & ex.ToString()) Finally con.Close() con.Dispose() End Try End If
Closing connection may throw another exception. We handle this situation. (Although this situation is more likely to occur in server based databases like MySQL or PostgreSQL.)
$ vbnc version.vb -r:Mono.Data.Sqlite.dll
We compile our example. A path to the SQLite data provider DLL is provided.
$ mono version.exe SQLite version : 3.7.7
This is the output of the program on our system.
The Using statement
The Visual Basic language implements garbage collection. It is a process of automatic
release of objects that are no longer required. The process is non-deterministic.
We cannot be sure when the CLR (Common Language Runtime) decides to release
resources. For limited resources such as file handles or network connections
it is best to release them as quickly as possible. With the Using
statement,
the programmer controls when the resource is to be released. When the program is
out of the Using block, either reaches the end of it or an exception is thrown,
the resource gets released.
Internally, the Using
statement is translated into Try
,
Finally
blocks with a Dispose
call in the Finally
block. Note that you might prefer to use Try
, Catch
,
Finally
blocks instead of the Using statement. Especially, if you want
to utilize the Catch
block explicitly. In this tutorial we have chosen
the Using
statement.
As a rule, when we use an IDisposable
object, we should declare and
instantiate it in a Using statement. (Or call Dispose
in the
Finally
block.) In the case of the SQLite ADO.NET driver, we use the
Using
statement for the SqliteConnection
, SqliteCommand
,
SqliteDataReader
, SqliteCommandBuilder
, and
SqliteDataAdapter
classes. We do not have to use it for DataSet
.
or DataTable
classes. They can be left for the garbage collector.
Option Strict On Imports Mono.Data.Sqlite Module Example Sub Main() Dim cs As String = "URI=file:test.db" Using con As New SqliteConnection(cs) con.Open() Using cmd As New SqliteCommand(con) cmd.CommandText = "SELECT SQLITE_VERSION()" Dim version As String = Convert.ToString(cmd.ExecuteScalar()) Console.WriteLine("SQLite version : {0}", version) End Using con.Close() End Using End Sub End Module
We have the same example. This time we implement the Using
keyword.
Using con As New SqliteConnection(cs) con.Open() Using cmd As New SqliteCommand(con)
Both SqliteConnection
and SqliteCommand
implement
the IDisposable
interface. Therefore they are wrapped with
the Using
keyword.
Creating and populating a table
Next we are going to create a database table and fill it with data.
Option Strict On Imports Mono.Data.Sqlite Module Example Sub Main() Dim cs As String = "URI=file:test.db" Using con As New SqliteConnection(cs) con.Open() Using cmd As New SqliteCommand(con) cmd.CommandText = "DROP TABLE IF EXISTS Cars" cmd.ExecuteNonQuery() cmd.CommandText = "CREATE TABLE Cars(Id INTEGER PRIMARY KEY," _ & "Name TEXT, Price INT)" cmd.ExecuteNonQuery() cmd.CommandText = "INSERT INTO Cars VALUES(1,'Audi',52642)" cmd.ExecuteNonQuery() cmd.CommandText = "INSERT INTO Cars VALUES(2,'Mercedes',57127)" cmd.ExecuteNonQuery() cmd.CommandText = "INSERT INTO Cars VALUES(3,'Skoda',9000)" cmd.ExecuteNonQuery() cmd.CommandText = "INSERT INTO Cars VALUES(4,'Volvo',29000)" cmd.ExecuteNonQuery() cmd.CommandText = "INSERT INTO Cars VALUES(5,'Bentley',350000)" cmd.ExecuteNonQuery() cmd.CommandText = "INSERT INTO Cars VALUES(6,'Citroen',21000)" cmd.ExecuteNonQuery() cmd.CommandText = "INSERT INTO Cars VALUES(7,'Hummer',41400)" cmd.ExecuteNonQuery() cmd.CommandText = "INSERT INTO Cars VALUES(8,'Volkswagen',21600)" cmd.ExecuteNonQuery() End Using con.Close() End Using End Sub End Module
In the above code example, we create a Cars
table with 8 rows.
cmd.CommandText = "DROP TABLE IF EXISTS Cars" cmd.ExecuteNonQuery()
First we drop the table if it already exists. We can use the
ExecuteNonQuery
method if we do not want a
result set. For example for DROP
, INSERT
,
or DELETE
statements.
cmd.CommandText = "CREATE TABLE Cars(Id INTEGER PRIMARY KEY," _ & "Name TEXT, Price INT)" cmd.ExecuteNonQuery()
A Cars
table is created. The INTEGER PRIMARY KEY
column is autoincremented in SQLite.
cmd.CommandText = "INSERT INTO Cars VALUES(1,'Audi',52642)" cmd.ExecuteNonQuery() cmd.CommandText = "INSERT INTO Cars VALUES(2,'Mercedes',57127)" cmd.ExecuteNonQuery()
We insert two rows into the table.
sqlite> .mode column sqlite> .headers on
In the sqlite3
command line tool we modify the
way the data is displayed in the console. We use the column mode
and turn on the headers.
sqlite> SELECT * FROM Cars; Id Name Price ---------- ---------- ---------- 1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 6 Citroen 21000 7 Hummer 41400 8 Volkswagen 21600
We verify the data. The Cars
table was successfully created.
Prepared statements
Now we will concern ourselves with prepared statements. When we write prepared statements, we use placeholders instead of directly writing the values into the statements. Prepared statements increase security and performance.
Option Strict On Imports Mono.Data.Sqlite Module Example Sub Main() Dim cs As String = "URI=file:test.db" Using con As New SqliteConnection(cs) con.Open() Using cmd As New SqliteCommand(con) cmd.CommandText = "INSERT INTO Cars(Name, Price) VALUES(@Name, @Price)" cmd.Prepare() cmd.Parameters.AddWithValue("@Name", "BMW") cmd.Parameters.AddWithValue("@Price", 36600) cmd.ExecuteNonQuery() End Using con.Close() End Using End Sub End Module
We add a row to the Cars
table. We use a parameterized command.
cmd.CommandText = "INSERT INTO Cars(Name, Price) VALUES(@Name, @Price)" cmd.Prepare()
Here we create a prepared statement. When we write prepared statements, we use
placeholders instead of directly writing the values into the statements.
Prepared statements are faster and guard against SQL injection attacks.
The @Name
and @Price
are placeholders, which are
going to be filled later.
cmd.Parameters.AddWithValue("@Name", "BMW") cmd.Parameters.AddWithValue("@Price", 36600)
Values are bound to the placeholders.
cmd.ExecuteNonQuery()
The prepared statement is executed. We use the ExecuteNonQuery
method of the SqliteCommand
object when we do not expect any
data to be returned.
$ mono prepared.exe sqlite> SELECT * FROM Cars; Id Name Price ---------- ---------- ---------- 1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 6 Citroen 21000 7 Hummer 41400 8 Volkswagen 21600 9 BMW 36600
We have a new car inserted into the table.
Sources
The MSDN (Microsoft Developer Network) was consulted to create this tutorial. Several definitions come from this website.
This was an introductory chapter to SQLite Visual Basic tutorial.