the <command>DELETE</command> command contains a <literal>RETURNING</literal>
clause, the result will be similar to that of a <command>SELECT</command>
statement containing the columns and values defined in the
<literal>RETURNING</literal> list, computed over the row(s) deleted by the
command.
</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>
<productname>PostgreSQL</productname> lets you reference columns of
other tables in the <literal>WHERE</literal> condition by specifying the
other tables in the <literal>USING</literal> clause. For example,
to delete all films produced by a given producer, one can do:
<programlisting>
DELETE FROM films USING producers
WHERE producer_id = producers.id AND producers.name = 'foo';
</programlisting>
What is essentially happening here is a join between <structname>films</structname>
and <structname>producers</structname>, with all successfully joined
<structname>films</structname> rows being marked for deletion.
This syntax is not standard. A more standard way to do it is:
<programlisting>
DELETE FROM films
WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo');
</programlisting>
In some cases the join style is easier to write or faster to
execute than the sub-select style.
</para>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
Delete all films but musicals:
<programlisting>
DELETE FROM films WHERE kind <> 'Musical';
</programlisting>
</para>
<para>
Clear the table <literal>films</literal>:
<programlisting>
DELETE FROM films;
</programlisting>
</para>
<para>
Delete completed tasks, returning full details of the deleted rows:
<programlisting>
DELETE FROM tasks WHERE status = 'DONE' RETURNING *;
</programlisting>
</para>
<para>
Delete the row of <structname>tasks</structname> on which the cursor
<literal>c_tasks</literal> is currently positioned:
<programlisting>
DELETE FROM tasks WHERE CURRENT OF c_tasks;
</programlisting>
</para>
<para>
While there is no <literal>LIMIT</literal> clause
for <command>DELETE</command>, it is possible to get a similar effect
using the same method described in <link linkend="update-limit">the
documentation of <command>UPDATE</command></link>:
<programlisting>
WITH delete_batch AS (
SELECT l.ctid FROM user_logs AS l
WHERE l.status = 'archived'
ORDER BY l.creation_date
FOR UPDATE
LIMIT 10000
)
DELETE FROM user_logs AS dl
USING delete_batch AS del
WHERE dl.ctid = del.ctid;
</programlisting>
</para>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
This command conforms to the <acronym>SQL</acronym> standard, except
that the <literal>USING</literal> and <literal>RETURNING</literal> clauses
are <productname>PostgreSQL</productname> extensions, as is the ability
to use <literal>WITH</literal> with <command>DELETE</command>.
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="sql-truncate"/></member>
</simplelist>
</refsect1>
</refentry>