Firebird strip程序,trggers视图和udf

时间:2016-09-21 08:52:47

标签: firebird firebird1.5 firebird-3.0

我正在准备一个新版本的软件,从Firebird 1.5过渡到3.我的安装程序备份1.5数据库并通过3服务器或嵌入式服务器恢复它,具体取决于安装类型(本地/多用户)。这一切都运作良好。

我想使用新的firebird功能重新创建所有过程触发器和视图,并试图摆脱我在1.5中使用的UDF。因此,我试图删除所有这些东西,但我偶然发现了我无法解决的问题,例如使用FB3中不存在的UDF的视图。由于没有Firebird 3的UDF,我有点卡住了。

删除旧数据库中的这些对象是不可取的,我不想破坏这个后备选项。还有两个备份/恢复轮次是没有选择的,因为我们正在谈论相当大的数据库。

我需要让安装程序完成所有这些操作,因为我无法访问客户系统。

非常感谢任何帮助。谢谢。

1 个答案:

答案 0 :(得分:1)

感谢Mark,我再次尝试并最终以某种方式将所有视图改为“从rdb $ database中选择1作为测试”,然后将其删除。

由于我在该字段中有许多不同版本的模式,因此我并不完全确定哪些依赖项将会出现。所以我编写了这个PSQL Block,它遍历所有这些对象,忽略了错误,直到清理完所有内容。因此,如果这些对象中的任何一个不可删除,一旦它运行了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