views:

56692

answers:

3

I am trying to insert into a table using the input from another table. Although this is entirely feasible for many database engines, I always seem to struggle to remember the correct syntax for the SQL-Engine of the day (MySQL, Oracle, SQLServer, Informix, DB2).

I've been wondering if there is a silver-bullet syntax coming from an SQL Standards (For example, SQL92) that would allow me to insert the values without worrying about the underlying database.

+24  A: 

Here is an SQL Statement that seems to be quite representative of what should work on any RDBMS and achieve the result. However, due to my incapacity to install all RDBMS software and test this query, I cannot be sure.

If this is wrong in an RDBMS, please notify me.

The SQL:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2
Shadow_x99
This is how to do it on Oracle
WW
And MS SQL server
littlegreen
And MySQL, and afair PgSQL
cichy
And SQLite version 3 of the database.
Gad D Lord
+5  A: 

@Shadow_x99: That should work fine, and you can also have multiple columns and other data as well:

INSERT INTO table1 ( column1, column2, someInt, someVarChar )
SELECT  table2.column1, table2.column2, 8, 'some string etc.'
FROM    table2
WHERE   table2.ID = 7

Edit: I should mention that I've only used this syntax with Access, SQL 2000/2005/Express, MySql, and PostGres, so those should be covered.

travis
travis: is that right? Did you mean to put "8, 'some string etc.'" in the SELECT list?
Michael Haren
Yeah, then every row that was inserted would have the value 8 and 'some string etc.' for those columns. You could also use something like GETDATE() on SQL server.
travis
Just to be clear, the query in your answer will not work (I tested on Sql Server), as you've put the constants in the field list of the INSERT and not into the SELECT.
Simon D
nice catch, I've updated the sql to actually work :-)
travis
+3  A: 

Both the answers I see work fine in Informix specifically, and are basically standard SQL. That is, the notation:

INSERT INTO target_table[(<column-list>)] SELECT ... FROM ...;

works fine with Informix and, I would expect, all the DBMS. (Once upon 5 or more years ago, this is the sort of thing that MySQL did not always support; it now has decent support for this sort of standard SQL syntax and, AFAIK, it would work OK on this notation.) The column list is optional but indicates the target columns in sequence, so the first column of the result of the SELECT will go into the first listed column, etc. In the absence of the column list, the first column of the result of the SELECT goes into the first column of the target table.

What can be different between systems is the notation used to identify tables in different databases - the standard has nothing to say about inter-database (let alone inter-DBMS) operations. With Informix, you can use the following notation to identify a table:

[dbase[@server]:][owner.]table

That is, you may specify a database, optionally identifying the server that hosts that database if it is not in the current server, followed by an optional owner, dot, and finally the actual table name. The SQL standard uses the term schema for what Informix calls the owner. Thus, in Informix, any of the following notations could identify a table:

table
"owner".table
dbase:table
dbase:owner.table
dbase@server:table
dbase@server:owner.table

The owner in general does not need to be quoted; however, if you do use quotes, you need to get the owner name spelled correctly - it becomes case-sensitive. That is:

someone.table
"someone".table
SOMEONE.table

all identify the same table. With Informix, there's a mild complication with MODE ANSI databases, where owner names are generally converted to upper-case (informix is the exception). That is, in a MODE ANSI database (not commonly used), you could write:

CREATE TABLE someone.table ( ... )

and the owner name in the system catalog would be "SOMEONE", rather than 'someone'. If you enclose the owner name in double quotes, it acts like a delimited identifier. With standard SQL, delimited identifiers can be used many places. With Informix, you can use them only around owner names -- in other contexts, Informix treats both single-quoted and double-quoted strings as strings, rather than separating single-quoted strings as strings and double-quoted strings as delimited identifiers. (Of course, just for completeness, there is an environment variable, DELIMIDENT, that can be set - to any value, but Y is safest - to indicate that double quotes always surround delimited identifiers and single quotes always surround strings.)

Note that MS SQL Server manages to use [delimited identifiers] enclosed in square brackets. It looks weird to me, and is certainly not part of the SQL standard.

Jonathan Leffler