589 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			589 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html>
 | |
| <html><head>
 | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 | |
| <link href="sqlite.css" rel="stylesheet">
 | |
| <title>CREATE TRIGGER</title>
 | |
| <!-- path= -->
 | |
| </head>
 | |
| <body>
 | |
| <div class=nosearch>
 | |
| <a href="index.html">
 | |
| <img class="logo" src="images/sqlite370_banner.gif" alt="SQLite" border="0">
 | |
| </a>
 | |
| <div><!-- IE hack to prevent disappearing logo --></div>
 | |
| <div class="tagline desktoponly">
 | |
| Small. Fast. Reliable.<br>Choose any three.
 | |
| </div>
 | |
| <div class="menu mainmenu">
 | |
| <ul>
 | |
| <li><a href="index.html">Home</a>
 | |
| <li class='mobileonly'><a href="javascript:void(0)" onclick='toggle_div("submenu")'>Menu</a>
 | |
| <li class='wideonly'><a href='about.html'>About</a>
 | |
| <li class='desktoponly'><a href="docs.html">Documentation</a>
 | |
| <li class='desktoponly'><a href="download.html">Download</a>
 | |
| <li class='wideonly'><a href='copyright.html'>License</a>
 | |
| <li class='desktoponly'><a href="support.html">Support</a>
 | |
| <li class='desktoponly'><a href="prosupport.html">Purchase</a>
 | |
| <li class='search' id='search_menubutton'>
 | |
| <a href="javascript:void(0)" onclick='toggle_search()'>Search</a>
 | |
| </ul>
 | |
| </div>
 | |
| <div class="menu submenu" id="submenu">
 | |
| <ul>
 | |
| <li><a href='about.html'>About</a>
 | |
| <li><a href='docs.html'>Documentation</a>
 | |
| <li><a href='download.html'>Download</a>
 | |
| <li><a href='support.html'>Support</a>
 | |
| <li><a href='prosupport.html'>Purchase</a>
 | |
| </ul>
 | |
| </div>
 | |
| <div class="searchmenu" id="searchmenu">
 | |
| <form method="GET" action="search">
 | |
| <select name="s" id="searchtype">
 | |
| <option value="d">Search Documentation</option>
 | |
| <option value="c">Search Changelog</option>
 | |
| </select>
 | |
| <input type="text" name="q" id="searchbox" value="">
 | |
| <input type="submit" value="Go">
 | |
| </form>
 | |
| </div>
 | |
| </div>
 | |
| <script>
 | |
| function toggle_div(nm) {
 | |
| var w = document.getElementById(nm);
 | |
| if( w.style.display=="block" ){
 | |
| w.style.display = "none";
 | |
| }else{
 | |
| w.style.display = "block";
 | |
| }
 | |
| }
 | |
| function toggle_search() {
 | |
| var w = document.getElementById("searchmenu");
 | |
| if( w.style.display=="block" ){
 | |
| w.style.display = "none";
 | |
| } else {
 | |
| w.style.display = "block";
 | |
| setTimeout(function(){
 | |
| document.getElementById("searchbox").focus()
 | |
| }, 30);
 | |
| }
 | |
| }
 | |
| function div_off(nm){document.getElementById(nm).style.display="none";}
 | |
| window.onbeforeunload = function(e){div_off("submenu");}
 | |
| /* Disable the Search feature if we are not operating from CGI, since */
 | |
| /* Search is accomplished using CGI and will not work without it. */
 | |
| if( !location.origin || !location.origin.match || !location.origin.match(/http/) ){
 | |
| document.getElementById("search_menubutton").style.display = "none";
 | |
| }
 | |
| /* Used by the Hide/Show button beside syntax diagrams, to toggle the */
 | |
| function hideorshow(btn,obj){
 | |
| var x = document.getElementById(obj);
 | |
| var b = document.getElementById(btn);
 | |
| if( x.style.display!='none' ){
 | |
| x.style.display = 'none';
 | |
| b.innerHTML='show';
 | |
| }else{
 | |
| x.style.display = '';
 | |
| b.innerHTML='hide';
 | |
| }
 | |
| return false;
 | |
| }
 | |
| </script>
 | |
| </div>
 | |
| <div class=fancy>
 | |
| <div class=nosearch>
 | |
| <div class="fancy_title">
 | |
| CREATE TRIGGER
 | |
| </div>
 | |
| <div class="fancy_toc">
 | |
| <a onclick="toggle_toc()">
 | |
| <span class="fancy_toc_mark" id="toc_mk">►</span>
 | |
| Table Of Contents
 | |
| </a>
 | |
| <div id="toc_sub"><div class="fancy-toc1"><a href="#syntax">1. Syntax</a></div>
 | |
| <div class="fancy-toc1"><a href="#description">2. Description</a></div>
 | |
| <div class="fancy-toc2"><a href="#syntax_restrictions_on_update_delete_and_insert_statements_within_triggers">2.1. Syntax Restrictions On UPDATE, DELETE, and INSERT Statements Within
 | |
| Triggers</a></div>
 | |
| <div class="fancy-toc1"><a href="#instead_of_triggers">3. INSTEAD OF triggers</a></div>
 | |
| <div class="fancy-toc1"><a href="#some_example_triggers">4. Some Example Triggers</a></div>
 | |
| <div class="fancy-toc1"><a href="#cautions_on_the_use_of_before_triggers">5. Cautions On The Use Of BEFORE triggers</a></div>
 | |
| <div class="fancy-toc1"><a href="#the_raise_function">6. The RAISE() function</a></div>
 | |
| <div class="fancy-toc1"><a href="#temp_triggers_on_non_temp_tables">7. TEMP Triggers on Non-TEMP Tables</a></div>
 | |
| </div>
 | |
| </div>
 | |
| <script>
 | |
| function toggle_toc(){
 | |
| var sub = document.getElementById("toc_sub")
 | |
| var mk = document.getElementById("toc_mk")
 | |
| if( sub.style.display!="block" ){
 | |
| sub.style.display = "block";
 | |
| mk.innerHTML = "▼";
 | |
| } else {
 | |
| sub.style.display = "none";
 | |
| mk.innerHTML = "►";
 | |
| }
 | |
| }
 | |
| </script>
 | |
| </div>
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| <h1 id="syntax"><span>1. </span>Syntax</h1>
 | |
| 
 | |
| <p><b><a href="syntax/create-trigger-stmt.html">create-trigger-stmt:</a></b>
 | |
| <button id='x1461' onclick='hideorshow("x1461","x1462")'>hide</button></p>
 | |
|  <div id='x1462' class='imgcontainer'>
 | |
|  <img alt="syntax diagram create-trigger-stmt" src="images/syntax/create-trigger-stmt.gif" />
 | |
| <p><b><a href="syntax/delete-stmt.html">delete-stmt:</a></b>
 | |
| <button id='x1463' onclick='hideorshow("x1463","x1464")'>show</button></p>
 | |
|  <div id='x1464' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram delete-stmt" src="images/syntax/delete-stmt.gif" />
 | |
| <p><b><a href="syntax/common-table-expression.html">common-table-expression:</a></b>
 | |
| <button id='x1465' onclick='hideorshow("x1465","x1466")'>show</button></p>
 | |
|  <div id='x1466' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram common-table-expression" src="images/syntax/common-table-expression.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/qualified-table-name.html">qualified-table-name:</a></b>
 | |
| <button id='x1467' onclick='hideorshow("x1467","x1468")'>show</button></p>
 | |
|  <div id='x1468' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram qualified-table-name" src="images/syntax/qualified-table-name.gif" />
 | |
| </div>
 | |
| </div>
 | |
| <p><b><a href="syntax/expr.html">expr:</a></b>
 | |
| <button id='x1469' onclick='hideorshow("x1469","x1470")'>show</button></p>
 | |
|  <div id='x1470' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram expr" src="images/syntax/expr.gif" />
 | |
| <p><b><a href="syntax/filter-clause.html">filter-clause:</a></b>
 | |
| <button id='x1471' onclick='hideorshow("x1471","x1472")'>show</button></p>
 | |
|  <div id='x1472' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram filter-clause" src="images/syntax/filter-clause.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/literal-value.html">literal-value:</a></b>
 | |
| <button id='x1473' onclick='hideorshow("x1473","x1474")'>show</button></p>
 | |
|  <div id='x1474' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram literal-value" src="images/syntax/literal-value.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/over-clause.html">over-clause:</a></b>
 | |
| <button id='x1475' onclick='hideorshow("x1475","x1476")'>show</button></p>
 | |
|  <div id='x1476' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram over-clause" src="images/syntax/over-clause.gif" />
 | |
| <p><b><a href="syntax/frame-spec.html">frame-spec:</a></b>
 | |
| <button id='x1477' onclick='hideorshow("x1477","x1478")'>show</button></p>
 | |
|  <div id='x1478' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram frame-spec" src="images/syntax/frame-spec.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/ordering-term.html">ordering-term:</a></b>
 | |
| <button id='x1479' onclick='hideorshow("x1479","x1480")'>show</button></p>
 | |
|  <div id='x1480' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram ordering-term" src="images/syntax/ordering-term.gif" />
 | |
| </div>
 | |
| </div>
 | |
| <p><b><a href="syntax/raise-function.html">raise-function:</a></b>
 | |
| <button id='x1481' onclick='hideorshow("x1481","x1482")'>show</button></p>
 | |
|  <div id='x1482' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram raise-function" src="images/syntax/raise-function.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/type-name.html">type-name:</a></b>
 | |
| <button id='x1483' onclick='hideorshow("x1483","x1484")'>show</button></p>
 | |
|  <div id='x1484' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram type-name" src="images/syntax/type-name.gif" />
 | |
| <p><b><a href="syntax/signed-number.html">signed-number:</a></b>
 | |
| <button id='x1485' onclick='hideorshow("x1485","x1486")'>show</button></p>
 | |
|  <div id='x1486' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram signed-number" src="images/syntax/signed-number.gif" />
 | |
| </div>
 | |
| </div>
 | |
| </div>
 | |
| <p><b><a href="syntax/insert-stmt.html">insert-stmt:</a></b>
 | |
| <button id='x1487' onclick='hideorshow("x1487","x1488")'>show</button></p>
 | |
|  <div id='x1488' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram insert-stmt" src="images/syntax/insert-stmt.gif" />
 | |
| <p><b><a href="syntax/common-table-expression.html">common-table-expression:</a></b>
 | |
| <button id='x1489' onclick='hideorshow("x1489","x1490")'>show</button></p>
 | |
|  <div id='x1490' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram common-table-expression" src="images/syntax/common-table-expression.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/upsert-clause.html">upsert-clause:</a></b>
 | |
| <button id='x1491' onclick='hideorshow("x1491","x1492")'>show</button></p>
 | |
|  <div id='x1492' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram upsert-clause" src="images/syntax/upsert-clause.gif" />
 | |
| <p><b><a href="syntax/column-name-list.html">column-name-list:</a></b>
 | |
| <button id='x1493' onclick='hideorshow("x1493","x1494")'>show</button></p>
 | |
|  <div id='x1494' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram column-name-list" src="images/syntax/column-name-list.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/indexed-column.html">indexed-column:</a></b>
 | |
| <button id='x1495' onclick='hideorshow("x1495","x1496")'>show</button></p>
 | |
|  <div id='x1496' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram indexed-column" src="images/syntax/indexed-column.gif" />
 | |
| </div>
 | |
| </div>
 | |
| </div>
 | |
| <p><b><a href="syntax/select-stmt.html">select-stmt:</a></b>
 | |
| <button id='x1497' onclick='hideorshow("x1497","x1498")'>show</button></p>
 | |
|  <div id='x1498' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram select-stmt" src="images/syntax/select-stmt.gif" />
 | |
| <p><b><a href="syntax/common-table-expression.html">common-table-expression:</a></b>
 | |
| <button id='x1499' onclick='hideorshow("x1499","x1500")'>show</button></p>
 | |
|  <div id='x1500' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram common-table-expression" src="images/syntax/common-table-expression.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/compound-operator.html">compound-operator:</a></b>
 | |
| <button id='x1501' onclick='hideorshow("x1501","x1502")'>show</button></p>
 | |
|  <div id='x1502' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram compound-operator" src="images/syntax/compound-operator.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/join-clause.html">join-clause:</a></b>
 | |
| <button id='x1503' onclick='hideorshow("x1503","x1504")'>show</button></p>
 | |
|  <div id='x1504' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram join-clause" src="images/syntax/join-clause.gif" />
 | |
| <p><b><a href="syntax/join-constraint.html">join-constraint:</a></b>
 | |
| <button id='x1505' onclick='hideorshow("x1505","x1506")'>show</button></p>
 | |
|  <div id='x1506' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram join-constraint" src="images/syntax/join-constraint.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/join-operator.html">join-operator:</a></b>
 | |
| <button id='x1507' onclick='hideorshow("x1507","x1508")'>show</button></p>
 | |
|  <div id='x1508' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram join-operator" src="images/syntax/join-operator.gif" />
 | |
| </div>
 | |
| </div>
 | |
| <p><b><a href="syntax/ordering-term.html">ordering-term:</a></b>
 | |
| <button id='x1509' onclick='hideorshow("x1509","x1510")'>show</button></p>
 | |
|  <div id='x1510' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram ordering-term" src="images/syntax/ordering-term.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/result-column.html">result-column:</a></b>
 | |
| <button id='x1511' onclick='hideorshow("x1511","x1512")'>show</button></p>
 | |
|  <div id='x1512' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram result-column" src="images/syntax/result-column.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/table-or-subquery.html">table-or-subquery:</a></b>
 | |
| <button id='x1513' onclick='hideorshow("x1513","x1514")'>show</button></p>
 | |
|  <div id='x1514' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram table-or-subquery" src="images/syntax/table-or-subquery.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/window-defn.html">window-defn:</a></b>
 | |
| <button id='x1515' onclick='hideorshow("x1515","x1516")'>show</button></p>
 | |
|  <div id='x1516' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram window-defn" src="images/syntax/window-defn.gif" />
 | |
| <p><b><a href="syntax/frame-spec.html">frame-spec:</a></b>
 | |
| <button id='x1517' onclick='hideorshow("x1517","x1518")'>show</button></p>
 | |
|  <div id='x1518' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram frame-spec" src="images/syntax/frame-spec.gif" />
 | |
| </div>
 | |
| </div>
 | |
| </div>
 | |
| <p><b><a href="syntax/update-stmt.html">update-stmt:</a></b>
 | |
| <button id='x1519' onclick='hideorshow("x1519","x1520")'>show</button></p>
 | |
|  <div id='x1520' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram update-stmt" src="images/syntax/update-stmt.gif" />
 | |
| <p><b><a href="syntax/column-name-list.html">column-name-list:</a></b>
 | |
| <button id='x1521' onclick='hideorshow("x1521","x1522")'>show</button></p>
 | |
|  <div id='x1522' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram column-name-list" src="images/syntax/column-name-list.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/common-table-expression.html">common-table-expression:</a></b>
 | |
| <button id='x1523' onclick='hideorshow("x1523","x1524")'>show</button></p>
 | |
|  <div id='x1524' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram common-table-expression" src="images/syntax/common-table-expression.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/join-clause.html">join-clause:</a></b>
 | |
| <button id='x1525' onclick='hideorshow("x1525","x1526")'>show</button></p>
 | |
|  <div id='x1526' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram join-clause" src="images/syntax/join-clause.gif" />
 | |
| <p><b><a href="syntax/join-constraint.html">join-constraint:</a></b>
 | |
| <button id='x1527' onclick='hideorshow("x1527","x1528")'>show</button></p>
 | |
|  <div id='x1528' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram join-constraint" src="images/syntax/join-constraint.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/join-operator.html">join-operator:</a></b>
 | |
| <button id='x1529' onclick='hideorshow("x1529","x1530")'>show</button></p>
 | |
|  <div id='x1530' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram join-operator" src="images/syntax/join-operator.gif" />
 | |
| </div>
 | |
| </div>
 | |
| <p><b><a href="syntax/qualified-table-name.html">qualified-table-name:</a></b>
 | |
| <button id='x1531' onclick='hideorshow("x1531","x1532")'>show</button></p>
 | |
|  <div id='x1532' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram qualified-table-name" src="images/syntax/qualified-table-name.gif" />
 | |
| </div>
 | |
| <p><b><a href="syntax/table-or-subquery.html">table-or-subquery:</a></b>
 | |
| <button id='x1533' onclick='hideorshow("x1533","x1534")'>show</button></p>
 | |
|  <div id='x1534' style='display:none;' class='imgcontainer'>
 | |
|  <img alt="syntax diagram table-or-subquery" src="images/syntax/table-or-subquery.gif" />
 | |
| </div>
 | |
| </div>
 | |
| </div>
 | |
| 
 | |
| 
 | |
| <h1 id="description"><span>2. </span>Description</h1>
 | |
| <p>The CREATE TRIGGER statement is used to add triggers to the 
 | |
| database schema. Triggers are database operations 
 | |
| that are automatically performed when a specified database event
 | |
| occurs.  </p>
 | |
| 
 | |
| <p>Each trigger must specify that it will fire for one of
 | |
| the following operations: <a href="lang_delete.html">DELETE</a>, <a href="lang_insert.html">INSERT</a>, <a href="lang_update.html">UPDATE</a>.
 | |
| The trigger fires once for each row that is deleted, inserted,
 | |
| or updated.  If the "UPDATE OF <span class='yyterm'>column-name</span>"
 | |
| syntax is used, then the trigger will only fire if
 | |
| <span class='yyterm'>column-name</span> appears on the left-hand side of
 | |
| one of the terms in the SET clause of the <a href="lang_update.html">UPDATE</a> statement.</p>
 | |
| 
 | |
| <p>Due to an historical oversight, columns named in the "UPDATE OF"
 | |
| clause do not actually have to exist in the table being updated.
 | |
| Unrecognized column names are silently ignored.
 | |
| It would be more helpful if SQLite would fail the CREATE TRIGGER
 | |
| statement if any of the names in the "UPDATE OF" clause are not
 | |
| columns in the table.  However, as this problem was discovered
 | |
| many years after SQLite was widely deployed, we have resisted
 | |
| fixing the problem for fear of breaking legacy applications.</p>
 | |
| 
 | |
| <p>At this time SQLite supports only FOR EACH ROW triggers, not FOR EACH
 | |
| STATEMENT triggers. Hence explicitly specifying FOR EACH ROW is optional.
 | |
| FOR EACH ROW implies that the SQL statements specified in the trigger
 | |
| may be executed (depending on the WHEN clause) for each database row being
 | |
| inserted, updated or deleted by the statement causing the trigger to fire.</p>
 | |
| 
 | |
| <p>Both the WHEN clause and the trigger actions may access elements of 
 | |
| the row being inserted, deleted or updated using references of the form 
 | |
| "NEW.<i>column-name</i>" and "OLD.<i>column-name</i>", where
 | |
| <i>column-name</i> is the name of a column from the table that the trigger
 | |
| is associated with. OLD and NEW references may only be used in triggers on
 | |
| events for which they are relevant, as follows:</p>
 | |
| 
 | |
| <table border="0" cellpadding="10">
 | |
| <tr>
 | |
| <td valign="top" align="right" width="120"><i>INSERT</i></td>
 | |
| <td valign="top">NEW references are valid</td>
 | |
| </tr>
 | |
| <tr>
 | |
| <td valign="top" align="right" width="120"><i>UPDATE</i></td>
 | |
| <td valign="top">NEW and OLD references are valid</td>
 | |
| </tr>
 | |
| <tr>
 | |
| <td valign="top" align="right" width="120"><i>DELETE</i></td>
 | |
| <td valign="top">OLD references are valid</td>
 | |
| </tr>
 | |
| </table>
 | |
| 
 | |
| 
 | |
| <p>If a WHEN clause is supplied, the SQL statements specified
 | |
| are only executed if the WHEN clause is true.
 | |
| If no WHEN clause is supplied, the SQL statements
 | |
| are executed every time the trigger fires.</p>
 | |
| 
 | |
| <p>The BEFORE or AFTER keyword determines when the trigger actions
 | |
| will be executed relative to the insertion, modification or removal of the
 | |
| associated row.  BEFORE is the default when neither keyword is present.</p>
 | |
| 
 | |
| <p>An <a href="lang_conflict.html">ON CONFLICT</a> clause may be specified as part of an <a href="lang_update.html">UPDATE</a> or <a href="lang_insert.html">INSERT</a>
 | |
| action within the body of the trigger.
 | |
| However if an <a href="lang_conflict.html">ON CONFLICT</a> clause is specified as part of 
 | |
| the statement causing the trigger to fire, then conflict handling
 | |
| policy of the outer statement is used instead.</p>
 | |
| 
 | |
| <p>Triggers are automatically <a href="lang_droptrigger.html">dropped</a>
 | |
| when the table that they are 
 | |
| associated with (the <i>table-name</i> table) is 
 | |
| <a href="lang_droptable.html">dropped</a>.  However if the trigger actions reference
 | |
| other tables, the trigger is not dropped or modified if those other
 | |
| tables are <a href="lang_droptable.html">dropped</a> or <a href="lang_altertable.html">modified</a>.</p>
 | |
| 
 | |
| <p>Triggers are removed using the <a href="lang_droptrigger.html">DROP TRIGGER</a> statement.</p>
 | |
| 
 | |
| <h2 id="syntax_restrictions_on_update_delete_and_insert_statements_within_triggers"><span>2.1. </span>Syntax Restrictions On UPDATE, DELETE, and INSERT Statements Within
 | |
|     Triggers</h2>
 | |
| 
 | |
| <p>The <a href="lang_update.html">UPDATE</a>, <a href="lang_delete.html">DELETE</a>, and <a href="lang_insert.html">INSERT</a>
 | |
| statements within triggers do not support
 | |
| the full syntax for <a href="lang_update.html">UPDATE</a>, <a href="lang_delete.html">DELETE</a>, and <a href="lang_insert.html">INSERT</a> statements.  The following
 | |
| restrictions apply:</p>
 | |
| 
 | |
| <ul>
 | |
| <li><p>
 | |
|   The name of the table to be modified in an <a href="lang_update.html">UPDATE</a>, <a href="lang_delete.html">DELETE</a>, or <a href="lang_insert.html">INSERT</a>
 | |
|   statement must be an unqualified table name.  In other words, one must
 | |
|   use just "<i>tablename</i>" not "<i>database</i><b>.</b><i>tablename</i>"
 | |
|   when specifying the table. </p></li>
 | |
| 
 | |
| <li><p>
 | |
|  For non-TEMP triggers,
 | |
|   the table to be modified or queried must exist in the
 | |
|   same database as the table or view to which the trigger is attached.
 | |
|   TEMP triggers are not subject to the same-database rule.  A TEMP
 | |
|   trigger is allowed to query or modify any table in any <a href="lang_attach.html">ATTACH</a>-ed database.
 | |
|   </p></li>
 | |
| 
 | |
| <li><p>
 | |
|   The "INSERT INTO <i>table</i> DEFAULT VALUES" form of the <a href="lang_insert.html">INSERT</a> statement
 | |
|   is not supported.
 | |
|   </p></li>
 | |
| 
 | |
| <li><p>
 | |
|   The INDEXED BY and NOT INDEXED clauses are not supported for <a href="lang_update.html">UPDATE</a> and
 | |
|   <a href="lang_delete.html">DELETE</a> statements.
 | |
|   </p></li>
 | |
| 
 | |
| <li><p>
 | |
|   The ORDER BY and LIMIT clauses on <a href="lang_update.html">UPDATE</a> and <a href="lang_delete.html">DELETE</a> statements are not
 | |
|   supported.  ORDER BY and LIMIT are not normally supported for <a href="lang_update.html">UPDATE</a> or
 | |
|   <a href="lang_delete.html">DELETE</a> in any context but can be enabled for top-level statements
 | |
|   using the <a href="compile.html#enable_update_delete_limit">SQLITE_ENABLE_UPDATE_DELETE_LIMIT</a> compile-time option.  However,
 | |
|   that compile-time option only applies to top-level <a href="lang_update.html">UPDATE</a> and <a href="lang_delete.html">DELETE</a>
 | |
|   statements, not <a href="lang_update.html">UPDATE</a> and <a href="lang_delete.html">DELETE</a> statements within triggers.
 | |
|   </p></li>
 | |
| 
 | |
| <li><p>
 | |
|   <a href="syntax/common-table-expression.html">Common table expression</a> are not supported for
 | |
|   statements inside of triggers.
 | |
|   </p></li>
 | |
| </ul>
 | |
| 
 | |
| <a name="instead_of_trigger"></a>
 | |
| 
 | |
| <h1 id="instead_of_triggers"><span>3. </span>INSTEAD OF triggers</h1>
 | |
| 
 | |
| <p>Triggers may be created on <a href="lang_createview.html">views</a>, as well as ordinary tables, by
 | |
| specifying INSTEAD OF in the CREATE TRIGGER statement. 
 | |
| If one or more ON INSERT, ON DELETE
 | |
| or ON UPDATE triggers are defined on a view, then it is not an
 | |
| error to execute an INSERT, DELETE or UPDATE statement on the view, 
 | |
| respectively.  Instead,
 | |
| executing an INSERT, DELETE or UPDATE on the view causes the associated
 | |
| triggers to fire. The real tables underlying the view are not modified
 | |
| (except possibly explicitly, by a trigger program).</p>
 | |
| 
 | |
| <p>Note that the <a href="c3ref/changes.html">sqlite3_changes()</a> and <a href="c3ref/total_changes.html">sqlite3_total_changes()</a> interfaces
 | |
| do not count INSTEAD OF trigger firings, but the
 | |
| <a href="pragma.html#pragma_count_changes">count_changes pragma</a> does count INSTEAD OF trigger firing.</p>
 | |
| 
 | |
| <h1 id="some_example_triggers"><span>4. </span>Some Example Triggers</h1>
 | |
| 
 | |
| <p>Assuming that customer records are stored in the "customers" table, and
 | |
| that order records are stored in the "orders" table, the following
 | |
| UPDATE trigger
 | |
| ensures that all associated orders are redirected when a customer changes
 | |
| his or her address:</p>
 | |
| 
 | |
| <blockquote><pre>
 | |
| CREATE TRIGGER update_customer_address UPDATE OF address ON customers 
 | |
|   BEGIN
 | |
|     UPDATE orders SET address = new.address WHERE customer_name = old.name;
 | |
|   END;
 | |
| </pre></blockquote>
 | |
| 
 | |
| <p>With this trigger installed, executing the statement:</p>
 | |
| 
 | |
| <blockquote><pre>
 | |
| UPDATE customers SET address = '1 Main St.' WHERE name = 'Jack Jones';
 | |
| </pre></blockquote>
 | |
| 
 | |
| <p>causes the following to be automatically executed:</p>
 | |
| 
 | |
| <blockquote><pre>
 | |
| UPDATE orders SET address = '1 Main St.' WHERE customer_name = 'Jack Jones';
 | |
| </pre></blockquote>
 | |
| 
 | |
| <p>For an example of an INSTEAD OF trigger, consider the following schema:
 | |
| 
 | |
| <blockquote><pre>
 | |
| CREATE TABLE customer(
 | |
|   cust_id INTEGER PRIMARY KEY,
 | |
|   cust_name TEXT,
 | |
|   cust_addr TEXT
 | |
| );
 | |
| CREATE VIEW customer_address AS
 | |
|    SELECT cust_id, cust_addr FROM customer;
 | |
| CREATE TRIGGER cust_addr_chng
 | |
| INSTEAD OF UPDATE OF cust_addr ON customer_address
 | |
| BEGIN
 | |
|   UPDATE customer SET cust_addr=NEW.cust_addr
 | |
|    WHERE cust_id=NEW.cust_id;
 | |
| END;
 | |
| </pre></blockquote>
 | |
| 
 | |
| </p><p>With the schema above, a statement of the form:</p>
 | |
| 
 | |
| <blockquote><pre>
 | |
| UPDATE customer_address SET cust_addr=$new_address WHERE cust_id=$cust_id;
 | |
| </pre></blockquote>
 | |
| 
 | |
| <p>Causes the customer.cust_addr field to be updated for a specific
 | |
| customer entry that has customer.cust_id equal to the $cust_id parameter.
 | |
| Note how the values assigned to the view are made available as field
 | |
| in the special "NEW" table within the trigger body.</p>
 | |
| 
 | |
| <a name="undef_before"></a>
 | |
| 
 | |
| <h1 id="cautions_on_the_use_of_before_triggers"><span>5. </span>Cautions On The Use Of BEFORE triggers</h1>
 | |
| 
 | |
| <p>If a BEFORE UPDATE or BEFORE DELETE trigger modifies or deletes a row
 | |
| that was to have been updated or deleted, then the result of the subsequent
 | |
| update or delete operation is undefined.  Furthermore, if a BEFORE trigger
 | |
| modifies or deletes a row, then it is undefined whether or not AFTER triggers
 | |
| that would have otherwise run on those rows will in fact run.
 | |
| </p>
 | |
| 
 | |
| <p>The value of NEW.rowid is undefined in a BEFORE INSERT trigger in which
 | |
| the rowid is not explicitly set to an integer.</p>
 | |
| 
 | |
| <p>Because of the behaviors described above, programmers are encouraged to
 | |
| prefer AFTER triggers over BEFORE triggers.</p>
 | |
| 
 | |
| <a name="raise"></a>
 | |
| 
 | |
| <h1 id="the_raise_function"><span>6. </span>The RAISE() function</h1>
 | |
| 
 | |
| <p>A special SQL function RAISE() may be used within a trigger-program,
 | |
| with the following syntax</p> 
 | |
| 
 | |
| <p><b><a href="syntax/raise-function.html">raise-function:</a></b></p><div class='imgcontainer'>
 | |
|  <img alt="syntax diagram raise-function" src="images/syntax/raise-function.gif"></img>
 | |
|  </div>
 | |
| 
 | |
| 
 | |
| <p>When one of RAISE(ROLLBACK,...), RAISE(ABORT,...) or RAISE(FAIL,...)
 | |
| is called during trigger-program
 | |
| execution, the specified <a href="lang_conflict.html">ON CONFLICT</a> processing is performed and
 | |
| the current query terminates.
 | |
| An error code of <a href="rescode.html#constraint">SQLITE_CONSTRAINT</a> is returned to the application,
 | |
| along with the specified error message.</p>
 | |
| 
 | |
| <p>When RAISE(IGNORE) is called, the remainder of the current trigger program,
 | |
| the statement that caused the trigger program to execute and any subsequent
 | |
| trigger programs that would have been executed are abandoned. No database
 | |
| changes are rolled back.  If the statement that caused the trigger program
 | |
| to execute is itself part of a trigger program, then that trigger program
 | |
| resumes execution at the beginning of the next step.
 | |
| </p>
 | |
| 
 | |
| <a name="temptrig"></a>
 | |
| 
 | |
| <h1 id="temp_triggers_on_non_temp_tables"><span>7. </span>TEMP Triggers on Non-TEMP Tables</h1>
 | |
| 
 | |
| <p>A trigger normally exists in the same database as the table named
 | |
| after the "ON" keyword in the CREATE TRIGGER statement.  Except, it is
 | |
| possible to create a TEMP TRIGGER on a table in another database.  
 | |
| Such a trigger will only fire when changes
 | |
| are made to the target table by the application that defined the trigger.
 | |
| Other applications that modify the database will not be able to see the
 | |
| TEMP trigger and hence cannot run the trigger.</p>
 | |
| 
 | |
| <p>When defining a TEMP trigger on a non-TEMP table, it is important to
 | |
| specify the database holding the non-TEMP table.  For example,
 | |
| in the following statement, it is important to say "main.tab1" instead
 | |
| of just "tab1":</p>
 | |
| 
 | |
| <blockquote><pre>
 | |
| CREATE TEMP TRIGGER ex1 AFTER INSERT ON <b>main.</b>tab1 BEGIN ...
 | |
| </pre></blockquote>
 | |
| 
 | |
| <p>Failure to specify the schema name on the target table could result
 | |
| in the TEMP trigger being reattached to a table with the same name in
 | |
| another database whenever any schema change occurs.</p>
 | |
| 
 |