2016-09-28 29 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