{"id":3540,"date":"2021-04-06T07:35:18","date_gmt":"2021-04-06T07:35:18","guid":{"rendered":"https:\/\/swiv.com.br\/logical-standby-using-triggers-to-replicate-unsupported-tables\/"},"modified":"2026-05-27T20:02:33","modified_gmt":"2026-05-27T19:02:33","slug":"logical-standby-using-triggers-to-replicate-unsupported-tables","status":"publish","type":"post","link":"https:\/\/swiv.com.br\/index.php\/2021\/04\/06\/logical-standby-using-triggers-to-replicate-unsupported-tables\/","title":{"rendered":"Logical Standby: using triggers to replicate Unsupported Tables"},"content":{"rendered":"<p>Este artigo reproduz uma implementa\u00e7\u00e3o muito simples, que \u00e9 dada de exemplo na documenta\u00e7\u00e3o da Oracle, para os casos onde temos tabelas n\u00e3o suportadas nativamente pelo SQL Apply, e que precisam de uma interven\u00e7\u00e3o manual para que seus dados sejam replicados. Essa opera\u00e7\u00e3o consiste basicamente na cria\u00e7\u00e3o de uma tabela paralela, e as triggers que far\u00e3o o trabalho de replica\u00e7\u00e3o em cada evento de DML na tabela de origem. O exemplo foi extra\u00eddo <a rel=\"\\&quot;noreferrer noopener\" noopener=\"\" href=\"http:\/\/www.asktheway.org\/official-documents\/oracle\/E50529_01\/SBYDB\/manage_ls.htm#SBYDB4835\" target=\"\\&quot;_blank\\&quot;\">DESTE<\/a> material oficial.<\/p>\n\n\n<p>Criando um objeto do tipo TYPE no primary e uma tabela que o utiliza em uma de suas colunas:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \\&quot;wp-block-syntaxhighlighter-code\\&quot;\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;oracle@fornix1 ~]$ sqlplus \/ as sysdba\n \nSQL*Plus: Release 19.0.0.0.0 - Production on Sun Apr 4 04:09:42 2021\nVersion 19.3.0.0.0\n \nCopyright (c) 1982, 2019, Oracle.  All rights reserved.\n \n \nConnected to:\nOracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production\nVersion 19.3.0.0.0\n \nSQL&gt; create or replace type SOE.PERSON as object\n(\nFIRSTNAME varchar2(50), LASTNAME varchar2(50), BIRTHDATE Date );\n\/  2    3    4\n \nType created.\n \nSQL&gt; create table SOE.PERSONS\n(\nIDNUMBER varchar2(10) , DEPARTMENT varchar2(50), INFO SOE.PERSON );  2    3\n \nTable created.\n<\/pre><\/div>\n\n\n<p>Criando a &#8220;shadow table&#8221; no primary que ser\u00e1 populada via trigger:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \\&quot;wp-block-syntaxhighlighter-code\\&quot;\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSQL&gt; create table SOE.PERSONS_LOG\n(\nT_IDNUMBER varchar2(10),\nT_DEPARTMENT varchar2(50),\nT_FIRSTNAME varchar2(50),\nT_LASTNAME varchar2(50),\nT_BIRTHDATE Date\n);  2    3    4    5    6    7    8\n \nTable created.\n<\/pre><\/div>\n\n\n<p>Criando a trigger no primary que popular\u00e1 a shadow table:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \\&quot;wp-block-syntaxhighlighter-code\\&quot;\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSQL&gt; CONN SOE\nEnter password:\nConnected.\nSQL&gt; SHOW USER;\nUSER is &quot;SOE&quot;\nSQL&gt; create or replace trigger flatten_persons\n        after insert on persons for each row\ndeclare\nbegin\n        insert into persons_log\n         (t_IdNumber, t_Department, t_FirstName, t_LastName, t_BirthDate)\n        values\n         (:new.IdNumber, :new.Department,\n        :new.Info.FirstName,:new.Info.LastName, :new.Info.BirthDate);\nend;\n\/  2    3    4    5    6    7    8    9   10   11\n \nTrigger created.\n<\/pre><\/div>\n\n\n<p>Criando a trigger no primary que popular\u00e1 a tabela no ambiente standby de destino:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \\&quot;wp-block-syntaxhighlighter-code\\&quot;\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSQL&gt; create or replace trigger reconstruct_persons\n        after insert on persons_log for each row\nbegin\n        insert into Persons (IdNumber, Department, Info)\n        values (:new.t_IdNumber, :new.t_Department,\n        Person(:new.t_FirstName, :new.t_LastName, :new.t_BirthDate));\nend;\n\/  2    3    4    5    6    7    8\n \nTrigger created.\n<\/pre><\/div>\n\n\n<p>Rodando o comando abaixo no primary, deixamos configurado para que a trigger possa ser disparada e alimente o standby:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \\&quot;wp-block-syntaxhighlighter-code\\&quot;\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSQL&gt; exec dbms_ddl.set_trigger_firing_property( trig_owner =&gt; &#039;SOE&#039;, trig_name =&gt; &#039;RECONSTRUCT_PERSONS&#039;, property =&gt; dbms_ddl.apply_server_only, setting =&gt; TRUE);\n \nPL\/SQL procedure successfully completed.\n<\/pre><\/div>\n\n\n<p>Gerando archives no primary:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \\&quot;wp-block-syntaxhighlighter-code\\&quot;\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSQL&gt; CONN \/ AS SYSDBA\nConnected.\nSQL&gt; ALTER SYSTEM SWITCH LOGFILE;\n \nSystem altered.\n \nSQL&gt; \/\n \nSystem altered.\n \nSQL&gt; \/\n \nSystem altered.\n<\/pre><\/div>\n\n\n<p>Confirmando que os objetos foram replicados para o standby database:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \\&quot;wp-block-syntaxhighlighter-code\\&quot;\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;oracle@fornix2 ~]$ sqlplus \/ as sysdba\n \nSQL*Plus: Release 19.0.0.0.0 - Production on Tue Apr 6 04:23:21 2021\nVersion 19.3.0.0.0\n \nCopyright (c) 1982, 2019, Oracle.  All rights reserved.\n \n \nConnected to:\nOracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production\nVersion 19.3.0.0.0\n \nSQL&gt; select count(*) from dba_objects where object_name in (&#039;PERSONS&#039;, &#039;PERSONS_LOG&#039;);\n \n  COUNT(*)\n----------\n         2\n<\/pre><\/div>\n\n\n<p>Para testar a replica\u00e7\u00e3o, vamos inserir 1 registro na tabela do primary:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \\&quot;wp-block-syntaxhighlighter-code\\&quot;\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;oracle@fornix1 ~]$ sqlplus \/ as sysdba\n \nSQL*Plus: Release 19.0.0.0.0 - Production on Tue Apr 6 04:25:38 2021\nVersion 19.3.0.0.0\n \nCopyright (c) 1982, 2019, Oracle.  All rights reserved.\n \n \nConnected to:\nOracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production\nVersion 19.3.0.0.0\n \nSQL&gt; insert into SOE.Persons (IdNumber, Department, Info)\nvalues (1, &#039;Database&#039; ,\nSOE.Person(&#039;Bruno&#039;, &#039;Silva&#039;, trunc(sysdate)));  2    3\n \n1 row created.\n \nSQL&gt; COMMIT;\n \nCommit complete.\n \nSQL&gt; ALTER SYSTEM SWITCH LOGFILE;\n \nSystem altered.\n<\/pre><\/div>\n\n\n<p>No logical standby, a tabela e conte\u00fado j\u00e1 foram replicados com sucesso:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \\&quot;wp-block-syntaxhighlighter-code\\&quot;\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSQL&gt; select count(*) from SOE.persons;\n \n  COUNT(*)\n----------\n         2\n<\/pre><\/div>\n\n\n<p>Obs: Este procedimento foi criado pelo senhor Ahmed Baraka (www.ahmedbaraka.com) e foi apenas reproduzido por mim em um laborat\u00f3rio pessoal para fins de aprendizado.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Este artigo reproduz uma implementa\u00e7\u00e3o muito simples, que \u00e9 dada de exemplo na documenta\u00e7\u00e3o da Oracle, para os casos onde temos tabelas n\u00e3o suportadas nativamente pelo SQL Apply, e que precisam de uma interven\u00e7\u00e3o manual para que seus dados sejam replicados. Essa opera\u00e7\u00e3o consiste basicamente na cria\u00e7\u00e3o de uma tabela paralela, e as triggers que [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-3540","post","type-post","status-publish","format-standard","hentry","category-high-availability"],"_links":{"self":[{"href":"https:\/\/swiv.com.br\/index.php\/wp-json\/wp\/v2\/posts\/3540","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/swiv.com.br\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/swiv.com.br\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/swiv.com.br\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/swiv.com.br\/index.php\/wp-json\/wp\/v2\/comments?post=3540"}],"version-history":[{"count":1,"href":"https:\/\/swiv.com.br\/index.php\/wp-json\/wp\/v2\/posts\/3540\/revisions"}],"predecessor-version":[{"id":9187,"href":"https:\/\/swiv.com.br\/index.php\/wp-json\/wp\/v2\/posts\/3540\/revisions\/9187"}],"wp:attachment":[{"href":"https:\/\/swiv.com.br\/index.php\/wp-json\/wp\/v2\/media?parent=3540"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/swiv.com.br\/index.php\/wp-json\/wp\/v2\/categories?post=3540"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/swiv.com.br\/index.php\/wp-json\/wp\/v2\/tags?post=3540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}