2016-09-21 22 views
1

我正在準備從Firebird 1.5過渡到3的我的軟件的新版本。我的安裝程序備份1.5數據庫,並通過3服務器或嵌入式服務器進行恢復,具體取決於安裝類型(本地/多用戶)。這一切運作良好。Firebird strip procedures,trggers views and udf

我想使用新的firebird功能重新創建所有過程觸發器和視圖,並嘗試擺脫我在1.5中使用的UDF。因此,我試圖刪除所有的東西,但我偶然發現了我不能掉落的問題一個使用FB3中不存在的UDF的視圖。由於UDF不適用於Firebird 3,所以我被卡住了。

在舊數據庫中刪除這些對象是沒有選擇的a我不想銷燬這個後備選項。同樣做兩個備份/恢復輪是不行的,因爲我們正在討論相當大的數據庫。

我需要讓安裝程序做所有這些,因爲我無法訪問客戶系統。

任何幫助非常感謝。謝謝。

+0

您是否嘗試過使用['創建或更改VIEW'(http://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en /html/fblangref25-ddl-view.html#fblangref25-ddl-view-crtoralter)?或者,您可以使用Firebird 3下的這些UDF進行遷移。 –

+0

對使用​​這些udfs的視圖執行任何刪除或修改命令會失敗,並顯示無效的blr。不幸的是,如上所述,udfs不適用於FB3。我很想替換它們,但因爲它們被使用,所以沒有用。 – MichaSchumann

+0

據我所知,你應該可以使用Firebird 1.5中使用的現有UDF。 –

回答

1

感謝馬克,我再次嘗試,並最終以某種方式改變了所有視圖「選擇1作爲測試從rdb $數據庫」工作,然後可以刪除它們。

由於我在現場有很多不同版本的模式,我不確定我會遇到哪些依賴關係。所以我寫了這個PSQL塊,它遍歷所有這些對象,忽略錯誤,直到一切都清理完畢。因此,如果這些對象中的任何一個都不可刪除​​,那麼一旦它運行了100次以避免掛起,我就會跳出迭代。之後,我檢查是否存在任何程序,視圖,觸發器和功能。如果是這樣,我招來一個例外。

我知道這是一種「骯髒」的解決方案(忽略異常通常是NoGo),但我沒有更好的主意,因爲無論是循環還是未檢測到的錯誤都不會發生,我會用這種方式。

EXECUTE BLOCK 
as 
declare x integer; 
declare y integer; 
declare z integer; 
declare s varchar(100); 
declare s1 varchar(100); 
begin 
    x=1; 
    y=0; 
    while (x>0 and y<100) do 
    -- we break out of the loop if we have more than 100 rounds as this indicates 
    -- at least one object could not be deleted. 
     begin 
     y=y+1; 
     for SELECT distinct RDB$VIEW_NAME from RDB$VIEW_RELATIONS into :s do 
      begin 
      in autonomous transaction do 
      execute statement 'alter view ' || s || ' as select 1 as test from rdb$database'; 
      -- Ignore errors here for now 
      in autonomous transaction do 
      execute statement 'drop view ' || s; 
      -- Ignore errors here for now 
      when any do begin end 
      end 
     for SELECT RDB$PROCEDURE_NAME from RDB$PROCEDURES into :s do 
      begin 
      in autonomous transaction do 
      execute statement 'drop procedure ' || s; 
      -- Ignore errors here for now 
      when any do begin end 
      end 

     for select RDB$TRIGGER_NAME from RDB$TRIGGERS where RDB$SYSTEM_FLAG=0 into :s do 
      begin 
      in autonomous transaction do 
      execute statement 'drop trigger ' || s; 
      -- Ignore errors here for now 
      when any do begin end 
      end 
     for select RDB$FUNCTION_NAME from RDB$FUNCTIONS into :s do 
      begin 
      in autonomous transaction do 
      execute statement 'drop function ' || s; 
       -- Ignore errors here for now 
      when any do begin end 
      end 
     for select rdb$constraint_name,rdb$relation_name from RDB$RELATION_CONSTRAINTS where not rdb$relation_name containing ('$') into :s,:s1 do 
      begin 
      in autonomous transaction do 
      execute statement 'alter table ' || s1 || ' drop constraint ' || s; 
       -- Ignore errors here for now 
      when any do begin end 
      end 
     for select rdb$index_name from rdb$indices where rdb$system_flag=0 into :s do 
      begin 
      in autonomous transaction do 
      execute statement 'drop index ' || s; 
       -- Ignore errors here for now 
      when any do begin end 
      end 
     x = 0; 
     SELECT count(*) from RDB$PROCEDURES into :z; 
     x = x + z; 
     SELECT count(distinct RDB$VIEW_NAME) from RDB$VIEW_RELATIONS into :z; 
     x = x + z; 
     select count(*) from RDB$TRIGGERS where RDB$SYSTEM_FLAG=0 into :z; 
     x = x + z; 
     select count(*) from RDB$FUNCTIONS into :z; 
     x = x + z; 
     select count(*) from RDB$RELATION_CONSTRAINTS where not rdb$relation_name containing ('$') into :z; 
     x = x + z; 
     select count(*) from rdb$indices where rdb$system_flag=0 into :z; 
     x = x + z; 
    end 
    if (x>0) then 
      -- Raise an exception showing that the block failed 
      y=x/0; 
end 

更新:我添加了代碼以刪除所有約束和索引。

更新2:保留「非空」約束可能是個好主意,因爲它們只能通過域進行重新調整。這樣做只是改變約束select語句:

for select rdb$constraint_name,rdb$relation_name from RDB$RELATION_CONSTRAINTS 
      where rdb$constraint_type<>'NOT NULL' and not rdb$relation_name containing ('$') into :s,:s1 do