delphi uniDac
Delphi 2010安裝及使用UniDAC 4.0
UniDAC是一個功能強大的非可視化跨數據庫的數據訪問組件,可用于Delphi,Delphi for .NET,C++Builder,and Lazarus (Free Pascal)。它提供了對流行數據庫服務器的統一訪問,像Oracle,Microsoft SQL Server,MySQL,InterBase,Firebird,PostgreSQL,SQLite,DB2,Microsoft Access,Sybase Advantage Database Server,Sybase Adaptive Server Enterprise,和其他數據庫(使用ODBC驅動)。
從網上下載到UniDAC 4.0的源碼版本,安裝過程如下:
1.進入"...\unidac40src\Source\Delphi14"文件夾,找到"Make.bat"文件,打開并修改IDE目錄路徑,如下:
set IdeDir="%PROGRAMFILES%\Embarcadero\RAD Studio\7.0
call ..\Make.bat Delphi 14 WIN32
因為我這里Delphi 2010不是安裝在默認位置,故修改如下:
set IdeDir="D:\Program Files\Embarcadero\RAD Studio\7.0
call ..\Make.bat Delphi 14 WIN32
2.執行"Make.bat"文件,自動執行一系列操作后,到"...\unidac40src\Bin\Delphi14"目錄下,可發現庫已經生成完畢;
3.運行Delphi 2010,菜單→"Tools"→"Options"→"Environment Options"→"Environment Variables",添加"...\unidac40src\Bin\Delphi14"完整路徑到"PATH"環境變量;
4.菜單→"Component"->"Install Packages...","Add"添加"...\unidac40src\Bin\Delphi14"目錄下的"dclunidac140.bpl";
5.菜單→"Tools"→"Options"→"Environment Options"→"Delphi Options"→"Library - Win32",在"Library Path"添加"...\unidac40src\Lib\Delphi14"路徑;
6.此時,已可以使用UniDAC連接數據庫了。若是需要鏈接查看源代碼,將"...\unidac40src\Source"路徑也添加到"Library Path"。
測試連接MySql數據庫:
1.新建一個應用程序,在面板上拖動TUniConnection、TMySQLUniProvider、TUniQuery、TUniDataSource、TDBGrid到窗體上,如下圖所示:
2.右鍵TUniConnection,選擇"Connection Editor...",填入數據庫連接參數,如下圖所示:
3.因為MySql一般設置字符集為UTF-8,而Delphi 2010工程字符集是Unicode,在"Options"頁面,設置"UseUnicode"為True,這可以通知服務器,客戶端和服務器雙方之間的所有數據都將通過UTF-8編碼,設置這個選項會轉換所有的TStringField字段類型到TWideStringField字段類型,使得幾乎所有的語言符號都可以正確工作,但另一方面,也引起工作延遲。
4.關聯其他項,在TUniQuery的SQL里面寫"select * from city",設置Active為True,運行程序,可以看到符號都可以正常顯示,如下圖所示:
代碼實現的方式如下:
procedure TForm1.FormCreate(Sender: TObject); begin UniQuery1.Connection := UniConnection1; UniDataSource1.DataSet := UniQuery1; DBGrid1.DataSource := UniDataSource1; with UniConnection1 do begin ProviderName := 'MySQL'; Username := 'root'; Password := '123'; Server := '192.168.82.201'; Database := 'world'; Port := 3306; SpecificOptions.Values['UseUnicode'] := 'True'; try Connect; UniQuery1.Close; UniQuery1.SQL.Text := 'select * from city'; UniQuery1.Open; exceptend; end; end; View Codedelphi2010下安裝UniDac
1. 進入 Source/Delphi14,編輯Make.bat 批改IdeDir="D:/Program Files/Embarcadero/RAD Studio/7.0 為你的Delphi2010安裝路徑,重視:雙引號只有前半項目組,沒有后半項目組。
2. 履行Make.bat。完成后在當前目次生成一個Unidac的目次。
3. 批改文件夾屬性,把所有文件夾的隱蔽屬性去掉。(針對win7,winxp下可省略這一步)
4. 批改C:/Users/All Users/Documents/RAD Studio/7.0/Bpl的接見權限,只要能進入即可。辦法如下:右鍵點擊Documents,在屬性的“安然”頁中選“高等”。高等頁面中有一項“拒絕”,選中它,點擊”更改權限”,再點擊”編輯”,選中”完全把握”,一路斷定。(針對win7,winxp下可省略這一步)
5. .把Unidac目次下*.bpl復制到C:/Users/All Users/Documents/RAD Studio/7.0/Bpl下。(針對win7,winxp下可省略這一步)
6. 打開Delphi2010,從菜單Component->Install Packages 安裝dclunidac140.bpl。
7. 把Source目次添加到delphi的library路徑,操縱路徑為:tools->options->environment options->Delphi options->library-win32,在library path中輸入。(winxp下可省略這一步,因為第六步操縱完后已經在library path中參加路徑)
8. 把Source/Delphi14/UniDAC/Lib目次添加到delphi的library路徑。
9. OK,如今可以連接各類數據庫啦
uniDAC用法總結
常言道,細微之處見體貼。UniDAC有一些過人的方法或屬性。
比如,刷新單條記錄(RefreshRecord)、多表更新的屬性(UpdatingTable)、宏替換參數(Macros)、
集成刪除/新增/修改/刷新/鎖定SQL語句、FetchRows,更讓人稱道的是引入了UpdateSQL組件。
TUniTable、TUniQuery和TUniStoredProc是用來檢索和編輯數據的UniDAC控件.
***************************TUniQuery******************************************************
UniDirectional屬性
ADO沒有單向數據集特性,所有的數據下載到本地,不停的開辟內存或釋放大內存,對三層的內存是一個極大考驗。TUniQuery有一個 UniDirectional屬性,支持單向速度,這點和DBX的想法不謀而合。況且,單向數據集特性速度非常快,在三層中,配合 TDataSetProvider,中間件將其Data包發送到客戶端,速度無可比擬。ADO也有流或XML格式包,但無論是XML或流格式,數據包遠比 CDS的包大幾倍。CDS封包技術很好!
FetchRows可以設定一次獲取記錄的行數
uniquery 和 unitable 的 SpecificOptions 屬性,需要設置 FetchAll=False才能使 FetchRows 的設置生效,而默認情況下, oracle 是設置Oracle.FetchAll=False;
而對去 sql server 和 mysql 等,卻是設置的 XXX.FetchAll=True
UniQuery.SpecificOptions.Values['FetchAll'] := BoolToStr(cbFetchAll.Checked, True);
UniDirectional屬性
ADO沒有單向數據集特性,所有的數據下載到本地,不停的開辟內存或釋放大內存,對三層的內存是一個極大考驗。TUniQuery有一個 UniDirectional屬性,支持單向速度,這點和DBX的想法不謀而合。況且,單向數據集特性速度非常快,在三層中,配合 TDataSetProvider,中間件將其Data包發送到客戶端,速度無可比擬。ADO也有流或XML格式包,但無論是XML或流格式,數據包遠比 CDS的包大幾倍。CDS封包技術很好!
UniDAC的單條記錄刷新
1、設置 SQLRefresh.TEXT的刷新SQL,一般要具體到單條記錄。比如:SQLRefresh.Text:='SELECT * FROM TName WHERE ID = :ID'(其中ID是表TName的主鍵,以確保返回只有一條記錄)
2、設置 TRefreshOptions為 [roAfterInsert,roAfterUpdate],即為新增后刷新,修改后刷新。
3、調用 UniQuery1.RefreshRecord
如果不做以上設置,僅執行UniQuery1.RefreshRecord 是一點反映也沒有的
UpdatingTable
屬性 UpdatingTable 服務顯示表將被更新(如果在查詢中有許多表)。如果它的值為空,正在使用的表就會顯示SQL操作的結果。 為了更好地對查詢結果進行操作,建議應總是設置屬性UpdatingTable
cachedupdates緩存更新
UniQuery默認狀態為行提交,使用前根據需要設置readonly或cachedupdates屬性
Filter過濾
UniQuery.Filter默認大小寫區分,請注意設置FilterOptions屬性([foCaseInsensitive]),TVirtualtable也存在相同情況
在UniQuery的SQL定義參數
我們經常會在UniQuery的SQL定義一些參數,在傳參時,需要特別注意,例如:
QExec.Close;
QExec.SQL.Text:= ‘select * from YHB where sYHBH=_YHBH’;
在傳參時有兩種寫法
1)最穩妥的寫法
QExec. ParamByName(‘P_YHBH’).DataType:= ftString;
QExec. ParamByName(‘P_YHBH’).ParamType:= ptInPut;
QExec. ParamByName(‘P_YHBH’).AsString:= ‘張三’;(此處可將AsString換成Value)
2)下面這個寫法我做了簡單測試,也是可以的,但對復雜的SQL傳參是否正確,未知
QExec. ParamByName(‘P_YHBH’).AsString:= ‘張三’;(在不對參數的數據類型和傳入傳出類型進行指定的情況下,絕對不能使用Value)
UniQuery.SetReadOnly屬性
1) 我們經常會用到多表關聯,且需要在前臺修改數據。舉個例子:a表和b表,在前臺兩個表字段都需要修改,則需要將SetReadOnly設置成false
2)特別注意:若將一個UniQuery.SetReadOnly設置成true,而這個表有一個自增長ID,那么你在提交數據時會出錯,跟蹤SQL會發現,ID被前臺前行傳了一個null值
UniQuery. RefreshRecord
可以刷新當前選擇的數據
數據提交
數據提交的順序,一定要注意:
對于單數據集的提交:
MyQuery. ApplyUpdates;
MyQuery. CommitUpdates;
Unidac:解決“trying to modify read-only Field”問題!
后臺使用SQL語句中,經常會關聯自定義函數或視圖,而CDS(TClientDataSet)對字段校驗比較嚴格,涉及到的自定義函數或視圖輸出的字段,都會強制改為ReadOnly為True屬性。
當后臺使用UniDAC+CDS,關聯視圖或自定義函數,為了數據一致性,有可能需要在前臺界面上修改CDS相關的自定義函數輸出的字段,即便是將 該字段設置為 readonly為false,
或將其字段的 FieldDefs屬性的attributes的faReadOnly去掉,系統也會拋出一個異常:trying to modify read-only Field。
解決問題很簡單,將TUniQuery.Options.SetFieldsReadOnly為false即可。
查一下TUniQuery.Options.SetFieldsReadOnly的幫助,這樣寫道:
If True, dataset sets the ReadOnly property to True for all fields that do not belong to UpdatingTable or can not be updated. Set this option for datasets
that use automatic generation of the update SQL statements only.
Macros屬性
要注意:如果要替換的值是一個字符串,那么記得在字符串兩邊加''號,因為Macro只是一個簡單的替換功能,他不會去判斷條件的類型。
其他
UniQuery默認情況下,有些varchar類型的字段有自動加了一個空格,請注意設置Options.TrimVarChar=true
UniQuery在進行Insert時,若字段不能為null且前臺操作未填寫時,可能會報錯,請設置RequiredFields=true
UniQuery在修改數據集時,默認的方式是按關鍵字生成SQL語句進行數據提交。還有另外兩種方式:一是設置updateSQL,一是設置KeyFields(具體請sql跟蹤查看)
UniQuery的數據排序屬性是IndexFieldNames
********************存儲過程*************************************************************************
TUniConnection, TUniSQL, TUniQuery, TUniStoredProc均可以執行存儲過程。
TUniConnection:
是一種最簡單的執行存儲過程的控件,但他有很多限制。TUniConnection不能具有SQL、存儲過程名和參數,不支持輸出參數也不支持存儲執行的預準備。當然,如果只是運行一個既沒有返回也沒有輸出參數設置,那TUniConnection是一個不錯的選擇。
TUniSQL:TUniSQL是一個被分離出的小控件,執行SQL語句但不返回結果集。它沒有數據存儲,但要消耗一些內存,但比TUniQuery和TUniStoredProc的執行速度快。
UniSQL.SQL.Text :=str
UniSQL.Execute;
s := 'Rows affected: ' + IntToStr(UniSQL.RowsAffected);
TUniQuery:TUniQuery除具有TUniSQL的執行功能外,還能返回結果集。
TUniStoredProc:TUniStoredProc是專門用來執行存儲過程的一個控件,可以返回結果集、輸出參數、執行準備以及通過CreateProcCall方法初始化等。
1、 參數類型
UniDAC支持四種參數類型:input, output, input/output, result
***********************************************TUniConnection************************************************************
事務
TUniConnection通過StartTransaction, Commit, Rollback等方法來控制本地事務,判斷一個事務是否開啟用InTransaction。
1、TUniConnection
建立和控件數據連接的控件,能訪問的數據庫包括:Oracle, SQL Server, MySQL, InterBase, Firebird, 和PostgreSQL.
雖然UniDAC對不同的數據庫提供了統一的訪問接口,但是對個別數據庫還是要進行一些特殊的設置,這些設置是一個字符串列表,你可以按以下代碼進行設置:
UniConnection.SpecificOptions.Values['CharLength'] := '1';
1、 Oracle
?
unidac 怎么對數據的插入和更新
1、使用unidac 如何得到有返回是否插入數據成功
2、使用unidac 如何得到有返回是否更新數據成功
下面是我關于數據查詢和無返回結果的插入數據,求教如何處理上面的兩個問題
--數據的查詢
--無返回值的插入數據
form1.UniQuery4.Close; form1.UniQuery4.SQL.Clear; form1.UniQuery4.SQL.Text:='insert UMTTare_Tmp (ScaleID,TareNo,TareWeigth,dummy) values(0,:a,:b,null)'; form1.UniQuery4.ParamByName('a').Value := form1.Edit1.Text; form1.UniQuery4.ParamByName('b').Value := form1.Edit2.Text; form1.UniQuery4.ExecSQL;UniTable2.Open; UniTable2.Append; TBlobField(UniTable2.FieldByName('CONTENT')).LoadFromFile('d:\PackageRequires.exe'); UniTable2.Post;UniQuery1.Close; UniQuery1.SQL.Text := 'SELECT * FROM TESTBLOB WHERE ID=9'; UniQuery1.ExecSQL; TBlobField(UniQuery1.FieldByName('CONTENT')).SaveToFile('d:\system\desktop\d.exe'); View Codeunidac直連oracle導入圖片到表中
基于UniDac的數據庫連接池
上篇提到了在XE~XE6下安裝UniDac。這篇,就基于UniDac,實現一個簡單的數據庫連接池。
文本的目錄:
1、簡單描述連接池實現的好處和原理;
2、連接池實現代碼;
3、給出使用連接池的Demo(窗體文件代碼 和 實現Pas代碼);
本文所有的代碼在XE環境上測試通過。如果要運行在XE以下版本,Demo請根據實現情況作修改。
1、簡單描述連接池實現的好處和原理
現在開始介紹第1點,使用Delphi開發數據庫應用軟件,那是一把利器。當然,Delphi也能開發其它類型的產品,比如游戲之類,盛大的傳奇就是用Delphi開發的;當然今天的話是數據庫應用。很多的ERP,我了解的金蝶ERP和用友ERP就是用Delphi開發的,當然他們也有Web版本。MIS系統初期時基于單機版本,現在很多財務軟件就有單機版本,后來發展成C/S架構,就是客戶端-服務端架構,客戶端提供UI界面,服務端實現業務邏輯;在后來就發展到多層結構,一直到N層,實現分布式結構。其實不管是單機結構,還是C/S結構,還是發展到目前的三層及多層結構,本身并對業務邏輯的編寫,并沒有多大差別。資料的CURD(C=Create,U=Update,R=Read ,D=Delete)操作都是一樣。這就涉及到一個問題。在連接數據庫,包括ODBC,ADO,ADO.net 還是 DBExpress,還是第三方的連接驅動,都是程序和數據庫的連接通道,本文的UniDac也是一個通道。我們知道每一次數據庫連接,都是需要消耗資源,包括TCP/IP連接,SQL緩存等開銷。現在的問題,如果有一個 Pool,能把每次申請的SQLConnetion用完后,再放回池里,不釋放,以備下次使用,那樣不是節省了開銷,又增加了效率,讓連接訪問數據庫為更快速,特別是多線程下,對數據庫的訪問。那么實現原理是什么呢?可以設計簡單或設計復雜,這要視實際情況而定。一般的思路,池對外提供一個接口,供程序調用。如果沒有SQL連接,池自己生產一個,返回SQL連接對象;程序調用完,池就回收,不實際釋放,等待下次調用。這里有個問題,就是控制池的最大連接數問題,不過對于一般的應用,這個問題可以先不用考慮。下面是訪問時序圖:
2、連接池實現代碼:
3、給出使用連接池的Demo;
窗體代碼:
object Form1: TForm1 Left = 0 Top = 0 Caption = 'Form1' ClientHeight = 310 ClientWidth = 682 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object Button1: TButton Left = 24 Top = 8 Width = 138 Height = 25 Caption = #20027#32447#27979#35797 TabOrder = 0 OnClick = Button1Click end object Button2: TButton Left = 24 Top = 55 Width = 138 Height = 25 Caption = #22810#32447#31243#27979#35797 TabOrder = 1 OnClick = Button2Click end object Memo1: TMemo Left = 184 Top = 8 Width = 490 Height = 294 Lines.Strings = ( 'Memo1') TabOrder = 2 end object Button3: TButton Left = 24 Top = 96 Width = 138 Height = 25 Caption = #33719#21462#27744'SQL'#36830#25509#23545#35937#20010#25968 TabOrder = 3 OnClick = Button3Click end end View Code實現代碼:
unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;const WM_PUSHDATA=WM_USER+100;type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Memo1: TMemo; Button3: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private procedure GetDtaTest; { Private declarations } procedure WMHandlePUSHDATA(var msg:TMessage);message WM_PUSHDATA; public { Public declarations } end;var Form1: TForm1;implementationuses sqlConPool,uni;{$R *.dfm}//開啟多個線程測試 procedure TForm1.Button2Click(Sender: TObject); var i: integer; begin for i := 0 to 50 do begin TThread.CreateAnonymousThread(GetDtaTest).Start; end; end;//顯示當前連接池中SQLConnetion對象 procedure TForm1.Button3Click(Sender: TObject); begin ShowMessage(Format('PoolCount=%d',[SQLConnectionPools.PoolCount])); end;//通過獲取SQL對象,獲取數據 procedure TForm1.GetDtaTest(); var qry: TUniQuery; uid: integer; susername, spw: string; str:String; begin // 獲取對象 qry := QryPools.Pop; try with qry do begin SQL.Text := 'select * from user'; Open; while not eof do begin uid := FieldByName('id').AsInteger; susername := FieldByName('username').AsString; spw := FieldByName('password').AsString;str:= Format('id=%d ,username=%s,password=%s',[uid,susername,spw]);//因為如果在工作線程中,避免在主線程下操作UI; SendTextMessage(self.Handle,WM_PUSHDATA,0,str);Next; end; end; finally // 回收對象 QryPools.Push(qry); end; end;//打印顯示獲取數據 procedure TForm1.WMHandlePUSHDATA(var msg: TMessage); var str:string; begin str:=String( msg.LParam ); Memo1.Lines.Add(str) ; end;//主線程下測試 procedure TForm1.Button1Click(Sender: TObject); begin GetDtaTest(); end;end. View Code?
Delphi中SQLite如何讀寫二進制字段(Blob類型)
在Delphi中,有大量的組件可以操作SQLite數據庫,如UniDAC就是其中一個比較優秀的,當然還有ASQLite3Components,也有SQLite3版的ODBC驅動,可直接用ADO操作。本文簡要說明SynopseSQLite3讀寫二進制字段,先說下SynopseSQLite3的優點,靜態編譯集成SQLite3引擎,不需要額外的DLL支持,支持SQLite3加密,支持JSON表,支持網絡版的SQLite3.支持線程安全保護.首先建一個表,字段類型為BLOBSL.Add('CREATE TABLE IF NOT EXISTS TEST (');SL.Add('FileName TEXT PRIMARY KEY,');SL.Add('Data BLOB);');SL.Add(''); 復制代碼寫入二進制數據:varFFileStream:TFileStream;FData:array of Char;FSQLR:TSQLRequest;ASQL:AnsiString;beginFFileStream:=TFileStream.Create('test.xml',fmOpenReadWrite);ASQL:='INSERT INTO TEST(FileName,Data) VALUES('+QuotedStr('test.xml')+',?)';trySQLite數據庫對象.Execute('DELETE FROM TEST');// SetLength(FData,FFileStream.Size);FFileStream.Position:=0;FFileStream.Read(PChar(FData)^,Length(FData));FSQLR.Prepare(SQLite數據庫對象.DB,ASQL);FSQLR.Bind(1,PChar(FData),Length(FData));FSQLR.Execute;finallyFreeAndNil(FFileStream);end; 復制代碼其中問號是參數,SQLite數據庫對象類型為TSQLDataBase讀取數據并寫入到文件:varFBlobField:TSQLBlobStream;FFileStream:TMemoryStream;FData:array of Char;begintryFFileStream:=TMemoryStream.Create;FBlobField:=SQLite數據庫對象.Blob('','TEST','Data',1,True);tryFBlobField.Position:=0;SetLength(FData,FBlobField.Size);FBlobField.ReadBuffer(PChar(FData)^,FBlobField.Size);FFileStream.Write(PChar(FData)^,FBlobField.Size);FFileStream.SaveToFile("test.xml");finallyFreeAndNil(FBlobField);FreeAndNil(FFileStream);end;exceptResult:='';end; View CodeUniDAC使用日記
UniDAC使用日記
1. UniQuery默認狀態為行提交,使用前根據需要設置readonly或cachedupdates屬性
2. UniQuery.Filter默認大小寫區分,請注意設置FilterOptions屬性([foCaseInsensitive]),TVirtualtable也存在相同情況
3. UniQuery默認情況下,有些varchar類型的字段有自動加了一個空格,請注意設置Options.TrimVarChar=true
4. UniQuery在進行Insert時,若字段不能為null且前臺操作未填寫時,可能會報錯,請設置RequiredFields=true
5. UniQuery在修改數據集時,默認的方式是按關鍵字生成SQL語句進行數據提交。還有另外兩種方式:一是設置updateSQL,一是設置KeyFields(具體請sql跟蹤查看)
6. UniQuery的數據排序屬性是IndexFieldNames
7. 數據提交的順序,一定要注意:
對于單數據集的提交:
MyQuery. ApplyUpdates;
MyQuery. CommitUpdates;
8. DataM中提供了一個功能Clone(Source, Dest):一、Dest是TVirtualTable,則完整的將源數據集復制;二、Dest是UniQuery,則是將Source的SQL復制到Dest,并Open
9. UniQuery.SetReadOnly屬性說明
1) 我們經常會用到多表關聯,且需要在前臺修改數據。舉個例子:a表和b表,在前臺兩個表字段都需要修改,則需要將SetReadOnly設置成false
2) 特別注意:若將一個UniQuery.SetReadOnly設置成true,而這個表有一個自增長ID,那么你在提交數據時會出錯,跟蹤SQL會發現,ID被前臺前行傳了一個null值
10.UniQuery. RefreshRecord,可以刷新當前選擇的數據
11.我們經常會在UniQuery的SQL定義一些參數,在傳參時,需要特別注意,例如:
QExec.Close;
QExec.SQL.Text:= ‘select * from YHB where sYHBH=:P_YHBH’;
在傳參時有兩種寫法
1)最穩妥的寫法
QExec. ParamByName(‘P_YHBH’).DataType:= ftString;
QExec. ParamByName(‘P_YHBH’).ParamType:= ptInPut;
QExec. ParamByName(‘P_YHBH’).AsString:= ‘張三’;(此處可將AsString換成Value)
2)下面這個寫法我做了簡單測試,也是可以的,但對復雜的SQL傳參是否正確,未知
QExec. ParamByName(‘P_YHBH’).AsString:= ‘張三’;(在不對參數的數據類型和傳入傳出類型進行指定的情況下,絕對不能使用Value)
UniDAC的過程中一定要注意,在DataM中提供了一個函數PrepareParam,請注意看一下。à在ADO
12.Sybase的一個特性
update a set a.fSJ=b.fSJ
from table1 a join table2 b on a.sYPBSM=b.sYPBSM
上述SQL語句在Sybase下執行不能通過,請改寫成如下SQL(在MS和ASE中都能執行通過)
update table1 set fSJ=b.fSJ
from table1 a join table2 b on a.sYPBSM=b.sYPBSM
UniDAC官方網址:http://www.devart.com/
一、連接數據庫Connecting to Database
通用連接屬性
Provider
第一個就應該設置的屬性,指定要連接的數據庫類型,根據指定的數據庫連接類型不同其它的設置也會發生相應的變化;
Username and Password
登錄數據的有效用戶名和密碼;
Server
通常將此設成要連接數據庫所在的計算機名或IP地址,如果將此屬性設置為空,對于MySQL, InterBase連接數據庫方式, UniDAC 將試圖連接本地(Localhost)。
Oracle:
客戶端模式下,指定的Server名稱一定要出現在tnsnames.ora中,且有效,設置效果如下:
直連模式(Direct mode)下:在此模式下,運行軟件的計算機可以不安裝Oracle客戶端而連接Oracle數據庫,但要做以下設置:
設置直連模式
設置Server
指定Server格式:Host:Port:SID.
注:客戶端模式和直連模式的設置不能混淆,否則無法執行。兩種格式嚴格區分。
效果如下:
SQL Server:
指定要連接的數據庫所在的網絡IP,且有效,如果采用的不是默認端口(1433),Server應該這樣設置:HostName,PortNumber.
Database
這個屬性只對SQL Server, MySQL, PostgreSQL, InterBase, and SQLite 連接方式有效,
Port
指定TCP/IP協議訪問的有效端口
MySQL – 默認端口 3306
PostgreSQL -默認端口5432
二、UniDAC(版本:2.7)連接數據庫必要文件或局限需求
1、Oracle連接
Oracle在采用直連模式將受到以下限制:
特別要注意的是(包括:應用TUniLoader):
1)、應用直連模式,本地執行程序的客戶機必須要安裝TCP/IP協議
2)、注意防火墻
3)、數據庫的triggers、check constraints、clustered tables、loading of remote objects、user-defined types將得不到支持
4)、available, like OBJECT, ARRAY, REF, XML, BINARY_DOUBLE, BINARY_FLOAT這些類型將變為不可用
5)、TUniLoader的應用版本應高于Oracle client 8.17
以下是英文原文:
?
SQL Server連接
提供連接支持
服務端: SQL Server 2005 (including Compact and Express editions), SQL Server 2000, SQL Server 7, and MSDE.
客戶端: SQL OLE DB and SQL Native Client.
環境需求
MDAC(Microsoft Data Access Components)版本不低于2.5
My SQL連接
My SQL提供的連接也包括直連和客戶端連接方式,默認采用的是直連方式,如果要更改連接方式,在應用程序分發時要帶上libmysqld.dll
二、Delphi與各數據庫數據類型比較
Delphi數據類型與各數據庫數據類型對比如下表,如有具體說明見表中腳注:
三、UniDAC更新數據
1、數據自動更新
TUniTable、TUniQuery和TUniStoredProc是用來檢索和編輯數據的UniDAC控件,
四、主從關系表
五、存儲過程
1、TUniConnection, TUniSQL, TUniQuery, TUniStoredProc均可以執行存儲過程。
TUniConnection:
是一種最簡單的執行存儲過程的控件,但他有很多限制。TUniConnection不能具有SQL、存儲過程名和參數,不支持輸出參數也不支持存儲執行的預準備。當然,如果只是運行一個既沒有返回也沒有輸出參數設置,那TUniConnection是一個不錯的選擇。
TUniSQL:
TUniSQL是一個被分離出的小控件,執行SQL語句但不返回結果集。它沒有數據存儲,但要消耗一些內存,但比TUniQuery和TUniStoredProc的執行速度快。
TUniQuery:
TUniQuery除具有TUniSQL的執行功能外,還能返回結果集。
TUniStoredProc:
TUniStoredProc是專門用來執行存儲過程的一個控件,可以返回結果集、輸出參數、執行準備以及通過CreateProcCall方法初始化等。
參數類型
UniDAC支持四種參數類型:input, output, input/output, result
六、事務處理
TUniConnection通過StartTransaction, Commit, Rollback等方法來控制本地事務,判斷一個事務是否開啟用InTransaction。
七、控件詳解
1、TUniConnection
建立和控件數據連接的控件,能訪問的數據庫包括:Oracle, SQL Server, MySQL, InterBase, Firebird, 和PostgreSQL.
雖然UniDAC對不同的數據庫提供了統一的訪問接口,但是對個別數據庫還是要進行一些特殊的設置,這些設置是一個字符串列表,你可以按以下代碼進行設置:
UniConnection.SpecificOptions.Values['CharLength'] := '1';
Oracle
?
多線程下使用使用 UniDAC+MSSQL
ADO線程不安全,UniDAC 在使用MSSQL也是如此。其實這是微軟COM問題,不怪Devart公司。
一般解決方法是在線程開始啟用 CoInitialize(nil),線程結束調用 CoUninitialize 。如果你使用多種數據庫連接,比如三層中經常切換到MSSQL和Oracle,我們只需在判斷 TUniConnection 的連接前事件 OnBeforeConnect 寫下如下代碼:
需要注意的是,必須先判斷連接控件 (ServConn <> nil) 是否為空,否則,你會陷入指針釋放的問題。
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids, DBGrids, DB, DBAccess, Uni, MemDS, UniProvider, InterBaseUniProvider; type TForm1 = class(TForm) UniConnTest: TUniConnection;//用于數據庫的連接 InterBaseUniProTest: TInterBaseUniProvider;//ib/FB的數據提供 UniQryTest: TUniQuery; UniDataSrTest: TUniDataSource; DBGrid1: TDBGrid; Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin with UniConnTest do begin ProviderName := 'interbase';//這里確定為interbase 但是可以支持firebird Password := 'masterkey';//數據庫密碼 Username := 'sysdba';//數據庫密碼 Server := ''; Database := 'TD_HOUSE.FDB';//數據庫文件的位置,這里在當前目錄 SpecificOptions.Clear; SpecificOptions.Add('InterBase.ClientLClientLClientLClientLibraryibraryibraryibrary=fbembed.dll'); //設置設置設置設置embeddll驅動位置 SpecificOptions.Add('InterBase.CharLength=0') ;//設置設置設置設置為0讓, unidacunidacunidacunidac自動讀取fb設置設置設置設置 SpecificOptions.Add('SQLDialet=3'); //設置設置設置設置為3 SpecificOptions.Add('USEUnicode=true');//遲滯unicode 有人說有問題 我沒有發現 try Connect; ShowMessage('OK'); except ShowMessage('eer'); end; end; end; procedure TForm1.Button2Click(Sender: TObject); begin UniQryTest.Close; UniQryTest.SQL.Text := 'select * from TB_SYS_LOG'; // UniQryTest.FetchingAll; UniQryTest.DisableControls; UniQryTest.Open; UniQryTest.EnableControls; end; end. View Code有網友問我常用的控件及功能。我先大概整理一下,以后會在文章里面碰到時再仔細介紹。
Devexpress VCL 這個基本上覆蓋了系統界面及數據庫展示的方方面面,是做桌面系統必備的一套控件,目前的版本是2011.2.3, 支持win32 及win64。
AutoUpgrader 這個是自動更新的一個小控件,適合桌面程序自動更新,但是自從2007 年后,就沒有更新了,我對其進行了修改,使其可以安裝在delphi XE2 上,
同時支持win64。
Devart 公司出品的UniDAC,ODAC,SDAC,IBDAC, 這幾個是目前delphi 數據庫存取最好的控件,UniDAC 幾乎支持所有的數據庫存取,而后面幾個則是針對每種
提供專用的訪問和控制功能,尤其是ODAC ,可以直接使用TCP/IP 連接oracle,免去安裝Oracle客戶端的麻煩,非常適合各種場合應用(在xe2 里面,已經可以直接支持用
Iphone 訪問oracle了)。
Advanced Data Export 和 Advanced Data Import 這是EMS 公司出品的數據導入、導出控件,幾乎可以導入、導出常用的各種數據格式,是數據庫轉換和備份的必備控件。
NativeXml 是生成和解析XML 文件及格式一個非可視控件(使用時,直接引用單元),是一個輕量級的xml 解析器,支持windows 和linux, 以前是收費的,
現在是開源了(唉,可惜我當時的銀子了)。
Paxcompiler 是目前最快的,最穩定的Pascal 腳本解析器,我前面介紹的delphi web 腳本就是使用它做解釋器的,目前還不支持win64,據作者說今年元月底就會支持win64.
kbmMW 是目前唯一與Remobjects 并駕齊驅的delphi多層解決方案, 比Remobjects 緊湊、便宜,但是功能絕不輸給Remobjects。我后面后介紹使用kbmMW 實現各種多層應用。
TeeChart Pro 在delphi 的圖形顯示方面目前唯一的選擇,雖然從delphi 3 就隨delphi 捆綁發布,但是捆綁的是標準版,很多功能都不全,要展示各種絢麗的統計、分析功能,
還是要用專業版(呵呵,領導們都是喜歡這個的)。最新的TeeChart Pro 已經支持firemonkey了(兼容性還有點問題),你可以把pc 上的絢麗圖形放到Iphone 上了。
從 Delphi 1 開始,delphi 每個版本都會有報表工具,但是每次自帶的報表工具都相當不給力,幾乎沒有人使用,因此出現了幾個非常不錯的第三方報表工具,例如Reportbuilder,
Fastreport 等,由于今年出的delphi xe2 開始捆綁Fastreport 標準版,同時Reportbuilder 的價格高的離譜,而且fastreport 確實非常不錯,建議報表工具還是用Fastreport.
Delphi 目前應該還是windows 平臺非常強的開發工具,因此經常會用來寫windows 服務,雖然Delphi 本身支持winservice 的開發,但是功能也就是能開發而已,要開發專業的
winservice, 還是要用Svcom , 這個可以像普通程序一樣調試服務程序,同時支持 界面和服務在同一個程序里面,調試、配置、安裝都非常方便。
這幾年隨著web 技術的發展,各種JS 框架越來越多,與delphi 后臺結合,基本上都需要使用JSON 格式,delphi XE 開始支持JSON ,但是個人認為語法復雜,理解困難,
幸好有開源的Super Object Toolkit,非常直觀和簡單,在服務器端運行也非常穩定,我上面的文章也有介紹。
以上就基本上是我常用的控件,當然還有些控件由于比較偏,就不再做介紹了。我個人的原則是只要有現成的控件,我不會再去做類似的,畢竟個人精力和能力有限,而人家專業做控件的,
無論從質量和功能上都有保證,同時只要是正版用戶,作者都會很及時的修改bug 的,自己把精力放到實現第三方無法實現的地方就可以了
UniDAC使用SQLite數據庫可能碰到的問題
如果說要使用第三方控件來鏈接操作數據庫,我想UniDAC絕對是個很好的選擇。對于SQLite來說,像這樣能較好支持中文的第三方控件更是少有了。不過使用UniDAC來說可能會碰到一些有趣的問題,特別是對于新手來說。現在說說我安裝控件后使用SQLite碰到的問題:
一、SQLite3.dll 不能被加載的問題
開始以為只要在程序主目錄下就可以直接在鏈接時被調用,但其實不是這樣的,默認情況下一般是從C:/windows/system32目錄下調用的,至少對于編程工具來說這是默認的調用路徑,所以將dll拷到目錄下即可解決,這個其實也不算是什么問題。
二、UniDAC這個控件很有意思,在鏈接數據庫時是不提供打開文件對話框的,如果你直接填寫數據庫名的話,這個數據庫應該會是直接被建立在桌面上了。
三、數據庫不能被打開,Database could not be Opened!
據說從3.5版本以后,SQLite是不支持中文路徑的,不過我用3.5以上版本也能鏈接成功,當然,這是在解決問題之后,解決之前的問題是如果把路徑設置為英語,那絕對是鏈接沒問題,換中文的話打死也鏈接不上,所以我想這方面多少應該是有些關系的。
四、SQLite function is not linked!
SQLite的函數未鏈接,說白了就是函數調用失敗,我不知道其它人碰到會是什么樣的原因,但我這里碰到的應該是sqlite3.dll損壞造成的函數調用失敗,不能說是肯定,但在替換過兩次后,鏈接恢復正常。想了想,用sqlite3.dll的肯定不只一種軟件,如果你安裝這類軟件時,軟件沒有檢查sqlite3.dll的存在和版本,并且直接替換掉了你原來使用的dll,那就很有可能造成版本不兼容問題,從而導致數據庫鏈接失敗,至少我看到了,當我恢復我原來的dll時,另一個原來使用正常的軟件掛掉了……
五、不是問題的問題,用UniDAC設置鏈接時我經常會看到unsuppored metadata kind ,看上去不是什么特別的異常,應該只是設置鏈接的步驟不對,先把conneted設置為False再操作就OK了。
讓unidac支持加密的sqlite
讓unidac支持加密的sqlite
sqlite是一款優秀的單文件數據庫軟件,只需一個dll就就完全包含數據庫引擎的功能,而且可以嵌入至其它程序中,完全不用額外的設定。其特性如下:
* 支持ACID (Atomic, Consistent, Isolated, Durable) 交易。
* 零組態設定(Zero-configuration),無須管理者的設定及管理。
* 支持大部分SQL92的語法。
* 數據庫存在于一個單一的文件中。
* 數據庫系統所在機器的字節順序(Byte order)無關。
* 支援大小至2 TB (2^41 bytes)。
* 極小的內存需求:小于3萬行的C語言程序代碼。小于250KB的程序空間。
* 大部分的數據庫操作皆快于一般流行的數據庫系統。
* 簡單易用的API。
* 支援TCL。也有其它語言的支持可用。
* 注釋詳細的程序代碼,以及超過90%的測試。
* 鏈接庫自己包含完整的功能,無須其它額外的程序或鏈接庫。
* 程序代碼版權為public domain。任何用途皆可免費使用。
不過sqlite開源版是不支持加密的,只留有接口,沒有進行實現,不過開源界從來不缺乏雷鋒,于是有了wxsqlite工程,wxsqlite是 sqlite的wxWidgets c++實現接口,順便用aes加密算法實現了sqlite的加密功能,與sqlite 100%兼容,實在是贊!
我常用的數據庫連接組件是unidac,最新的3.x版本已經支持sqlite,不過也沒有實現加密函數定義,于是自已動手幫它加上,我用的版本是3.0.0.6。
\UniProviders\SQLite\LiteCallUni.pas是調用接口定義
// functions下面加上以下代碼:
_sqlite3_key = function(
pDb: Tsqlite3; // Database handle
pKey: PAnsiChar; // Database PassWord (UTF-8)
nKey: Integer // Database sizeofpassword
): integer; {$IFNDEF CLR}cdecl;{$ENDIF}
_sqlite3_rekey = function(//If the current database is not encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the database is decrypted.
pDb: Tsqlite3; // Database handle
pNew: PAnsiChar; // Database New PassWord (UTF-8)
nNew: Integer // Database sizeofnewpassword
): integer; {$IFNDEF CLR}cdecl;{$ENDIF}
...........................
var 下面加
sqlite3_key: _sqlite3_key;
sqlite3_rekey: _sqlite3_rekey;
........................................
procedure InitFunctions;
begin
{$IFDEF CLR}下面加
sqlite3_key := {$IFNDEF UNIDACPRO}LiteCallCLR{$ELSE}LiteCallCLRUni{$ENDIF}.sqlite3_key;
sqlite3_rekey := {$IFNDEF UNIDACPRO}LiteCallCLR{$ELSE}LiteCallCLRUni{$ENDIF}.sqlite3_rekey;
...................
{$ELSE}下面加
sqlite3_key := GetProc('sqlite3_key');
sqlite3_rekey := GetProc('sqlite3_rekey');
..................................
initialization
LockInit := TCriticalSection.Create;
{$IFNDEF CLR}下面加
sqlite3_key := @NotLink;
sqlite3_rekey := @NotLink;
..................................
\UniProviders\SQLite\LiteClassesUni.pas是引擎調用接口實現
Check(sqlite3_open(PAnsiChar(UTF8Encode(FDatabase)), FSQLite));
下面加:
測試加密,解密正常。
用UniQuery添加數據
可以直接添加blob sub_type 1類型的字符串數據,如下面的text字段為blob sub_type 1.雖然UniTable也可以實現同樣的功能,但由于其要載入所有記錄內存,所以效率不是太好.而UniQuery.Params.ParamByName方法則不能直接添加blob sub_type 1類型的數據,也不能用loadfromstream(ms)進行加載數據,所以不行. procedure TForm1.FormCreate(Sender: TObject); begin self.UniConnection1.Connect; UniQuery1.Close; UniQuery1.SQL.Clear; UniQuery1.SQL.Text:='select * from tableblob where 0=1'; {返回空數據集,避免加載所有記錄到內存,提高效率} UniQuery1.Open; UniQuery1.Prepared:=true; end; procedure TForm1.Button2Click(Sender: TObject); begin istart:=GetTickcount; //showmessage(inttostr(length(memo1.text))); //UniQuery1.Close; {如果字段內容超長,并且沒有檢查的話,需要close再open,才能保證下一條合法記錄的添加,否則會再次報內容超長} //UniQuery1.open; UniQuery1.Append; UniQuery1.Fields.FieldByName('id').AsInteger:=GetMaxID1; UniQuery1.Fields.FieldByName('name').AsString:=Memo1.text; UniQuery1.Fields.FieldByName('text').AsString:=Memo2.Text; UniQuery1.Fields.FieldByName('datetime').AsDateTime:=Now; UniQuery1.Post; //UniQuery1.Transaction.Commit; {由于UniQuery是自動提交事務的,所以這句不需要} iend:=GetTickCount; caption:=floattostr((iend-istart)/1000); showmessage(UniQuery1.Fields.FieldByName('text').AsString); end; View Code?
轉載于:https://www.cnblogs.com/blogpro/p/11345673.html
總結
以上是生活随笔為你收集整理的delphi uniDac的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 很邪门的事,你知道多少?
- 下一篇: 独立t检验和配对t检验_配对学生的t检验