1. 程式人生 > 資料庫 >powershell玩轉sqlite資料庫詳細介紹

powershell玩轉sqlite資料庫詳細介紹

指令碼經常需要處理文字,有時候是行列整齊文字。那麼powershell指令碼處理行列文字有幾種方法呢?一種是excel,另外的一些是?access?sqlite?

sqlite是一個很小巧的,很方便嵌入到指令碼語言中的,關係型資料庫。它給powershell提供了一個免費的,處理行列整齊資料,儲存資料,統計資料的極品神器。
只要你學會了它,上天入地皆可去得。而且以後學sql server,mysql,都類似,沒有難度。

帶著引號搜本文關鍵字: "^_^上天入地皆可去^_^"
發文初衷:世界上幾乎沒有講powershell呼叫sqlite的帖子。

初稿,會更新。有錯誤歡迎指正,謝謝。

------------------【sqlite 欄位型別】------------------

sqlite只有5種資料型別,用於儲存。
資料型別佔用位元組描述
NULL
TEXT?使用資料庫編碼(UTF-8,UTF-16BE或者UTF-16LE)存放
INTEGER根據值的大小以1,2,3,4,6或8位元組存放值是有符號整形
REAL以8位元組IEEE浮點數存放
BLOB最多 1,000,000 位元組只是一個數據塊,完全按照輸入存放(即沒有準換)存放。

使用時會將【記憶體資料型別】和【儲存資料型別】之間進行轉換。
如將布林值,轉換成INTEEGER儲存。具體參見手冊:

http://www.sqlite.org/datatype3.html

沒有日期型,沒有布林型,這一點要注意。

------------------【應用場景,重要!】------------------

powershell 傳教士 原創文章 始作於 2016-01-01 元旦, 改 允許轉載,但必須保留名字和出處,否則追究法律責任

下為個人整理的應用場合,如有不妥,請斧正。

1 儲存資料。中量資料。
這個中量資料是指,由於sqlite表不支援分割槽,所以應該在一億條以下,或者更少。
excel表儲存資料有個行數(記錄條數)限制,104萬左右。比如我有110萬資料,只有一列,要統計列最大值。這時用excel就不方便了。
excel中每單元格最大儲存32k位元組,access2016中,每個text欄位的容量儲存為64k位元組,行數倒是夠用。

2 各種資料統計。
3 由於sqlite支援純記憶體資料庫,把所有庫放在記憶體中。可以結合上述兩種需求。即從大庫查詢(或匯出)部分資料,在記憶體中進行統計。

4 缺點是:資料展示不好。不像excel、access那樣(對業務人員)有表,圖。
5 sqlite是關係型資料庫,join,group by,order by這些基本功能和mysql,sql server比不遜色。單執行緒效能也很好。另外單機,綠色,軟體1M以下,支援資料量極大,比access強。

------------------【圖形管理工具】------------------

英文:
SQLiteStudiohttp://sqlitestudio.pl/
SQLiteManagerhttp://www.sqlabs.com/
SQLite Experthttp://www.sqliteexpert.com/
SQLite Developerhttp://www.sqlitedeveloper.com/
SQLiteSpyhttp://www.yunqa.de/delphi/doku.php/products/sqlitespy/index
RazorSQLhttp://www.razorsql.com/

中文:
SQLite Administratorhttp://sqliteadmin.orbmu2k.de/ 打不開3.x版本資料庫
navicat for sqlite//www.jb51.net/database/132499.html推薦
Database.NEThttp://fishcodelib.com/database.htm推薦

------------------【下載安裝】------------------
ps呼叫sqlite的兩種方法。這裡我們主要介紹第二種
1 https://psqlite.codeplex.com/
2 https://github.com/RamblingCookieMonster/PSSQLite
上述2種,都支援支援winxp,powershell2.0,及以上。

2.1 下載:
https://github.com/RamblingCookieMonster/PSSQLite/archive/master.zip

我們下載:PSSQLite-master-jb51.zip

2.2 建立【C:\Users\你的使用者名稱\Documents\WindowsPowerShell\Modules】目錄,並解壓:
把 PSSQLite-master\PSSQLite 這個目錄複製到,你的模組目錄中。
即modules目錄中,含有PSSQLite這個目錄。

2.3 檢視模組中的所有命令:
Import-Module pssqlite
get-command * -module pssqlite

返回
CommandType Name Version Source
----------- ---- ------- ------
Function Invoke-SQLiteBulkCopy 1.0.1 pssqlite
Function Invoke-SqliteQuery 1.0.1 pssqlite
Function New-SQLiteConnection 1.0.1 pssqlite
Function Out-DataTable 1.0.1 pssqlite

2.4 一鍵安裝命令:
#一鍵安裝命令依賴.net 4.5 及以上。powershell 3.0 及以上。如果不滿足條件,請用手動安裝方法。
mkdir "$env:USERPROFILE\Documents\WindowsPowerShell\Modules"
Invoke-WebRequest https://github.com/RamblingCookieMonster/PSSQLite/archive/master.zip -OutFile .\master.zip
add-Type -AssemblyName 'System.IO.Compression.Filesystem'
[System.IO.Compression.ZipFile]::ExtractToDirectory("$pwd\master.zip","$pwd")
Copy-Item -Recurse PSSQLite-master\PSSQLite "$env:USERPROFILE\Documents\WindowsPowerShell\Modules"
Import-Module pssqlite
get-command * -module pssqlite

------------------【命令幫助】------------------

Invoke-SqliteQuery -DataSource $庫檔名 -query $查詢字串 -as 輸出格式(PSObject,DataRow,DataTable,DataSet,SingleValue)


$記憶體庫 = New-SQLiteConnection -DataSource :MEMORY:
Invoke-SqliteQuery -SQLiteConnection $記憶體庫 -Query "CREATE TABLE OrdersToNames (OrderID INT PRIMARY KEY,fullname TEXT);" #建表語句
Invoke-SqliteQuery -SQLiteConnection $記憶體庫 -Query "INSERT INTO OrdersToNames (OrderID,fullname) VALUES (1,'Cookie Monster');" #插入語句
Invoke-SqliteQuery -SQLiteConnection $記憶體庫 -Query "SELECT xxx FROM yyy WHERE mmm=nnn;" #你想要的統計語句

問:csv如何入庫?
答:
最好用圖形工具搞,也可以用下列類似命令。
$dt1 = get-process | Out-DataTable
Invoke-SQLiteBulkCopy -DataTable $st1 -DataSource $DataSource -Table 表名
具體參見例子2

------------------【powershell操作sqlite經驗】------------------
1 不外乎查詢出行,查詢出列, 或查詢出表,然後foreach。
2 不外乎去重,合併結果,統計最大,列中數字合計。


問:乍開始我不熟悉sql語句咋辦?
答:
用柺棍!完全使用圖形程式(找傳教士要navicat for sqlite)來建表,匯入資料,在圖形軟體中執行sql。

問:現在我已經會用【常用sql語句】+【圖形程式】來處理資料了。為啥還要用指令碼呢?
答:
圖形程式畢竟只是根柺杖。你要處理的資料有可能要先取到一行,(比如用"_"先拆分,分成n列)預先用ps處理後再入庫。
庫裡輸出的行列,也很容易(用Out-GridView進行展示等。)所以說還是要ps+sqlite共同處理的。

---------------【根據官網手冊,增減的sql教程】----------------
sqlite官網,手冊位置:

http://www.sqlite.org/lang.html


問:什麼是(關係型)資料庫索引,索引有什麼好處壞處?
答:
索引是把無序的每條資料,添加了一個從小到大的順序,變成了有序的資料。
每個欄位都可以新增一個索引。或者n個欄位公用一個索引。
索引加速了查詢速度,降低了插入速度。

問:如何快速插入資料?
答:
1 較少併發寫入,最好只有一個執行緒在讀寫。
2 儘量減少索引。
3 使用事務。事務是由類似【START TRANSACTION】,【COMMIT】sql關鍵字包含的命令。
事務的作用是,在所有資料插入後,即【COMMIT】後,才一次性修改所有索引,而不是插入一條,修改一次索引。
4 使用.net聯結器封裝的事務。即類似sql bulkcopy 之類的方法。

問:事務相關的sql語句是?
答:
BEGIN TRANSACTION;事務開始
COMMIT TRANSACTION; 顯示事務被提交,資料表中的資料也發生了變化。
ROLLBACK TRANSACTION;回滾

問:為什麼傳教士也很愛sqlite?
答:
PRAGMA encoding; # 這個命令將返回庫編碼預設值,utf-8
用 中文表名,欄位名毫無問題!!!

問:開啟庫檔名後,列出所有《庫名》的sql語句是?
答:
PRAGMA database_list;

問:開啟sqlite庫檔案後,預設的資料庫名是?
答:
main

問:列出所有表名的sql語句是?
答:
SELECT name FROM sqlite_master WHERE type='table' order by name;

問:測試表是否存在的sql語句是?
答:
SELECT name FROM sqlite_master WHERE name='表名' ;

問:列出某個表的所有索引,要用的sql語句是?
答:
PRAGMA index_list(表名);

問:建立表的sql語句是?
答:
CREATE TABLE IF NOT EXISTS '表名' ('自增' INTEGER PRIMARY KEY AUTOINCREMENT,'欄位名2' REAL)
CREATE TABLE IF NOT EXISTS '表名' ('欄位名1' INTEGER AUTOINCREMENT,'欄位名2' REAL,'欄位名3' TEXT,'欄位名4' BLOB,PRIMARY KEY ('欄位名1'))
CREATE TEMP TABLE #建臨時表
PRIMARY KEY#主鍵
AUTOINCREMENT#自增

問:建立,刪除索引的sql語句是?
答:
CREATE INDEX IF NOT EXISTS 索引名 ON 表名(欄位名)
CREATE INDEX IF NOT EXISTS 索引名 ON 表名(欄位名 ASC,欄位名2 DESC)
CREATE UNIQUE INDEX IF NOT EXISTS 索引名 ON 表名(欄位名 DESC)#唯一索引

刪除索引:
DROP INDEX IF EXISTS 索引名

傳教士問:
我搜遍了全世界,包括官方,也搞不清楚為啥不是DROP INDEX IF EXISTS 索引名 on 表名?而是DROP INDEX IF EXISTS 資料庫名.索引名
一個庫裡,可以有多個表啊,請問誰能答?

問:什麼是sqlite資料清理?有什麼好處?
答:
刪除一條記錄時只是打上刪除標記。資料清理是徹底刪除資料。
大量的插入、更新和刪除等操作後,清理下資料,有助於讀取效能。還會歸還空間給作業系統。
sqlite的資料清理,只能對整個資料庫來操作。

問:資料清理命令是?
答:
Attached 資料庫名 連線資料庫。
vacuum 刪除已經打上刪除標記的表,記錄。
reindex 重生成索引

問:查看錶結構的sql語句是?
答:
PRAGMA table_info(表名);

問:清空表的sql語句是?
答:
delete from 表名;
update sqlite_sequence SET seq = 0 where name ='表名'; #自增欄位歸零。sqlite_sequence是main庫中的特殊表。

問:插入資料的sql語句是?
答:
INSERT INTO 表名 VALUES(null,21.5,'this is a texttest.','blob WER@#$@$%^^')

問:空值是?
答:
null

http://www.sqlite.org/lang_select.html
問:查詢資料的sql語句是?
答:
SELECT '欄位名' FROM '表名' WHERE 條件

問:查詢結果去重的sql語句是?
答:
SELECT DISTINCT '欄位名'
SELECT DISTINCT '欄位名1','欄位名2','欄位名3','欄位名4' #所有欄位的值完全相同,才算重複。

問:集合去重的sql語句是?
答:
SELECT 返回的集合1
UNION
SELECT 返回的集合2

問:查詢結果按 '欄位名' 分組輸出的sql語句是?
答:
SELECT '欄位名' FROM '表名' WHERE 條件 GROUP BY '欄位名' ;
GROUP BY 一定要放在WHERE之後,GROUP BY 一定要放在ORDER BY之前。

問:查詢結果按 '欄位名' 排序輸出的sql語句是?
答:
SELECT '欄位名' FROM '表名' WHERE 條件 ORDER BY '欄位名' ASC ;
SELECT '欄位名' FROM '表名' WHERE 條件 ORDER BY '欄位名' DESC ;

問:隱藏的自增列叫什麼?
答:
rowid或_rowid_
在沒有INTEGER型別的主鍵時,存在這個隱藏欄位。

問:sqlite有個叫sqlite3.exe的客戶端軟體。我可以用這個sqlite.exe + cmd + bat 玩轉sqlite資料庫麼?
答:
基本不行。
簡單來說powershell有內建的值型別,如小數數值,和表datetable。而bat中沒有。
powershell字串物件長度大,bat資料超過8000左右字母不行。

------------------【例子】------------------

# 例子1 :專門給菜鳥編寫的 PowerShell 操作Sqlite的例子。大量硬編碼,快速上手。win10測試通過。

Import-Module pssqlite


$sqlite庫檔名 = "a:\pscode\sqlite\test001.db" # 記憶體庫用 ':MEMORY:'
$sqlite庫名 = "" #預設main
$sqlite表名 = "biao001"

#region sql
#---
$建立_表_的sql語句 = ""
$建立_索引_的sql語句 = "CREATE INDEX IF NOT EXISTS $將要建立的索引名 ON $sqlite表名($將要建立索引的欄位名)"
#powershell 傳教士 原創例子 始作於 2016-01-01 元旦 允許轉載,但必須保留名字和出處,否則追究法律責任
#---
$列出所有_庫名_的sql語句 = 'PRAGMA database_list;'
$列出所有_表名_的sql語句 = "SELECT name FROM sqlite_master WHERE type='table' order by name;"
$列出某個_表結構_的sql語句 = "PRAGMA table_info($sqlite表名);"
$列出某個_表的所有索引_的sql語句 = "PRAGMA index_list($sqlite表名); "

#---
$測試_表是否存在_的sql語句 = "SELECT name FROM sqlite_master WHERE name='$sqlite表名' ; "

#---
$插入一條_資料資料_的sql語句 = ''

#---
$查詢_表_的sql語句 = ''

#---
$清空_表_的sql語句 = "delete from $sqlite表名 ;"
#---
#endregion sql


# 前提1 庫檔案確實存在,有【$sqlite庫檔名】。則建立連線。
# 前提2 庫檔案不存在,有【$sqlite庫檔名】和【$建立_表的sql語句】。則建立連線,然後建立表。
# 前提3 有【$建立_表的sql語句】和【$sqlite庫檔名 = ':MEMORY:'】字串。則建立連線,然後建立表。
if ($sqlite庫檔名 -eq ':MEMORY:')
{
 Write-Verbose '新建【記憶體】sqlite庫檔案'
 $我的Sqlite連線 = New-SQLiteConnection -DataSource $sqlite庫檔名
 Invoke-SqliteQuery -query $建立_表的sql語句 -DataSource $sqlite庫檔名 
}
else
{
 if (test-path $sqlite庫檔名)
 {
  Write-Verbose 'sqlite庫檔案已經存在'
  $我的Sqlite連線 = New-SQLiteConnection -DataSource $sqlite庫檔名
 }
 else
 {
  Write-Verbose '新建sqlite庫檔案'
  $我的Sqlite連線 = New-SQLiteConnection -DataSource $sqlite庫檔名

  #新建表
  $欄位字串 = ""
  $建立_表_的sql語句 = 
@"
CREATE TABLE IF NOT EXISTS '$sqlite表名' ($欄位字串)
"@
  Invoke-SqliteQuery -query $建立_表_的sql語句 -DataSource $sqlite庫檔名
 }
}

# 列出庫,列出表。前提【$我的Sqlite連線】已經建立。
Invoke-SqliteQuery -SQLiteConnection $我的Sqlite連線 -Query $列出所有_庫名_的sql語句 
Invoke-SqliteQuery -SQLiteConnection $我的Sqlite連線 -Query $列出所有_表名_的sql語句



# 建表索引。前提【$sqlite表名】,【$將要建立的索引名】,【$將要建立索引的欄位名】已經賦值。
$將要建立的索引名 = 'yyy'
$將要建立索引的欄位名 = 'bbb'
$建立_索引_的sql語句 = "CREATE INDEX IF NOT EXISTS $將要建立的索引名 ON $sqlite表名($將要建立索引的欄位名)"
Invoke-SqliteQuery -SQLiteConnection $我的Sqlite連線 -Query $建立_索引_的sql語句



# 測表是否存在,查表結構,查表索引。前提【$sqlite表名】已經賦值。
Invoke-SqliteQuery -SQLiteConnection $我的Sqlite連線 -Query $測試_表是否存在_的sql語句 #返回表名 
Invoke-SqliteQuery -SQLiteConnection $我的Sqlite連線 -Query $列出某個_表結構_的sql語句 
Invoke-SqliteQuery -SQLiteConnection $我的Sqlite連線 -Query $列出某個_表的所有索引_的sql語句



$查詢_表_的sql語句 = "select * from '$sqlite表名'  ;"
$查詢_表_的sql語句
Invoke-SqliteQuery -SQLiteConnection $我的Sqlite連線 -Query $查詢_表_的sql語句



#插入資料
$欄位1值 = 'null'
$欄位2值 = '121215687'
$欄位3值 = ''
$插入一條_資料資料_的sql語句 = "INSERT INTO $sqlite表名 VALUES($欄位1值,$欄位2值) ;" #本例表只有2個欄位 
Invoke-SqliteQuery -SQLiteConnection $我的Sqlite連線 -Query $插入一條_資料資料_的sql語句



#查詢資料
$查詢_表_的sql語句 = "select * from '$sqlite表名' ;"
$查詢_表_的sql語句
Invoke-SqliteQuery -SQLiteConnection $我的Sqlite連線 -Query $查詢_表_的sql語句



#清空
$清空_表_的sql語句 = "delete from $sqlite表名 ;"
Invoke-SqliteQuery -SQLiteConnection $我的Sqlite連線 -Query $清空_表_的sql語句
Invoke-SqliteQuery -SQLiteConnection $我的Sqlite連線 -Query $查詢_表_的sql語句

例子2:專門給菜鳥編寫的 PowerShell 操作Sqlite bulkcopy的例子。大量硬編碼,快速上手。win10測試通過。

Import-Module pssqlite

$sqlite庫檔名 = "a:\pscode\sqlite\test006.db" # 記憶體庫用 ':MEMORY:'
$sqlite庫名 = "" #預設main
$sqlite表名 = "biao001"

if (test-path $sqlite庫檔名)
{
 Write-error 'sqlite庫檔案已經存在'
 exit 1
}

$點net的DataTable = get-process | Out-DataTable #資料來源

$列集合 = $點net的DataTable.Columns
[array]$每個欄位名 = @()
foreach ($temp001 in $列集合)
{
 $每個欄位名 += $temp001.ColumnName
}

#powershell 傳教士 原創例子 始作於 2016-01-01 元旦 允許轉載,但必須保留名字和出處,否則追究法律責任

$每個欄位型別 = 'text'
$temp002 = $每個欄位名[0]
$建立_表_的sql語句 = 
@"
CREATE TABLE IF NOT EXISTS '$sqlite表名' ($temp002 $每個欄位型別)
"@
#Write-Warning $建立_表_的sql語句
Invoke-SqliteQuery -query $建立_表_的sql語句 -DataSource $sqlite庫檔名

for ($i = 1;$i -le $每個欄位名.Count ;$i++)
{
 $temp003 = $每個欄位名[$i]
 $建立_表_的sql語句 = 
@"
ALTER TABLE '$sqlite表名' ADD COLUMN '$temp003' $每個欄位型別 ;
"@
# Write-Warning $建立_表_的sql語句
 Invoke-SqliteQuery -query $建立_表_的sql語句 -DataSource $sqlite庫檔名
}

Invoke-SQLiteBulkCopy -DataTable $點net的DataTable -DataSource $sqlite庫檔名 -Table $sqlite表名 -force

文章到這就結束了,需要的朋友可以多看看例項。