2016-09-28 62 views
2

我想添加一些触发器到我的PostgreSQL(v 9)数据库,我想创建一个Rails迁移(使用v 4.2.7)来满足这个目标。所以,我创建了一个迁移与此内容如何在Rails迁移中创建触发器?

class CreateDeleteAddressTriggers < ActiveRecord::Migration 
    def change 
    execute <<-SQL 
     CREATE OR REPLACE FUNCTION remove_address() RETURNS trigger 
     LANGUAGE plpgsql AS 
     $$BEGIN 
      DELETE FROM public.addresses WHERE id = OLD.address_id; 
     END;$$; 

     CREATE TRIGGER remove_my_object_address 
     AFTER DELETE ON public.my_objects FOR EACH ROW 
     EXECUTE TRIGGER remove_address() 

     CREATE TRIGGER remove_user_address 
     AFTER DELETE ON public.users FOR EACH ROW 
     EXECUTE TRIGGER remove_address() 
    SQL 
    end 
end 

不幸的是,当我运行“耙分贝:迁移”的任务,我得到以下错误

davea$ rake db:migrate 
== 20160928184431 CreateDeleteAddressTriggers: migrating ====================== 
-- execute("  CREATE OR REPLACE FUNCTION remove_address() RETURNS trigger\n  LANGUAGE plpgsql AS\n  $$BEGIN\n   DELETE FROM public.addresses WHERE id = OLD.address_id;\n  END;$$;\n\n  CREATE TRIGGER remove_my_object_address\n  AFTER DELETE ON public.my_objects FOR EACH ROW\n  EXECUTE TRIGGER remove_address()\n\n  CREATE TRIGGER remove_user_address\n  AFTER DELETE ON public.users FOR EACH ROW\n  EXECUTE TRIGGER remove_address()\n") 
rake aborted! 
StandardError: An error has occurred, this and all later migrations canceled: 

PG::SyntaxError: ERROR: syntax error at or near "TRIGGER" 
LINE 9:   EXECUTE TRIGGER remove_address() 
         ^
:  CREATE OR REPLACE FUNCTION remove_address() RETURNS trigger 
     LANGUAGE plpgsql AS 
     $$BEGIN 
      DELETE FROM public.addresses WHERE id = OLD.address_id; 
     END;$$; 

     CREATE TRIGGER remove_my_object_address 
     AFTER DELETE ON public.my_objects FOR EACH ROW 
     EXECUTE TRIGGER remove_address() 

     CREATE TRIGGER remove_user_address 
     AFTER DELETE ON public.users FOR EACH ROW 
     EXECUTE TRIGGER remove_address() 
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `async_exec' 
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `block in execute' 
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract_adapter.rb:484:in `block in log' 
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.7.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument' 
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract_adapter.rb:478:in `log' 
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:154:in `execute' 
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/migration.rb:665:in `block in method_missing' 
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/migration.rb:634:in `block in say_with_time' 

我怎样才能更正我的移民才能运行触发器是否正确?

编辑:针对给出的答案,这是你使用了错误的语法在SQL生成的错误...

ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: syntax error at or near "CREATE" 
LINE 11:  CREATE TRIGGER remove_user_address 

回答

5

。您需要EXECUTE PROCEDURE,而不是EXECUTE TRIGGER

你应该有

CREATE TRIGGER remove_my_object_address 
    AFTER DELETE ON public.my_objects FOR EACH ROW 
    EXECUTE PROCEDURE remove_address() 
      ^^^^^^^^^ 

CREATE TRIGGER remove_user_address 
    AFTER DELETE ON public.users FOR EACH ROW 
    EXECUTE PROCEDURE remove_address() 
      ^^^^^^^^^ 

来源:The PostgreSQL docs

+0

我用“EXECUTE PROCEDURE”替换了“EXECUTE T​​RIGGER”,但在运行我的迁移时遇到了此错误,“PG :: SyntaxError:ERROR:语法错误处于或接近”CREATE“,第11行:CREATE TRIGGER remove_user_address” – Dave

+0

@Dave每个语句后都需要分号。 – meagar

+0

@meagar这种处理函数和触发器迁移的方式不会在测试env迁移中执行代码。有什么建议么? – carbonr