2015年8月27日 星期四

SQLite 簡介

資料庫在處理大量的資料上是很必要的,但如果資料固定且量不多,或是資料庫只會在單機上使用,且沒有讓多人使用的需求的話,就不一定需要特別架一個資料庫系統;因此,可以使用類似 SQLite 這樣的嵌入式資料庫(embedded SQL database)。

SQLite 的資料庫(database)都是以單一檔案的形式存於磁碟中,不需要再安裝資料庫伺服器軟體,所以要把資料庫複製或建立在你的電腦上是相單簡單快速。
SQLite 是一個很小的 C 語言程式庫,且本身就完全包含資料庫引擎的功能,而且可以嵌入至其他程式中,完全不用額外的設定。

特性如下:
  • 支援ACID (Atomic, Consistent, Isolated, Durable) transaction。
  • Zero-configuration:無須管理者的設定及管理。
  • 支援大部分SQL92的語法。
  • 資料庫存在於一個單一的檔案中。
  • 資料庫系統所在機器的位元組順序(Byte order)無關。
  • 支援大小至2 terabytes (2^41 bytes)。
  • 記憶體需求小:小於3萬行的C語言程式碼。小於250KB的程式空間。
  • 大部分的資料庫操作皆快於一般資料庫系統。
  • 簡單易用的API。
  • 支援TCL。也有其他語言的支援可用。
  • 註解詳細的程式碼,以及超過90%的測試。
  • 程式庫自己包含完整的功能,無須其他額外的程式或程式庫。
  • 為public domain,可免費使用。
  • serverless
  • cross-platform - 使用unicode
  • 不會進行data type檢查


架构(architecture)
SQLite采用了模块的设计,它由三个子系统,包括8个独立的模块构成。
接口(Interface) 接口由SQLite C API组成,也就是说不管是程序、脚本语言还是库文件,最终都是通过它与SQLite交互的(我们通常用得较多的ODBC/JDBC最后也会转化为相应C API的调用)。 
编译器(Compiler) 在编译器中,分词器(Tokenizer)和分析器(Parser)对SQL进行语法检查,然后把它转化为底层能更方便处理的分层的数据结构---语法树,然后把语法树传给代码生成器(code generator)进行处理。而代码生成器根据它生成一种针对SQLite的汇编代码,最后由虚拟机(Virtual Machine)执行。 
虚拟机(Virtual Machine) 架构中最核心的部分是虚拟机,或者叫做虚拟数据库引擎(Virtual Database Engine,VDBE)。它和Java虚拟机相似,解释执行字节代码。VDBE的字节代码由128个操作码(opcodes)构成,它们主要集中在数据库操作。它的每一条指令都用来完成特定的数据库操作(比如打开一个表的游标)或者为这些操作栈空间的准备(比如压入参数)。总之,所有的这些指令都是为了满足SQL命令的要求(关于VM,后面会做详细介绍)。 
后端(Back-End) 后端由B-树(B-tree),页缓存(page cache,pager)和操作系统接口(即系统调用)构成。B-tree和page cache共同对数据进行管理。B-tree的主要功能就是索引,它维护着各个页面之间的复杂的关系,便于快速找到所需数据。而pager的主要作用就是通过OS接口在B-tree和Disk之间传递页面。

事务(Transaction)
事务的周期(Transaction Lifecycles) 
程序与事务之间有两件事值得注意: 
A、哪些对象在事务下运行——这直接与API有关。 
B、事务的生命周期,即什么时候开始,什么时候结束以及它在什么时候开始影响别的连接(这点对于并发性很重要)——这涉及到SQLite的具体实现。 
一个连接(connection)可以包含多个狀態(statement),而且每个连接有一个与数据库关联的B-tree和一个pager。Pager在连接中起着很重要的作用,因为它管理事务、锁、内存缓存以及负责崩溃恢复(crash recovery)。当你进行数据库写操作时,记住最重要的一件事:在任何时候,只在一个事务下执行一个连接。这些回答了第一个问题。 
一般来说,一个事务的生命和statement差不多,你也可以手动结束它。默认情况下,事务自动提交,当然你也可以通过BEGIN..COMMIT手动提交。接下来就是锁的问题。
关于这个图有以下几点值得注意: 
A、一个事务可以在UNLOCKED,RESERVED或EXCLUSIVE三种状态下开始。默认情况下在UNLOCKED时开始。 
B、白色框中的UNLOCKED, PENDING, SHARED和 RESERVED可以在一个数据库的同一时存在。 
C、从灰色的PENDING开始,事情就变得严格起来,意味着事务想得到排斥锁(EXCLUSIVE)(注意与白色框中的区别)。 
虽然锁有这么多状态,但是从体质上来说,只有两种情况:读事务和写事务。

SQL语法    由于以前用SQLServer或者ISeries,所以DDL的语法很汗颜 
   创建一个单个Primary Key的table    CREATE TABLE  [Admin] ( 
             [UserName] [nvarchar] (20)   PRIMARY KEY NOT NULL , 
             [Password] [nvarchar] (50)   NOT NULL , 
             [Rank] [smallint] NOT NULL , 
             [MailServer] [nvarchar] (50)   NOT NULL , 
             [MailUser] [nvarchar] (50)   NOT NULL , 
             [MailPassword] [nvarchar] (50)   NOT NULL , 
             [Mail] [nvarchar] (50)   NOT NULL 
   ) ; 
  创建一个多个Primary Key的table    CREATE TABLE  [CodeDetail] ( 
             [CdType] [nvarchar] (10)  NOT NULL , 
             [CdCode] [nvarchar] (20)  NOT NULL , 
             [CdString1] [ntext]   NOT NULL , 
             [CdString2] [ntext]   NOT NULL , 
             [CdString3] [ntext]   NOT NULL, 
              PRIMARY KEY (CdType,CdCode) 
   ) ; 
  创建索引    CREATE  INDEX [IX_Account] ON  [Account]([IsCheck], [UserName]); 
   还可以视图等等。

SQLite 分页查询
寫法1:    SELECT * FROM TABLE1 LIMIT  20 OFFSET 20 ;
寫法2:    SELECT * FROM TABLE1 LIMIT 20 , 20;

SQLite 文件的压缩 
在多次删除数据、插入数据、更新数据后,数据库体积增大,但实际有效数据量很小,则需要对数据库进行压缩、整理,把已经删除的数据从物理文件中移除。调用一下SQL命令即可:
VACUUM
VACUUM的实现

数据插入与更新
使用REPLACE替代INSERT、UPDATE命令。在无满足条件记录,则执行Insert,有满足条件记录,则执行UPDATE。
REPLACE INTO TABLE1(col1, col2, col3) VALUES(val1, val2,val3);
Insert or Replace Into 和Replace Into 的效果是一样的上面这句话也可以这样写
Insert or Replace INTO TABLE1(col1, col2, col3) VALUES(val1, val2,val3);

2013年3月21日 星期四

NET 錯誤回應


P1: Application Name                   (應用程式名稱)
P2: Application version                 (應用程式版本)
P3: Application time stamp           (應用程式時間標記)
P4: Assembly/Module name         (組件/模組名稱)
P5: Assembly/Module version      (組件/模組版本)
P6: Assembly/Module timestamp (組件/模組時間標記)
P7: MethodDef                             (通常為錯誤的函式的位置)
P8: IL offset                                  (..... 不知道 ........)
P9: Exception name                     (錯誤的類型)

 

error C2872:"IServiceProvider":模稜兩可的符號

網路上資料:

为了让C#使用一个非托管Dll中的类,于是想用托管c++包装成托管的dll,但是在编译时出现了以下错误:


error C2872: “IServiceProvider”: 不明确的符号     c:\program files\microsoft sdks\windows\v6.0a\include\servprov.h     96     CSRLib
.............................................................................
经过一番查找,知道了原因,解决方法如下:

是因为using namespace System;和windows.h中的名称冲突,

“windows.h”间接引入了 servprov.h,   而 servprov.h中有这样的定义:typedef interface IServiceProvider IServiceProvider; 
其中 IServiceProvider与System命名空间中的 IServiceProvider冲突,从而引起不确定性。


C# code





#include "CSRLib.h"//位置不对  
#include "LaneSpeech.h"  
#include <vcclr.h>  
#using "Speech_Re.dll" 



其中CSRLib.h中包含using namespace System;
而LaneSpeech.h中间接引入了windows.h头文件,因而使using namespace System;出现在windows.前面。

解决方法是令using namespace System;现出在windows.h的后面。

C# code






#include "stdafx.h"  
#include "LaneSpeech.h"  
#include <vcclr.h>  
#using "Speech_Re.dll"  
#include "CSRLib.h"  


但这样并不能完全解决问题,当代码中用到IServiceProvider(或其它冲突的名称)时同样会引起同样的错误。解决的办法是,不引入System命名空间而是用完全限定名使用其中的名称,如System::IServiceProvider
详细信息请参考以下文章:
http://msdn.microsoft.com/en-us/library/Aa712965
http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.languages.vc/2007-01/msg00087.html

2013年3月18日 星期一

C , C++ , C# 型態對照表


Conclusion在C#與C/C++作interop時,最重要的就是兩個語言型別的對應,整理如下:

Unmanage type in Wtypes.hUnmanaged C typeManaged class nameManaged C# typeDescription
HANDLEvoid *System.InPtrN/A32 bits on 32-bit windows operation systems, 64 bits on 64-bit windows operation systems.
BYTEunsigned charSystem.Bytebyte8 bits
SHORTshortSystem.Int16short16 bits
WORDunsigned shortSystem.UInt16ushort16 bits
INTintSystem.Int32int32 bits
UINTunsigned intSystem.UInt32uint32 bits
LONGlongSystem.Int32int32 bits
BOOLlongSystem.Int32int32 bits
DWORDunsigned longSystem.Int32int32 bits
ULONGunsigned longSystem.Int32int32 bits
CHARcharSystem.CharcharDecorate with ANSI
LPSTRchar *System.String or System.Text.StringBuilderstringDecorate with ANSI
LPCSTRconst char *System.String or System.Text.StringBuilderstringDecorate with ANSI
LPWSTRwchar_t*System.String or System.Text.StringBuilderstringDecorate with ANSI
LPCWSTRconst wchar_t*System.String or System.Text.StringBuilderstringDecorate with ANSI
FLOATFloatSystem.Singlefloat32 bits
DUOBLEDoubleSystem.Doubledouble64 bits

2013年1月28日 星期一

多執行緒

處理序(Process):

不同的應用程式,在作業系統中是以處理序 (Process) 做為分隔,讓不同的應用程式間不會相互干擾,我們從 Windows 工作管理員可以看到幾個頁籤,其中「應用程式」頁是指有視窗的應用程式,「處理程序」頁則列出所有正在執行的處理序。

執行緒 (Thread): 
是作業系統分配處理器 (CPU) 時間的基本單元,也就是當應用程式在執行時是經由執行緒向作業系統申請處理器的使用權。因為同一時間一個處理器只能給一個執行緒使用,作業系統中所有正在執行的處理序所建立的所有執行緒需要使用處理器時,會在一個佇列中等候作業系統分配可用的處理器時間,當執行緒使用處理器的時間量超過限額時就會暫止,由佇列中下一個執行緒繼續使用。每段時間量的長度視作業系統和處理器而定,由於這是一個極短的時間,例如每一個執行緒使用10毫秒,1秒鐘就會有100個執行緒次被執行,因此即使只有一個處理器,看起來就像多個執行緒同時在執行一樣,但終究和多工有所不同,多工是指不管把時間細分到多小都還是同時執行。


一個處理序可同時使用多個執行緖,那什麼時候應該使用多執行緒呢?

使用多執行緒最大的好處在於讓工作同時開工,如果我們使用單一執行緒執行一段會耗時很久的程式碼,這段時間無法經由使用者介面得到回應。如果使用多執行緒,就能讓一個執行緒儘量保持在閒置狀態以便快速回應使用者,另一方面又可以同時在其他執行緒進行作業,如果再搭配執行進度的回報,使用者就可以清楚地知道到底進行了多少工作,還有多少工作未完成。
使用多執行緒另一個可能得到的好處是可以節省無謂的等待時間,使用單一執行緒時,即使後面的步驟與前面的步驟互不相關,還是得等前面的執行完才能接下去做,使用多執行緒分頭辦事比較有效率,在同一時間內可以同時執行多項工作,自然可以花較少的時間。但這不意味只要使用多執行緒就能節省空等的時間,執行緒只是幫忙跑腿把工作交給處理器,有沒有多個閒置的處理器可以同時作業?再來,這些工作是不是真的要耗用很多處理器時間?還是短暫經手後交給其他主機的處理器或 I/O 裝置等,如果是後面這種情形,本機處理器多寡就不重要了,真正的執行者有沒有空閒才是關鍵,如果不同的執行緒送交的工作最後還是找上同一個執行工作者,還是沒有辦法同時執行,就達不到縮短工時的效果了。所以使用多執行緒只能讓工作同時啟動,要工作能真的同時並行才能有效縮短工時。


2012年12月27日 星期四

DataGridView 事件順序


「DataGridView」當中的「Cell」事件,
真是被搞的頭大,
觸發時機點很多,
要寫不少code去控制住,
而「Cell」也讓我很痛在心裡口難開,
順手記下幾個常用的Cell事件及順序。


  1. CellEnter-發生於 DataGridView 控制項中的目前儲存格變更時,或是當控制項收到輸入焦點時。 
  2. CellBeginEdit -發生於選定的儲存格開始編輯模式時。
  3. CellEndEdit-發生於目前所選的儲存格停止編輯模式時。
  4. CellValidating-發生於儲存格失去輸入焦點、啟用內容驗證時。 
  5. CellValueChanged-發生於儲存格的值變更時。
  6. CellValidated -發生在儲存格完成驗證之後。
  7. CellLeave-發生於儲存格失去輸入焦點,且不再是目前儲存格時。

正則表示法


^ : 表示一行文字的『開始位置』。如:"^Cat", 匹配的單詞Cat出現在行的開始處。
$ : 表示一行文字的『結束位置』。如:"Cat$" 匹配的單詞Cat出現來一行的結尾處。
[]:表示匹配括弧中字元『其中一個』。如:"[0123456789]"將匹配數位0到9的任何一個。
[]中的"^"符號:不再是前面說的位置符號,這裏它是『否定符號』
".":點字元出現在運算式中,表示匹配『任何字元』。
"|":某些字元中『可選擇』,我們可以採用選項字元。
"()":圓括號在運算式中也是被作『?』元字元使用
================================================================

例:
html中的<H1><H2><H3><H4><H5><H6>的標簽 :可寫成 "<H[123456]>" 或 "<H[1-6]>"
例:
匹配數位字元、小寫26個字母和大寫26個字母中的一個:可寫成 "[0-9a-zA-Z]"
例:
表示不包含數位0到9的字元。:"[^0-9]"

例:
"07.04.76":將匹配形如:07/04/76, 07-04-76,07.04.76。
例:
"[Bob|Robert]":則表示Bob或者Robert將被匹配。

例:
"^(From|Subject|Data): ":在電子郵件中查找所有以「From:」或者「Subject:」或者「Date:」開頭的行 

例:
"q[^u]":
Iraqi
Iraqian
miqra
qasida
qintar
qoph
zaqqum