1. 程式人生 > >Firebird 數據庫使用經驗總結

Firebird 數據庫使用經驗總結

不用 oschina HA HR isnull 調用 問題 () denied

轉自:https://www.oschina.net/question/54100_8615

最近在改寫一段ms sql的存儲過程到firebird,總結了一些經驗,firebird可以說是這個世界上最小的支持存儲過程的數據庫,才2.3M 而已。如果做小型的應用,相比ms sql桌面版有70多M(+sp3),mysql也有20-30M,還是更合適一些。

1.自定義函數問題.Access to UDF library "rfunc.dll" is denied by server administrator

花了很長時間,不明白為何,將rfunc.dll拷到udf目錄,bin目錄,windows\system32目錄都不能解決問題,google一下, 網上有同樣的問題,但沒有解決方案,結果我重裝了一下firebird就解決了.

2.存儲過程中變量的定義

ms sql存儲過程中無論在哪都可以定義新的變量,但在firebird中,只能在as 與begin之間進行定義.firebird的變量不能用@符號,我將@全部變成a就好了.

3.存儲過程中變量的使用

  1. select @i=count(*) from table1 //ms sql
  2. select count(*) from table1 into :i//firebird引用變量使用冒號

4.嵌入式sql,

firebird支持select * from table exists (select ...) 或 select * from table in (select ...)

但不支持select * from (select * from ...) a,
我是將這類改寫成視圖解決的

5.case語句

mssql 可使用field= case (),但firebbird僅支持case () as field

6.mssql getdate()變成CURRENT_DATE+CURRENT_TIME

  1. select * from snartleave where dt_starttime<CURRENT_DATE+CURRENT_TIME

  1. select * from snartleave where dt_starttime<CURRENT_DATE||‘ ‘ ||CURRENT_TIME

7.返回數據集的存儲過程寫法(firebird寫法有點麻煩)

  1. CREATE PROCEDURE SPVARTST2 (
  2. VAR_IPTARTNO CHAR(6))
  3. RETURNS (
  4. VAR_ARTNAME CHAR(10))
  5. AS
  6. begin
  7. for select v_name1 from snart where v_artNo=:var_iptartno into :var_artname do
  8. suspend;
  9. end

8.自動增長字段的使用(autoincrement)

firebird有個發生器(generator)的東東,在發生器裏記錄值的增長,
再用觸發器實現

  1. begin
  2. if (new.i_seqno is null) then
  3. begin
  4. NEW.i_seqno = GEN_ID(GEN_T_DB_ARTSEQNO_ID,1);
  5. end
  6. end

GEN_T_DB_ARTSEQNO_ID就是創建的發生器,看到沒有,也就是說不同的表不同的字段可以共用一個發生器,gen_id相當於 identity,看起來比mssql復雜,其實也很簡單。

9.發生器重置mssql裏自動增加的字段要重置好像很麻煩,較難控制,

firebird可以這樣(存儲過程中)

  1. agenerator=Gen_ID(GEN_T_DB_ARTSEQNO_ID,Gen_ID(GEN_T_DB_ARTSEQNO_ID,0)*-1+1);

//agenerator是一個整形變量,好像一定要裝gen_id的值符給一個變量才行,不知道有沒有更好的辦法,不用定義一個多余的變量
可參考如下網址:http://www.fingerbird.de/generatorguide_body.htm

10 通過一個表更改另一個表的數據

  1. mssql:update table1 set cname=b.cname from table1 a inner join table2 as b where a.id=b.id
  2. firebird:update table1 a set cname=(select cname from table 2 b where b where a.id=b.id)

11.如何選擇前幾條記錄

  1. mssql: select top 10 * from table1
  2. firebird:select first 10 * from table1
  3. IB:select * from table rows 10

12.Firebird存存儲過程中的事務

在存儲過程 ib/fb 不支持開事務或者結束事務。提交是由調用者提交的。也就是,fb/ib存儲過程應該設計在一個事務裏。
在sql server裏,存儲過程或以開這樣的事務:

  1. begin trancstion
  2. commit trancstion

但在fb/ib裏沒有這樣的事務 ,需要在調的程序中開事務,如:

  1. pFIBDtbsMain.StartTransaction;
  2. pFIBDtbsMain.Commit;

在Firebird裏如何防止空值擴散

出自:http://dev.csdn.net/article/72/72836.shtm
在統計、計算、合並數據時,空值擴散問題,有時不經意冒出來,一不小心,就會導致結果出錯。
我舉個例子。
有一個成績表achieve,有四個字段:yuwen、shuxue、yingyu、total, 分別用來存儲語文、數學、英語及總分。現在要計算學生的總分,現寫出如下SQL語句:

  1. update achieve set total=yuwen+shuxue+yingyu

這句語句好像是沒錯的,但有時得不出有用的結果,比如,有個學生語文80,數學90,英語缺考,沒填成績,這時yingyu字 段的值很可能不是0而是 NULL,空值,要看設計的人是什 麽想法。如果yingyu的值為NULL, 那麽,大家猜猜,計算出來,總分字段total為多少?
按一般的想法,當然是80+90,這個學生的總分是170,英語字段不參加計算。但是,這是錯誤的!
實際計算出來,這個學生的總分為空(NULL)。
在一個SQL計算表達式裏,如果有一個值為空,那麽結果就一定為空!這就是空值擴散!!!
那麽,如何防止出現空值擴散的情況呢?
在這方面,SQL Server提供了ISNULL()函數,Access提供了NZ()函 數,都可以解決這個問題,這些函數就是提供一個判斷功能:如果為空,則用某個值代替,比如用0或用空字符串等。Firebird有類似函數麽?
有,那就是函數coalesce()。
只要將以上的SQL語句改為如下即可。

  1. update achieve set total=coalesce(yuwen,0)+coalesce(shuxue,0)+coalesce(yingyu,0)

這樣寫,似乎麻煩了一些,但是,它是一個安全的代碼。

Firebird 數據庫使用經驗總結