PowerShell has no built-in cmdlets for SQLite. A free module called PSSQLite fills the gap with a handful of commands, and in this article I’ll walk you through installing it and using it to build and query an SQLite database from your scripts.
TLDR
- PowerShell doesn’t include SQLite. Install the PSSQLite module with
Install-Module PSSQLite. - Run any SQL with
Invoke-SqliteQuery -DataSource <file> -Query <sql>. Pass values with-SqlParameters, not string concatenation. - Query results come back as PowerShell objects, so commands like
Where-ObjectandExport-Csvwork on them. - PSSQLite bundles an old SQLite (3.30.1) and an x64 native library. On ARM64 Linux, it fails to load.
- Without the module, pipe
sqlite3 -jsonoutput toConvertFrom-Jsonto get objects.
What is PSSQLite and what will we build?
PSSQLite is a PowerShell module from the PowerShell Gallery for working with SQLite (PSSQLite on GitHub). It wraps the System.Data.SQLite library, so you don’t have to load DLLs yourself. Its main commands are:
| Command | What it does |
|---|---|
Invoke-SqliteQuery | Runs SQL against a database file and returns rows as objects |
New-SQLiteConnection | Opens a connection you can reuse |
Invoke-SQLiteBulkCopy | Inserts a whole DataTable in one transaction |
Out-DataTable | Turns PowerShell objects into a DataTable |
To show you how it works, I will build a small server inventory database called inventory.db with one servers table.
Prerequisites
| Requirement | Version tested |
|---|---|
| PowerShell | 7.6.6. The PSSQLite README also covers Windows PowerShell 5 (not executed here) |
| PSSQLite | 1.1.0, published to the PowerShell Gallery on 18 May 2020 |
| sqlite3 command-line shell | 3.45.1, only for the no-module option at the end |
Building the inventory database
Each step below is a script file. I ran them in order in the same folder, so each one sees the data from the step before.
Step 1: Install the module
Install-Module -Name PSSQLite -Scope CurrentUser
Import-Module PSSQLite
Get-Module PSSQLite | Select-Object Name, Version
Name Version
---- -------
PSSQLite 1.1.0
If PowerShell asks whether to trust the PSGallery repository, answer Y.
Step 2: Create a database and a table
Invoke-SqliteQuery creates the database file the first time you use it. CREATE TABLE IF NOT EXISTS makes the script safe to run again:
Import-Module PSSQLite
$db = "./inventory.db"
$query = @"
CREATE TABLE IF NOT EXISTS servers (
id INTEGER PRIMARY KEY,
hostname TEXT NOT NULL UNIQUE,
os TEXT NOT NULL,
ram_gb INTEGER
)
"@
Invoke-SqliteQuery -DataSource $db -Query $query
Invoke-SqliteQuery -DataSource $db -Query "SELECT name FROM sqlite_master WHERE type = 'table'"
name
----
servers
Step 3: Insert rows with parameters
Put @name placeholders in the SQL and pass the values in a hashtable. SQLite then treats them as values, never as SQL:
Import-Module PSSQLite
$db = "./inventory.db"
$query = "INSERT INTO servers (hostname, os, ram_gb) VALUES (@hostname, @os, @ram)"
Invoke-SqliteQuery -DataSource $db -Query $query -SqlParameters @{
hostname = "web01"; os = "Ubuntu 24.04"; ram = 16
}
Invoke-SqliteQuery -DataSource $db -Query $query -SqlParameters @{
hostname = "db01"; os = "Windows Server 2025"; ram = 64
}
Invoke-SqliteQuery -DataSource $db -Query "SELECT count(*) AS servers FROM servers"
servers
-------
2
Step 4: Query the data
Each row comes back as a PSCustomObject, so PowerShell’s own commands work on the results:
Import-Module PSSQLite
$db = "./inventory.db"
$servers = Invoke-SqliteQuery -DataSource $db -Query "SELECT hostname, os, ram_gb FROM servers ORDER BY ram_gb DESC"
$servers | Format-Table
$servers[0].GetType().Name
$servers | Where-Object ram_gb -gt 32 | Select-Object -ExpandProperty hostname
hostname os ram_gb
-------- -- ------
db01 Windows Server 2025 64
web01 Ubuntu 24.04 16
PSCustomObject
db01
Step 5: Bulk insert many rows
For many rows, build a DataTable with Out-DataTable and load it with Invoke-SQLiteBulkCopy, which inserts it in one transaction:
Import-Module PSSQLite
$db = "./inventory.db"
$rows = 1..3 | ForEach-Object {
[pscustomobject]@{ hostname = "app0$_"; os = "Debian 13"; ram_gb = 8 * $_ }
}
$table = $rows | Out-DataTable
Invoke-SQLiteBulkCopy -DataTable $table -DataSource $db -Table servers -Force
Invoke-SqliteQuery -DataSource $db -Query "SELECT id, hostname, ram_gb FROM servers" | Format-Table
id hostname ram_gb
-- -------- ------
1 web01 16
2 db01 64
3 app01 8
4 app02 16
5 app03 24
Step 6: Export query results to CSV
Import-Module PSSQLite
$db = "./inventory.db"
Invoke-SqliteQuery -DataSource $db -Query "SELECT hostname, os, ram_gb FROM servers" |
Export-Csv -Path ./servers.csv -NoTypeInformation
Get-Content ./servers.csv
"hostname","os","ram_gb"
"web01","Ubuntu 24.04","16"
"db01","Windows Server 2025","64"
"app01","Debian 13","8"
"app02","Debian 13","16"
"app03","Debian 13","24"
Step 7: Use the connection directly with ExecuteNonQuery
New-SQLiteConnection returns a System.Data.SQLite connection object. Use it when you want the ADO.NET methods, such as ExecuteNonQuery() for statements that don’t return rows and ExecuteReader() for ones that do. Its ConnectionString shows the Data Source= form that ADO.NET expects:
Import-Module PSSQLite
$conn = New-SQLiteConnection -DataSource "./inventory.db"
$conn.GetType().FullName
$conn.ConnectionString
$cmd = $conn.CreateCommand()
$cmd.CommandText = "UPDATE servers SET ram_gb = ram_gb * 2 WHERE os LIKE @os"
[void]$cmd.Parameters.AddWithValue("@os", "Debian%")
"Rows updated: " + $cmd.ExecuteNonQuery()
$cmd.CommandText = "SELECT hostname, ram_gb FROM servers WHERE os LIKE 'Debian%'"
$reader = $cmd.ExecuteReader()
while ($reader.Read()) { "{0} has {1} GB" -f $reader["hostname"], $reader["ram_gb"] }
$reader.Close()
$conn.Close()
System.Data.SQLite.SQLiteConnection
Data Source=/work/inventory.db;
Rows updated: 3
app01 has 16 GB
app02 has 32 GB
app03 has 48 GB
Step 8: Skip the module and use the sqlite3 shell
If you’d rather not install a module, the sqlite3 command-line shell can print JSON with -json, and PowerShell turns that into objects. Out-String joins the output lines into one JSON document first:
$servers = sqlite3 -json ./inventory.db "SELECT hostname, ram_gb FROM servers WHERE ram_gb >= 32" |
Out-String | ConvertFrom-Json
$servers | Format-Table
sqlite3 --version
hostname ram_gb
-------- ------
db01 64
app02 32
app03 48
3.45.1 2024-01-30 16:01:20 e876e51a0ed5c5b3126f52e532044363a014bc594cfefa87ffb5b82257ccalt1 (64-bit)
Running it
Run each script from the folder that holds inventory.db, for example pwsh ./query.ps1. The paths in the scripts are relative, so ./inventory.db means the current folder.
Common problems
These two errors come from the module’s bundled libraries, not from your SQL.
no such function: concat
PSSQLite bundles its own copy of SQLite, and it’s old. Functions added since then, such as concat() from SQLite 3.44.0, aren’t there:
Import-Module PSSQLite
Invoke-SqliteQuery -DataSource ":MEMORY:" -Query "SELECT sqlite_version() AS bundled_sqlite"
Invoke-SqliteQuery -DataSource ":MEMORY:" -Query "SELECT concat('a', 'b') AS joined"
bundled_sqlite
--------------
3.30.1
Invoke-SqliteQuery: /work/version.ps1:3
Line |
3 | Invoke-SqliteQuery -DataSource ":MEMORY:" -Query "SELECT concat('a', …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Exception calling "Fill" with "1" argument(s): "SQL logic error no such
| function: concat"
Use the || operator instead. See SQLite concatenate strings.
Unable to load shared library ‘SQLite.Interop.dll’
PSSQLite ships native libraries for x64 and x86, not ARM64. On ARM64 Linux, the first query fails:
Exception calling ".ctor" with "1" argument(s): "Unable to load shared library 'SQLite.Interop.dll' or one of its dependencies.
On an ARM64 machine, use the sqlite3 shell (Step 8), or run PowerShell as x64.
Conclusion
PSSQLite is the shortest route from PowerShell to an SQLite file: Install-Module PSSQLite, then Invoke-SqliteQuery for everything else. Use parameters for values, and bulk copy for large loads. If you need a newer SQLite or you’re on ARM64, call the sqlite3 shell with -json instead, as in Step 8.
Further reading
- Install SQLite3 on Windows
- SQLite commands
- SQLite cheat sheet
- SQLite syntax
- SQLite introduction
- SQLite in C#
- PSSQLite: GitHub README, PowerShell Gallery
Tested with PowerShell 7.6.6, PSSQLite 1.1.0 (bundled SQLite 3.30.1) and sqlite3 3.45.1 on Linux (x64 container) on 7 October 2026.
