翻譯|使用教程|編輯:李爽夏|2019-01-31 09:59:27.000|閱讀 461 次
概述:本篇文章介紹使用UniDAC中的數據類型映射。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
Universal Data Access Components (UniDAC)是一款通用數據庫訪問組件,提供了多個數據庫的直接訪問,如針對Windows的Delphi, C++Builder, Lazarus (以及 Free Pascal) , Mac OS X, iOS, Android, Linux和64和32位的FreeBSD等等。我們將長期的經驗集于這個小組件,提供統一的數據庫連接訪問(如oracle、微軟SQL等等)。這意味著您可以在您的項目之間輕松地切換不同的數據庫,以及創建跨數據庫應用程序接口。
Data Type Mapping(數據類型映射)是一種靈活且易于定制的工具,它允許在DB類型和Delphi字段類型之間進行映射。
在本文中,有幾個示例,可以在處理所有支持的DBS時使用。為了清楚地顯示數據類型映射設備的通用性,每個示例將使用單獨的數據庫。
在不支持數據類型映射的版本中,UniDAC自動設置DB數據類型和Delphi 字段類型之間的對應關系。在具有數據類型映射的版本中,可以手動設置DB數據類型和Delphi 字段類型之間的對應關系。
下面是PostgreSQL數據庫下表中數字類型的示例:
CREATE TABLE numeric_types ( id integer NOT NULL, value1 numeric(5,2), value2 numeric(10,4), value3 numeric(15,6), CONSTRAINT pk_numeric_types PRIMARY KEY (id) )
應使用數據類型映射,以便:
Delphi中Scale=0的數字字段將映射到以下字段類型之一:TSmallintField、TIntegerField 或TlargeintField,具體取決于精度
為了保存精度,Precision>=10且Scalе<= 4的數字字段將映射到TBCDField。
數值字段Scalе>= 5將映射到TFMTBCDField。
以上表格形式:
要指定Precision <= 4且Scale = 0的數值字段必須映射到ftSmallint,應設置以下規則:
var DBType: Word; MinPrecision: Integer; MaxPrecision: Integer; MinScale: Integer; MaxScale: Integer; FieldType: TfieldType; begin DBType := pgNumeric; MinPrecision := 0; MaxPrecision := 4; MinScale := 0; MaxScale := 0; FieldType := ftSmallint; PgConnection.DataTypeMap.AddDBTypeRule(DBType, MinPrecision, MaxPrecision, MinScale, MaxScale, FieldType); end;
這是詳細規則設置的一個例子,它是為了最大限度地可視化而設計的。通常,規則設置得要短得多,例如如下所示:
// clear existing rules PgConnection.DataTypeMap.Clear; // rule for numeric(4,0) PgConnection.DataTypeMap.AddDBTypeRule(pgNumeric, 0, 4, 0, 0, ftSmallint); // rule for numeric(10,0) PgConnection.DataTypeMap.AddDBTypeRule(pgNumeric, 5, 10, 0, 0, ftInteger); // rule for numeric(15,0) PgConnection.DataTypeMap.AddDBTypeRule(pgNumeric, 11, rlAny, 0, 0, ftLargeint); // rule for numeric(5,2) PgConnection.DataTypeMap.AddDBTypeRule(pgNumeric, 0, 9, 1, rlAny, ftFloat); // rule for numeric(10,4) PgConnection.DataTypeMap.AddDBTypeRule(pgNumeric, 10, rlAny, 1, 4, ftBCD); // rule for numeric(15,6) PgConnection.DataTypeMap.AddDBTypeRule(pgNumeric, 10, rlAny, 5, rlAny, ftFMTBcd);
在設置規則時,可能會出現這樣的情況:為數據庫中的一個類型設置了兩個或多個相互矛盾的規則。在這種情況下,將只應用一個規則-首先設置的規則。
例如,Oracle數據庫中有一個表:
CREATE TABLE NUMBER_TYPES ( ID NUMBER NOT NULL, VALUE1 NUMBER(5,2), VALUE2 NUMBER(10,4), VALUE3 NUMBER(15,6), CONSTRAINT PK_NUMBER_TYPES PRIMARY KEY (id) )
TBCDField應用于NUMBER(10,4),TFMTBCDField - 應用于NUMBER(15,6),而不是默認字段:
如果按以下方式設置規則:
OraSession.DataTypeMap.Clear; OraSession.DataTypeMap.AddDBTypeRule(oraNumber, 0, 9, rlAny, rlAny, ftFloat); OraSession.DataTypeMap.AddDBTypeRule(oraNumber, 0, rlAny, 0, 4, ftBCD); OraSession.DataTypeMap.AddDBTypeRule(oraNumber, 0, rlAny, 0, rlAny, ftFMTBCD);
結果如下:
但是,如果規則是按以下方式設置的:
OraSession.DataTypeMap.Clear; OraSession.DataTypeMap.AddDBTypeRule(oraNumber, 0, rlAny, 0, rlAny, ftFMTBCD); OraSession.DataTypeMap.AddDBTypeRule(oraNumber, 0, rlAny, 0, 4, ftBCD); OraSession.DataTypeMap.AddDBTypeRule(oraNumber, 0, 9, rlAny, rlAny, ftFloat);
結果如下:
這是因為規則
OraSession.DataTypeMap.AddDBTypeRule(oraNumber, 0, rlAny, 0, rlAny, ftFMTBCD);
將應用于精度從0到無窮大,比例也從0到無窮大的數字字段。所有具有任何精度和刻度的數字字段都滿足此條件。
使用數據類型映射時,將為每個類型搜索第一個匹配規則,并將其用于映射。在第二個示例中,第一個集合規則似乎是所有三種類型的第一個匹配規則,因此ftFMTBCD類型將用于Delphi中的所有字段。
如果要返回到第一個示例,NUMBER(5,2)類型的第一個匹配規則是第一個規則,NUMBER(10,4)-第二個規則,NUMBER(15,6)-第三個規則。因此,在第一個例子中,得到了預期的結果。
因此,應該記住,如果設置了數據類型映射規則,以便為數據庫中的一個類型設置兩個或多個相互矛盾的規則,則這些規則將按指定的順序應用。
數據類型映射允許為整個連接以及應用程序中的每個數據集設置規則。
例如,這樣的表是在SQL Server中創建的:
CREATE TABLE person ( id INT NOT NULL , firstname VARCHAR(20) NULL , lastname VARCHAR(30) NULL , gender_code VARCHAR(1) NULL , birth_dttm DATETIME NULL , CONSTRAINT pk_person PRIMARY KEY CLUSTERED (id ASC) ON [PRIMARY] ) GO
眾所周知,birth_dttm字段包含birth day,該字段應該是delphi中的ftDate,而不是ftDateTime。如果設置了此規則:
MSConnection.DataTypeMap.Clear; MSConnection.DataTypeMap.AddDBTypeRule(msDateTime, ftDate);
Delphi中的所有日期時間字段都將具有ftDate類型,這是不正確的。ftDate類型只能在處理person表時用于DATETIME類型。在這種情況下,不應為整個連接設置數據類型映射,而應為特定的數據集設置:
MSQuery.DataTypeMap.Clear; MSQuery.DataTypeMap.AddDBTypeRule(msDateTime, ftDate);
或者相反的情況。例如,DATETIME在應用程序中僅用于日期存儲,并且只有一個表同時存儲日期和時間。在這種情況下,以下規則設置將是正確的:
MSConnection.DataTypeMap.Clear; MSConnection.DataTypeMap.AddDBTypeRule(msDateTime, ftDate); MSQuery.DataTypeMap.Clear; MSQuery.DataTypeMap.AddDBTypeRule(msDateTime, ftDateTime);
在這種情況下,將為ftDate類型的DATETIME類型字段和ftDateTime類型的MSQuery創建所有數據集。
重點是,為數據集設置的規則的優先級高于為整個連接設置的規則的優先級。這允許為整個應用程序靈活方便地設置數據類型映射。不需要為每個數據集設置相同的規則,所有常規規則都可以為整個連接設置一次。如果需要具有單個數據類型映射的數據集,可以為其設置單個規則。
有時需要設置一個規則,不是針對整個連接,也不是針對整個數據集,而是僅針對特定字段。
例如,MySQL 數據庫中有這樣的表:
CREATE TABLE item ( id INT NOT NULL AUTO_INCREMENT, name CHAR(50) NOT NULL, guid CHAR(38), PRIMARY KEY (id) ) ENGINE=MyISAM;
guid字段包含唯一標識符。為了方便工作,此標識符應映射到Delphi中的TGuidField類型。但是有一個問題,如果要設置這樣的規則:
MyQuery.DataTypeMap.Clear; MyQuery.DataTypeMap.AddDBTypeRule(myChar, ftGuid);
然后,name和guid字段都將在delphi中具有ftguid類型,這與計劃的內容不符。在這種情況下,唯一的方法是對特定字段使用數據類型映射:
MyQuery.DataTypeMap.AddFieldNameRule('guid', ftGuid);
此外,必須記住,為特定字段設置規則具有最高優先級。如果要為特定字段設置某些規則,則連接或數據集中的所有其他規則都將被此字段忽略。
數據類型映射允許映射各種類型,有時會出現這樣的問題:存儲在數據庫中的數據無法轉換為數據類型映射規則中指定的Delphi字段類型的正確數據,反之亦然。在這種情況下,將發生一個錯誤,這將通知數據無法映射到指定的類型。
例如:
但在為數據類型映射設置規則時,有可能忽略數據轉換錯誤:
IBCConnection.DataTypeMap.AddDBTypeRule(ibcVarchar, ftInteger, True);
在這種情況下,不可能進行正確的轉換。但是由于忽略了數據轉換錯誤,數據類型映射嘗試返回可以根據轉換方向設置為Delphi字段或DB字段的值。
因此,只有在預期轉換結果時才應使用忽略轉換錯誤。
當使用UniDAC時,經常會出現一種難以解決的情況,即數據庫中的兩個相似類型在Delphi中有不同的類型。為了更清楚地說明,下面有一些例子。
例如,有一個項目,它與兩個DB一起工作:Oracle和SQL Server。在每個數據庫中都創建了這樣的表:
Oracle:
CREATE TABLE ITEM_INFO ( ID NUMBER NOT NULL, CODE VARCHAR2(10) NOT NULL, DESCRIPTION NVARCHAR2(250), CONSTRAINT PK_ITEM_INFO PRIMARY KEY (id) )
SQL Server:
CREATE TABLE item_info ( id INT NOT NULL , code VARCHAR(10) NOT NULL , description NVARCHAR(250) NULL , CONSTRAINT pk_item_info PRIMARY KEY CLUSTERED (id ASC) ON [PRIMARY] ) GO
問題在于,使用啟用的UseUnicode選項處理Oracle時,代碼和描述字段都將具有ftWideString類型,如果禁用了UseUnicode選項,這兩個字段都將具有ftString類型。對于SQL Server,代碼字段始終是ftString,描述字段始終是ftWideString。當試圖創建持久字段時,這個問題尤其嚴重,因為在這種情況下,當與某個提供程序一起工作時,總是會發生錯誤。以前,避免錯誤的唯一方法是在這種情況下拒絕使用持久字段。
目前,這個問題很容易解決。可以為Oracle提供程序設置數據類型映射:
UniConnection.DataTypeMap.Clear; UniConnection.DataTypeMap.AddDBTypeRule(oraVarchar2, ftString); UniConnection.DataTypeMap.AddDBTypeRule(oraNVarchar2, ftWideString);
或者可以為SQL Server設置數據類型映射:
// for useUnicode = True in the Oracle data provider UniConnection.DataTypeMap.Clear; UniConnection.DataTypeMap.AddDBTypeRule(msVarchar, ftWideString);
或者:
// for useUnicode = False in the Oracle data provider UniConnection.DataTypeMap.Clear; UniConnection.DataTypeMap.AddDBTypeRule(msNVarchar, ftString);
購買UniDAC正版授權,請點擊“”喲!
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn