<para>
       Specifies that the command takes effect for only the current
       transaction.  After <command>COMMIT</> or <command>ROLLBACK</>,
-      the session-level setting takes effect again.  Note that
-      <command>SET LOCAL</> will appear to have no effect if it is
-      executed outside a <command>BEGIN</> block, since the
-      transaction will end immediately.
+      the session-level setting takes effect again.
+      <productname>PostgreSQL</productname> reports an error if
+      <command>SET LOCAL</> is used outside a transaction block.
      </para>
     </listitem>
    </varlistentry>
 
    current transaction. Thus, if you execute this command outside of a
    transaction block
    (<command>BEGIN</command>/<command>COMMIT</command> pair), it will
-   not appear to have any effect.
+   generate an error.
   </para>
  </refsect1>
 
 
 
   <para>
    If <command>SET TRANSACTION</command> is executed without a prior
-   <command>START TRANSACTION</command> or  <command>BEGIN</command>,
-   it will appear to have no effect, since the transaction will immediately
-   end.
+   <command>START TRANSACTION</command> or <command>BEGIN</command>,
+   it will generate an error.
   </para>
 
   <para>
 
                        break;
 
                case T_VariableSetStmt:
-                       ExecSetVariableStmt((VariableSetStmt *) parsetree);
+                       ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
                        break;
 
                case T_VariableShowStmt:
                        break;
 
                case T_ConstraintsSetStmt:
+                       RequireTransactionChain(isTopLevel, "SET CONSTRAINTS");
                        AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
                        break;
 
 
  * SET command
  */
 void
-ExecSetVariableStmt(VariableSetStmt *stmt)
+ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
 {
        GucAction       action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
 
        {
                case VAR_SET_VALUE:
                case VAR_SET_CURRENT:
+                       if (stmt->is_local)
+                               RequireTransactionChain(isTopLevel, "SET LOCAL");
                        (void) set_config_option(stmt->name,
                                                                         ExtractSetVariableArgs(stmt),
                                                                         (superuser() ? PGC_SUSET : PGC_USERSET),
                                                                         0);
                        break;
                case VAR_SET_MULTI:
-
                        /*
                         * Special-case SQL syntaxes.  The TRANSACTION and SESSION
                         * CHARACTERISTICS cases effectively set more than one variable
                        {
                                ListCell   *head;
 
+                               RequireTransactionChain(isTopLevel, "SET TRANSACTION");
+
                                foreach(head, stmt->args)
                                {
                                        DefElem    *item = (DefElem *) lfirst(head);
                                        ereport(ERROR,
                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                                         errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
+
+                               RequireTransactionChain(isTopLevel, "SET TRANSACTION");
                                Assert(IsA(con, A_Const));
                                Assert(nodeTag(&con->val) == T_String);
                                ImportSnapshot(strVal(&con->val));
                                         stmt->name);
                        break;
                case VAR_SET_DEFAULT:
+                       if (stmt->is_local)
+                               RequireTransactionChain(isTopLevel, "SET LOCAL");
+                       /* fall through */
                case VAR_RESET:
+                       if (strcmp(stmt->name, "transaction_isolation") == 0)
+                               RequireTransactionChain(isTopLevel, "RESET TRANSACTION");
+
                        (void) set_config_option(stmt->name,
                                                                         NULL,
                                                                         (superuser() ? PGC_SUSET : PGC_USERSET),
 
 extern void GetPGVariable(const char *name, DestReceiver *dest);
 extern TupleDesc GetPGVariableResultDesc(const char *name);
 
-extern void ExecSetVariableStmt(VariableSetStmt *stmt);
+extern void ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel);
 extern char *ExtractSetVariableArgs(VariableSetStmt *stmt);
 
 extern void ProcessGUCArray(ArrayType *array,
 
 
 -- SET LOCAL has no effect outside of a transaction
 SET LOCAL vacuum_cost_delay TO 50;
+ERROR:  SET LOCAL can only be used in transaction blocks
 SHOW vacuum_cost_delay;
  vacuum_cost_delay 
 -------------------
 (1 row)
 
 SET LOCAL datestyle = 'SQL';
+ERROR:  SET LOCAL can only be used in transaction blocks
 SHOW datestyle;
  DateStyle 
 -----------