On 2016/01/16 4:53 PM, Simon Slavin wrote:
> On 16 Jan 2016, at 2:31pm, R Smith <rsmith at rsweb.co.za> wrote:
>
>> There is of course no SQL function to do this, but thanks to CTE we can 
>> achieve it easily (though not extremely efficiently).
> I thought that WITH could be used only for SELECT statements.
>
> Oh wait, you want to use the WITH statement as a sub-select on an INSERT 
> statement.  Does that work ?

The example I posted simply SELECTs the values, but it can as easily be 
piped to a table via an INSERT statement or such. The OP said indeed he 
wants to push the values to a table and from there read it. This can 
even be an in-memory table or simply another CTE table.

As to your question - WITH can be used in any place where a table-select 
can,  with some restrictions (though my example requires nothing fancy 
in this regard).

I quote from the documentation at: https://www.sqlite.org/lang_with.html

"All common table expressions (ordinary and recursive) are created by 
prepending a WITH clause in front of a SELECT, INSERT, DELETE, or UPDATE 
statement. A single WITH clause can specify one or more common table 
expressions...."

That is to say, it is perfectly legal to do something like this:

WITH C(Idx) AS (
SELECT 1 UNION ALL SELECT Idx+1 FROM C OFFSET 5 LIMIT 3
) DELETE FROM Contacts WHERE EXISTS (SELECT 1 FROM C WHERE 
C.Idx=Contacts.ID);

Which will delete contacts from the "Contacts" table with ID's 6, 7 and 8.

Or perhaps:

WITH NewPeeps(title, name, surname, tel, email) AS (
     SELECT 'James', 'Jones', '555-123-7689' UNION ALL
     SELECT 'Jason', 'Johnson', '555-124-7689' UNION ALL
     SELECT 'Jeffrey', 'Jenner', '555-125-7689'
) INSERT INTO Contacts (Name, Surname, Title, Tel, Mail) SELECT name, 
surname, 'Mr.', tel, name||'@jworld.org' FROM NewPeeps;

Which will insert the contacts into the Contacts table. Etc.

Even in explicit sub-selects it works perfectly well, for example this 
query:

SELECT * FROM (
   WITH C(Idx) AS (SELECT (10+1) UNION ALL SELECT Idx+2 FROM C WHERE 
Idx<(20-1)) SELECT * FROM C
)

Which will produce all odd numbers between 10 and 20.

And then this Query will list all contacts with ID's that are the odd 
numbers between 10 and 20:

SELECT *
   FROM Contacts, (
     WITH C(Idx) AS (SELECT (10+1) UNION ALL SELECT Idx+2 FROM C WHERE 
Idx<(20-1)) SELECT * FROM C
   ) AS S
WHERE IndexC=S.Idx


Or in a correlated sub-query:

SELECT (
     WITH C(Idx, SqrIdx) AS (
       SELECT 1,1 UNION ALL SELECT Idx+1, (Idx*Idx) FROM C WHERE Idx<1000
     ) SELECT SqrIdx FROM C WHERE C.Idx=Contacts.ID LIMIT 1
   ) AS SQR, Contacts.*
   FROM Contacts

which shows the square of contact ID's next to the rest of their data.


These examples are of course extremely simple, but they show  the 
principles.

Reply via email to