Files
doc-exports/docs/dws/dev/dws_04_0106.html
luhuayi 177cd61a57 DWS DEVG 910.211 version
Reviewed-by: Pruthi, Vineet <vineet.pruthi@t-systems.com>
Co-authored-by: luhuayi <luhuayi@huawei.com>
Co-committed-by: luhuayi <luhuayi@huawei.com>
2025-05-05 07:44:03 +00:00

114 lines
22 KiB
HTML

<a name="EN-US_TOPIC_0000002100746058"></a><a name="EN-US_TOPIC_0000002100746058"></a>
<h1 class="topictitle1">GaussDB(DWS) Stored Procedure Development Specifications</h1>
<div id="body8662426"><div class="section" id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_section15429113495012"><h4 class="sectiontitle">Suggestion 5.1: Simplifying Stored Procedures and Avoiding Nesting</h4><div class="note" id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_note0606173014610"><img src="public_sys-resources/note_3.0-en-us.png"><span class="notetitle"> </span><div class="notebody"><p id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_p1418881295812"><strong id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_b135897240010742">Impact of rule violation:</strong></p>
<ul id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_ul1011962534414"><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li14119425184419">The maintenance cost for complex and nested stored procedures is high, making fault locating and recovery time-consuming.</li></ul>
<p id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_p10188141245817"><strong id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_b1245925773112631">Solution:</strong></p>
<ul id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_ul1173125635215"><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li77841258105210">Avoid using stored procedures altogether or limit their usage to a single layer. Nested stored procedures should be avoided.</li><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li138341507506">Create a corresponding log table for the stored procedure design and record information before and after key steps in the log table. Follow the steps below to implement this.</li></ul>
</div></div>
<p id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_p5714543516">Saving and viewing logs</p>
<ol id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_ol1913319268461"><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li12133112611469"><span>Create a log table.</span><p><div class="codecoloring" codetype="Sql" id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_screen892065517472"><div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">CREATE</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="n">func_exec_log</span>
<span class="p">(</span>
<span class="n">id</span><span class="w"> </span><span class="n">varchar2</span><span class="p">(</span><span class="mi">32</span><span class="p">)</span><span class="w"> </span><span class="k">default</span><span class="w"> </span><span class="k">lower</span><span class="p">(</span><span class="n">sys_guid</span><span class="p">()),</span>
<span class="n">pro_name</span><span class="w"> </span><span class="n">varchar2</span><span class="p">(</span><span class="mi">60</span><span class="p">),</span>
<span class="n">exec_times</span><span class="w"> </span><span class="nb">int</span><span class="p">,</span>
<span class="n">log_date</span><span class="w"> </span><span class="nb">date</span><span class="p">,</span>
<span class="n">deal_date</span><span class="w"> </span><span class="nb">date</span><span class="p">,</span>
<span class="n">log_mesage</span><span class="w"> </span><span class="nb">text</span>
<span class="p">);</span>
</pre></div></td></tr></table></div>
</div>
</p></li><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li1213332654613"><span>Create a table and import data.</span><p><div class="codecoloring" codetype="Sql" id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_screen3916142116483"><div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">CREATE</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="n">demo_table</span><span class="p">(</span><span class="n">data_id</span><span class="w"> </span><span class="nb">int</span><span class="p">,</span><span class="w"> </span><span class="n">data_number</span><span class="w"> </span><span class="nb">int</span><span class="p">);</span>
<span class="k">INSERT</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="n">demo_table</span><span class="w"> </span><span class="k">values</span><span class="p">(</span><span class="n">generate_series</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1000</span><span class="p">),</span><span class="n">generate_series</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1000</span><span class="p">));</span>
</pre></div></td></tr></table></div>
</div>
</p></li><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li17134142674610"><span>Create a service stored procedure.</span><p><div class="codecoloring" codetype="Sql" id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_screen198783311486"><div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">CREATE</span><span class="w"> </span><span class="k">OR</span><span class="w"> </span><span class="k">REPLACE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">demo_table_process</span><span class="p">(</span><span class="k">out</span><span class="w"> </span><span class="n">exe_info</span><span class="w"> </span><span class="nb">text</span><span class="p">)</span>
<span class="k">LANGUAGE</span><span class="w"> </span><span class="n">plpgsql</span>
<span class="k">AS</span><span class="w"> </span><span class="err">$$</span>
<span class="k">declare</span><span class="w"> </span><span class="n">v_count</span><span class="w"> </span><span class="nb">int</span><span class="p">;</span>
<span class="n">pro_result</span><span class="w"> </span><span class="nb">text</span><span class="p">;</span>
<span class="n">fun_name</span><span class="w"> </span><span class="nb">text</span><span class="p">;</span>
<span class="n">exec_times</span><span class="w"> </span><span class="nb">int</span><span class="p">;</span>
<span class="k">begin</span>
<span class="n">fun_name</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="s1">'demo_table_process'</span><span class="p">;</span>
<span class="k">select</span><span class="w"> </span><span class="n">nvl</span><span class="p">(</span><span class="k">max</span><span class="p">(</span><span class="n">exec_times</span><span class="p">),</span><span class="w"> </span><span class="s1">'0'</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k">into</span><span class="w"> </span><span class="n">exec_times</span><span class="w"> </span><span class="k">from</span><span class="w"> </span><span class="n">func_exec_log</span><span class="w"> </span><span class="k">where</span><span class="w"> </span><span class="n">pro_name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fun_name</span><span class="p">;</span>
<span class="c1">-- Insert data into the service table.</span>
<span class="k">insert</span><span class="w"> </span><span class="k">into</span><span class="w"> </span><span class="n">demo_table</span><span class="w"> </span><span class="k">values</span><span class="w"> </span><span class="p">(</span><span class="n">dbms_random</span><span class="p">.</span><span class="n">value</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1000</span><span class="p">)::</span><span class="nb">int</span><span class="p">,</span><span class="n">generate_series</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">dbms_random</span><span class="p">.</span><span class="n">value</span><span class="p">(</span><span class="mi">10000</span><span class="p">,</span><span class="w"> </span><span class="mi">20000</span><span class="p">)::</span><span class="nb">int</span><span class="p">));</span>
<span class="k">get</span><span class="w"> </span><span class="k">diagnostics</span><span class="w"> </span><span class="n">v_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">ROW_COUNT</span><span class="p">;</span>
<span class="n">exe_info</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sysdate</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="s1">'# step1:insert count:'</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">v_count</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="s1">' rows;'</span><span class="p">;</span>
<span class="c1">-- Delete specified data from a service table.</span>
<span class="k">delete</span><span class="w"> </span><span class="k">from</span><span class="w"> </span><span class="n">demo_table</span><span class="w"> </span><span class="k">where</span><span class="w"> </span><span class="n">data_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dbms_random</span><span class="p">.</span><span class="n">value</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1000</span><span class="p">)::</span><span class="nb">int</span><span class="p">;</span>
<span class="k">get</span><span class="w"> </span><span class="k">diagnostics</span><span class="w"> </span><span class="n">v_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">ROW_COUNT</span><span class="p">;</span>
<span class="n">exe_info</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">exe_info</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">sysdate</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="s1">'# step2:delete count:'</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">v_count</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="s1">' rows;'</span><span class="p">;</span>
<span class="c1">-- Update service table data.</span>
<span class="k">update</span><span class="w"> </span><span class="n">demo_table</span><span class="w"> </span><span class="k">set</span><span class="w"> </span><span class="n">data_number</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dbms_random</span><span class="p">.</span><span class="n">value</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">100</span><span class="p">)::</span><span class="nb">int</span><span class="w"> </span><span class="k">where</span><span class="w"> </span><span class="n">data_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dbms_random</span><span class="p">.</span><span class="n">value</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1000</span><span class="p">)::</span><span class="nb">int</span><span class="p">;</span>
<span class="n">exe_info</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">exe_info</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">sysdate</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="s1">'# step3:update count:'</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">sql</span><span class="o">%</span><span class="n">rowcount</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="s1">' rows'</span><span class="p">;</span>
<span class="c1">-- Record logs either before the entire program ends or after each step completes. You can also create a function specifically for logging purposes.</span>
<span class="k">insert</span><span class="w"> </span><span class="k">into</span><span class="w"> </span><span class="n">func_exec_log</span><span class="p">(</span><span class="n">pro_name</span><span class="p">,</span><span class="w"> </span><span class="n">exec_times</span><span class="p">,</span><span class="w"> </span><span class="n">log_date</span><span class="p">,</span><span class="w"> </span><span class="n">deal_date</span><span class="p">,</span><span class="w"> </span><span class="n">log_mesage</span><span class="p">)</span><span class="w"> </span><span class="k">values</span><span class="w"> </span><span class="p">(</span><span class="n">fun_name</span><span class="p">,</span><span class="n">exec_times</span><span class="p">,</span><span class="n">sysdate</span><span class="p">,</span><span class="n">split_part</span><span class="p">(</span><span class="n">regexp_split_to_table</span><span class="p">(</span><span class="n">exe_info</span><span class="p">,</span><span class="w"> </span><span class="s1">';'</span><span class="p">),</span><span class="w"> </span><span class="s1">'#'</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">),</span><span class="n">split_part</span><span class="p">(</span><span class="n">regexp_split_to_table</span><span class="p">(</span><span class="n">exe_info</span><span class="p">,</span><span class="w"> </span><span class="s1">';'</span><span class="p">),</span><span class="w"> </span><span class="s1">'#'</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">));</span>
<span class="c1">-- EXCEPTION is used to ensure that logs can be properly recorded when the insertion, update, or deletion exits abnormally.</span>
<span class="k">EXCEPTION</span>
<span class="k">WHEN</span><span class="w"> </span><span class="n">OTHERS</span><span class="w"> </span><span class="k">THEN</span>
<span class="n">pro_result</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="n">exe_info</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">sysdate</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="s1">'# exception error message is: '</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">sqlerrm</span><span class="p">;</span>
<span class="k">insert</span><span class="w"> </span><span class="k">into</span><span class="w"> </span><span class="n">func_exec_log</span><span class="p">(</span><span class="n">pro_name</span><span class="p">,</span><span class="w"> </span><span class="n">exec_times</span><span class="p">,</span><span class="w"> </span><span class="n">log_date</span><span class="p">,</span><span class="w"> </span><span class="n">deal_date</span><span class="p">,</span><span class="w"> </span><span class="n">log_mesage</span><span class="p">)</span><span class="w"> </span><span class="k">values</span><span class="p">(</span><span class="n">fun_name</span><span class="p">,</span><span class="n">exec_times</span><span class="p">,</span><span class="n">sysdate</span><span class="p">,</span><span class="n">split_part</span><span class="p">(</span><span class="n">regexp_split_to_table</span><span class="p">(</span><span class="n">pro_result</span><span class="p">,</span><span class="w"> </span><span class="s1">';'</span><span class="p">),</span><span class="w"> </span><span class="s1">'#'</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">),</span><span class="n">split_part</span><span class="p">(</span><span class="n">regexp_split_to_table</span><span class="p">(</span><span class="n">pro_result</span><span class="p">,</span><span class="w"> </span><span class="s1">';'</span><span class="p">),</span><span class="w"> </span><span class="s1">'#'</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">));</span>
<span class="k">END</span><span class="p">;</span><span class="w"> </span><span class="err">$$</span><span class="p">;</span>
</pre></div></td></tr></table></div>
</div>
</p></li><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li613512615464"><span>Invoke the stored procedure (normal execution).</span><p><div class="codecoloring" codetype="Sql" id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_screen12534175114481"><div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">SELECT</span><span class="w"> </span><span class="n">demo_table_process</span><span class="p">();</span>
</pre></div></td></tr></table></div>
</div>
</p></li><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li11135122664614"><span>View the created log table to check the service running status.</span><p><pre class="screen" id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_screen71231484492">SELECT * FROM func_exec_log ORDER BY log_date desc,deal_date,log_mesage;</pre>
<p id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_p959652111478"><span><img id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_image19271133142515" src="figure/en-us_image_0000002100390820.png"></span></p>
</p></li><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li3179824184712"><span>Invoke the stored procedure again to construct an execution exception.</span><p><pre class="screen" id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_screen1261413134912">SELECT demo_table_process(); -- Delete the data_number column of demo_table to construct an exception, and then call the stored procedure again.</pre>
</p></li><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li16135152664615"><span>View the log to check the service running status.</span></li></ol>
</div>
<div class="section" id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_section188550284514"><h4 class="sectiontitle">Rule 5.2: Avoiding Non-CREATE DDL Operations in Stored Procedures</h4><div class="note" id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_note46407169234"><img src="public_sys-resources/note_3.0-en-us.png"><span class="notetitle"> </span><div class="notebody"><p id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_p2196227125910"><strong id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_b148914624210742">Impact of rule violation:</strong></p>
<ul id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_ul41966274598"><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li171961427175917">A stored procedure is a large transaction. If a non-CREATE DDL operation, especially one with a high lock level, is executed, it can block external access to related tables during the stored procedure's execution window.</li></ul>
<p id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_p16196182713591"><strong id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_b50590457112631">Solution:</strong></p>
<ul id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_ul13196527115918"><li id="EN-US_TOPIC_0000002100746058__en-us_topic_0000002098487000_li1196827125914">Avoid using non-CREATE DDL operations within stored procedures whenever possible. If there is a necessity to use such operations, carefully assess the duration of the stored procedures and the potential impact of the DDL operations. It is advised to schedule non-CREATE DDL operations during off-peak hours when external access services are less active.</li></ul>
</div></div>
</div>
</div>
<div>
<div class="familylinks">
<div class="parentlink"><strong>Parent topic:</strong> <a href="dws_04_0074.html">GaussDB(DWS) Development Design Proposal</a></div>
</div>
</div>