Computing: Website and Database Programming

Web development environment setup on MS Windows.


7.1. SQLite embedded databases.
7.1.0. The SQLite distribution.
 
SQLite is an in-process library that implements a self-contained, serverless, zero-configuration, transactional SQL database engine. The code for SQLite is in the public domain and is thus free for use for any purpose, commercial or private. SQLite is the most widely deployed database in the world.
SQLite is an embedded SQL database engine. Unlike most other SQL databases, SQLite does not have a separate server process. SQLite reads and writes directly to ordinary disk files. A complete SQL database with multiple tables, indices, triggers, and views, is contained in a single disk file. The database file format is cross-platform – you can freely copy a database between 32-bit and 64-bit systems or between big-endian and little-endian architectures.
We the developers hope that you find SQLite useful and we entreat you to use it well: to make good and beautiful products that are fast, reliable, and simple to use. Seek forgiveness for yourself as you forgive others. And just as you have received SQLite for free, so also freely give, paying the debt forward.
The paragraph above is taken from the SQLite user manual. The important here, apart the fact that the database engine is 100% free and open source, as well as totally shareable between any platforms, is that SQLite is just a DLL to be included into the application programs (instead of a separate running server application in the case of most other databases). For the rest, all works in a similar way than, for example MySQL: To connect from a given programming language application, you need some SQLite-specific diver, or you can implement a generic ODBC connection. The communication with the engine is more or less standard SQL (SQLite doesn't support all SQL features and the full syntax, has some own extensions, and some features work differently as you know from other relational database systems).
7.1.1. Setting-up SQLite.
 
You can download SQLite from the SQLite Download Page. There you find the source code, as well as precompiled binaries for all major platforms (a zipped DLL in the case of Windows). The DLL, used in this tutorial (all samples have been build and tested on Windows 10) is the 64-bit DLL for SQLite v3.44.2 (file: sqlite-dll-win-x64-3440200.zip). You should also download the version corresponding SQLite tools (file: sqlite-tools-win-x64-3440200.zip); the documentation is available as a bundle of static HTML files (file: sqlite-doc-3440200.zip).
Setting up SQLite is done in just a minute. Unzip the archive containing the database engine and copy its content (the files sqlite3.dll and sqlite3.def) to your system directory; in the case of a 64-bit Windows, this is C:\Windows\SysWOW64. Unzip the tools archive, and copy its content to "some" directory (I used C:\Programs\SQLite). If you intend to create your databases in another directory, you may want to add the directory with the SQLite tools to your PATH environment variable. Concerning the documentation, unzip the archive and double-click the file index.html to open the main page in your web browser.
The tools archive contains 3 command line programs:
  • sqlite3.exe: A SQLite client that can be used for SQLite database administration, as well as to enter SQL queries and commands. I will describe its usage in the next section.
  • sqldiff.exe: A command-line utility program that displays content differences between SQLite databases. For details, have a look at the sqldiff.exe: Database Difference Utility page at the SQLite website.
  • sqlite3_analyzer.exe: A command-line utility program that measures and displays how much and how efficiently space is used by individual tables and indexes with an SQLite database file. For details, have a look at the The sqlite3_analyzer.exe Utility Program page at the SQLite website.
7.1.2. The sqlite3 command line client.
 
Whereas connecting to a database like MySQL consists in connecting as an authenticated user to a database specified as the name of a database that you have created on the database server before, connecting to a SQLite database consists in accessing a file created by sqlite on the file system (the path to this file having to be specified as database). SQLite does not include user authentication and if you may or may not access the file depends on where it is located: If you created it in a subdirectory of your User directory, only you can access it, if you created it in some Windows system directory you probably need administrator privileges to modify it, otherwise any user of the computer has full access to it.
Note: SQLite does support user authentication, but to use it, you'll have to rebuild the database engine with special build options. Click the following link for details concerning SQLite user authentication.
Two important facts concerning the connection to SQLite:
  • If the filename, that you specify as database, doesn't actually exists, by default, a new database (with this filename) will automatically be created.
  • If you connect without specifying a database name, an transient in memory database will automatically be created.
The screenshot below shows my folder with the 3 SQLite executables and the execution of sqlite3.exe without parameter, thus the connection to a transient in memory database.
SQLite on Windows: Execution of the database client sqlite3.exe
The client program sqlite3.exe accepts three kinds of input:
  • Commands: They start with a dot (.) and must not be terminated with a semicolon. Examples: Use .help to display the sqlite3 help documentation; use .quit to terminate the program.
  • SQL statements: Regular SQL statements, that may span over several lines. Hitting ENTER continues the statement in the next line. SQL statements must be terminated with a semicolon (;). If the last character in the actual line is a semicolon and you hit ENTER, the statement is executed.
  • Pragmas: Like SQL statements, they must be terminated with a semicolon. Example: pragma foreign_keys = 1;
Here is a list with some sqlite3 commands that you should know (for a more detailed overview, have a look at the SQLite tutorial at the SQLite commands article at the tutorialspoint website:
CommandDescription
.databasesList database names and files
.tablesList names of tables
.indicesList names of indices
.mode MODESet display mode, where MODE is one of: csv, column, html, insert, line, list, tabs, tcl
.header(s) ON|OFFTurn display of table headers on resp. off
.output FILENAMESend output to a file
.read FILENAMEExecute SQL statements in a file
7.1.3. Creating the "world" database.
 
The program samples in this tutorial use the MySQL "world" database. If you have MySQL installed with this database, you can get the SQL by doing an export of the 3 tables. Otherwise, you can download the SQL of the "world" database from the MySQL website. You can use copy/paste to create the files for SQLite from those for MySQL. I myself created the following files: create_country.sql, create_countrylanguage.sql, and create_city.sql (containing the CREATE TABLE statements), fill_country.sql, fill_countrylanguage.sql, and fill_city.sql (containing the INSERT statements), and create_indices.sql (containing the statements to create the primary keys and other indices for all 3 tables). However, when trying to execute the table creation statements (using the .read command), I got lots of errors due to SQLite-MySQL SQL compatibility issues. In particular, you'll have to remove the CHARACTER SET and COLLATE attributes, as well as the ENGINE=InnoDB DEFAULT CHARSET=utf8 at the end of the statement. For the "country" table, you'll also have to replace the ENUM('Asia', 'Europe', 'North America', 'Africa', 'Oceania', 'Antarctica', 'South America') by some data type that is supported by SQLite, for example CHAR(13).
Another important difference between SQLite and MySQL is that SQLite does not support the addition of a foreign key constraint to an existing table (ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEY ... is not supported). This means, that if you want to use foreign keys, it's mandatory to define them during table creation (also note that you must not specify a name for SQLite foreign keys)!
Concerning the AUTO_INCREMENT attribute of the "ID" field in the "city" table, I did not succeed to implement it. The SQLite documentation says that an integer field, that actually is a primary key, is automatically considered as being an auto-increment (the attribute AUTO_INCREMENT is not supported). But, defining ID as NOT NULL will make it impossible to insert records into the table without specifying an ID. And allowing it to be null (what is possible in SQLite), sets the value to NULL, and not to the next increment value, if you insert a record without an ID specified.
You'll also have to edit fill_city.sql. SQLite does not support the escape of a single quote by \' as it is used in two city names.
Finally, you have to create the primary keys using CREATE UNIQUE INDEX ... ON ..., and the other indices using CREATE INDEX ... ON ..., instead of using ALTER TABLE ... ADD PRIMARY KEY ... and ALTER TABLE ... ADD KEY ... as it's done with MySQL.
As this file editing is annoying and just costs time, I have placed a copy of my "world" SQL statements on this site, where you can download an archive with the 7 files mentioned above, and ready to be used with the .read command of sqlite3.exe.
The screenshot below shows the creation of the 3 tables from the corresponding files (with the ENUM problem, and then a syntax error with the "country" table, the display of the 3 tables, the insertion of the "country" records, and finally the display of the number of records in the "country" table.
SQLite on Windows: Creating the 'world' database, using the sqlite3 client
And the following screenshot (taken on my other Windows 10) shows the insertion of some records into the "city" table. The first insertion fails, as the primary key ID is already used. The second insertion succeeds. This might surprise you, as it's an insertion with a country code that doesn't actually exist in the "country" table, what means that the foreign key constraint has not been checked. The reason for this is that in SQLite foreign keys checking is disabled by default, and in order to use this feature, we have to set PRAGMA FOREIGN_KEYS = 1. With this done, the insertion will fail, as it will succeed after we'll have created the referenced record in the "country" table.
SQLite on Windows: Primary and foreign key checking (in sqlite3 client)
7.1.4. SQLite GUI tools.
 
I suppose that the "standard" GUI tool to manage SQLite databases is DB Browser for SQLite, that you can download free of charge from sqlitebrowser.org. It is available as 64bit and 32bit installer, as well as as portable application. I actually installed version 3.12.2, 64bit.
The application is simple to use, has all you need to work with your SQLite databases, and offers a very wide range of configuration options. If you aren't normally connected to the Internet and want to avoid the "Host not found" warning at startup, just disable auto-update. A more important setting is to select the foreign keys enabled checkbox on the Database tab of the Preferences window, if you actually use foreign keys with your databases.
Connection to the database is just opening the corresponding file. From the menu, choose File > Open Database... and browse to your SQLite database file. The file extension expected by DB Browser for SQLite is either .db, or .sql. Using .sql as extension for your SQLite database files is not recommendable, as this extension is usually used for SQL source files. If the extension of your database file is none of those expected by the application (on my Windows 10 VM I forgot to add an extension when I created the "world" database), select All files in the Choose a database file dialog box in order to get your file displayed for selection.
SQLite on Windows: DB Browser for SQLite - Opening a database
The tab layout of the GUI window is very clear. Below the menu bar, you find two icon bars. The first one allows to create, open, attach, or close a database (you can also create projects). The second one allows to edit the database structure (create a new table, or index), to edit a table's data (with a large edit field for this at the right side of the window), to edit the pragmas, and to execute SQL statements. The screenshot shows the structure of the "world" database. Note the column schema, that contains the SQL statement used to create a table or index. These statements are actually stored in the table sqlite_master that you can view using a SELECT statement. There is a pragma writable_schema = 1, however it seems that the table is read-only and that there is no way to update it, thus no possibility to add a foreign key to an existing table this way, as is suggested in some forums.
SQLite on Windows: DB Browser for SQLite - Database structure
If you have MariaDB installed on your computer, you probably use HeidiSQL. This application also works well with SQLite. When HeidiSQL starts up, click the New button to create a new session. Select network type = SQLite, select Library = sqlite3.dll and browse to your database file to fill in the corresponding edit field. Do not forget to save the newly added session.
SQLite on Windows: HeidiSQL - Creating a new SQLite session
The screenshot shows the execution of a SELECT statement in a HeidiSQL query tab.
SQLite on Windows: HeidiSQL - Ruuning a SELECT query
7.1.5. Accessing SQLite with PHP: FAILURE.
 
Using PHP 8.0.0, I did not succeed to access the SQLite database "world". Using the extension sqlite3, I got the error message Class SQLit3 not found, with the extension pdo_sqlite, the message was could not find driver. Same issue when trying to use ODBC. Maybe that there is a path to be set (for other databases this is not the case), maybe that the installed drivers do not work with my version of SQLite. As I very rarely use PHP, I made no further investigation to find out.
7.1.6. Accessing SQLite with Perl.
 
Access to a database engine with Perl is normally done using DBI (access using ODBC is also possible, of course). DBI is a generic interface that acts with a given database distribution via a specific driver. In the case of SQLite, this driver is dbi:SQLite, that is included by default with the Strawberry Perl installation files. Thus, nothing to install, nothing to configure (to access the database from web applications, CGI must be configured, of course). Here is the code of a simple console application, that displays the number of cities in the "world" database.
    use strict; use warnings;
    use DBI;
    my $database = 'C:\Programs\SQLite\world.db';
    my $dsn = "dbi:SQLite:dbname=$database";
    my $username = ''; my $password = '';
    my $dbh = DBI->connect($dsn, $username, $password, {RaiseError => 1},)
        or die $DBI::errstr;
    my $sql = "SELECT COUNT(*) FROM city";
    my $sth = $dbh->prepare($sql);
    $sth->execute();
    my ($count) = $sth->fetchrow();
    print "\nNumber of cities in the world.city table = $count\n\n";
    $sth->finish();
    $dbh->disconnect();
To run the script (I called it sqlite.pl) in Command Prompt, type:
    perl sqlite.pl
7.1.7. Accessing SQLite with Python.
 
Access to SQLite with Python is simple and without having to install special components. In fact, the driver needed (sqlite3) is included by default with the Python 3 installation files. Here is the code of a simple CGI application, that displays the number of cities in the "world" database.
    #!C:/Users/allu/AppData/Local/Programs/Python/Python310/python.exe
    import sqlite3
    print("Content-type: text/html")
    print()
    print("<html>")
    print("<head><title>Python SQLite test</title></head>")
    print("<body>")
    try:
        # Connect to database 'world'
        sqliteConnection = sqlite3.connect('C:\Programs\SQLite\world.db')
        cursor = sqliteConnection.cursor()
        # Read the number of records in the 'city' table
        query = "select count(*) from city;"
        cursor.execute(query)
        count = cursor.fetchone()[0]
        # Print result onto webpage
        print("<p>Number of cities in database 'world' = ", count, "</p>")
    except sqlite3.Error as error:
        # Connection error handling
        print("Error while accessing SQLite database", error)
    finally:
        # Disconnect from database
        if sqliteConnection:
            cursor.close()
            sqliteConnection.close()
    print("</body>")
    print("</html>")
Place the script (I called it sqlite.py) in the cgi-bin directory of your webserver, and type the follwing in the address field of your web browser:
    localhost/cgi-bin/sqlite.py
7.1.8. Accessing SQLite with Lazarus/Free Pascal.
 
There are two ways to connect from a Lazarus/Free Pascal application to a SQLite database: first, using a TSQLite3Connection, object and second, using a TODBCConnection object. Both ways are described in my tutorial Using SQLite databases with Lazarus/Free Pascal.
7.1.9. Accessing SQLite with Java.
 
To connect from Java to a database engine, you need the JDBC driver, specific for this database distribution. You can download the SQLite JDBC Driver from Sourceforge. The download is a ZIP archive containing the driver code as JAR file. Move the JAR to "some directory", for example together with your SQLite files (C:\Programs\sqlite, in my case). The important thing is that you'll have to add the driver to the Java class path. In Windows 10, this is done by adding the full filename (path + name + extension) to the environment variable CLASSPATH: In File Explorer, right-click This PC and from the context menu choose Properties (this actually opens the Settings > System > About page). On the right side of this page, click the Advanced system settings link. In the window that pops up, push the Environment variables button. If there is a variable called CLASSPATH, push the Edit... button to modify it, otherwise push New... to create it. In the Edit environment variable window, push the Add button and enter the full path name of your JAR file, in my case C:\Programs\sqlite\sqlite-jdbc-3.7.2.jar.
SQLite on Windows: Adding the JDBC driver to the Java classpath
Here is the code of a simple Java console program, that displays the number of cities in the "world" database.
    import java.sql.DriverManager;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    public class testsqlite {
        private Connection connect() {
            String url = "jdbc:sqlite:C:\\Programs\\sqlite\\world.db";
            Connection conn = null;
            try {
                DriverManager.registerDriver(new org.sqlite.JDBC());
                conn = DriverManager.getConnection(url);
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
            return conn;
        }
        public void selectCount() {
            String sql = "SELECT COUNT(*) FROM city";
            try {
                Connection conn = this.connect();
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery(sql);
                if (rs.next()) {
                    int reccount = rs.getInt(1);
                    System.out.println ("Number of records in table 'city' = " + reccount);
                }
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
        }
        public static void main(String[] args) {
            testsqlite app = new testsqlite();
            app.selectCount();
        }
    }
To compile, and then run the program (I called it testsqlite.java) in Command Prompt, type:
    javac testsqlite.java
    java testsqlite
SQLite on Windows: Compiling and running a simple Java program
If you get the error message No suitable driver found, then it's probably because you forgot to register the driver, what in the program above, is done with the statement DriverManager.registerDriver(new org.sqlite.JDBC()).

If you find this text helpful, please, support me and this website by signing my guestbook.