views:

63

answers:

3

I'd like to be able to insert some values into a table using a single INSERT statement, but I'm having trouble determining the best way. The data I'm inserting is bootstrap (or hard-coded) data, ie. not available in another table. Here's what I've tried so far.

create table #t (id int)

insert into #t values (1)  --- (a)
insert into #t values (5)  --- (a)

insert into #t values ((5), (3), (22))  --- (b)

insert into #t             --- (c)
select 3 union all
select 5 union all
select 6 union all
select 8

The code at (a) works just fine, but adds only a single value per insert.

The code at (b) seems to be the logical extension of (a) to me (at least when I think of initialisers from Perl or Java), but doesn't work.

The code at (c) works and is probably more of the SQL way, but seems verbose.

Is there a variant of (b) that works? Or is there an approach like (c) that requires less typing?

I'm using SQL Server 2000, but I'm interested in something that's fairly portable if possible.

UPDATE: Thanks to everynoe who answered. In summary, it seems the SQL standard has a multi-insert, which is what I was after, but is not supported in my environment. So I will stick with (a) for simplicity and clarity.

A: 

Is there a variant of (b) that works?

INSERT can only insert one row at a time. If you'd like to insert more than one row, you'll have to call it many times. So in short, no.

Or is there an approach like (c) that requires less typing?

There might be a short-handed way to perform the unions, but you should be aware that performing all of those unions will require a lot of memory and be significantly slower than calling INSERT multiple times.

If your data is hard-coded and you're looking to bulk import you might want to look into BULK INSERT. You can use BULK INSERT to read CSV data.

Ben S
In that the code at (c) communicates with the server once whereas calling the code at (a) multiple times communicates with the server multiple times, I suspect that unless you can cut out the round-trips between program and server, then the UNION code will out-perform the multiple-INSERT code.
Jonathan Leffler
This is obviously dependent on the environment, but if the size of the union is larger than the system memory and the server starts to page memory to disk, I doubt that network latency will be a bottleneck.
Ben S
@Ben: well, yes, it is somewhat dependent on the environment; if you are communicating with a DBMS over a WAN, the response will be different from if you are working on the same machine as the DBMS. These days, the limit on the size on an SQL statement (32 KB - 2 MB, roughly, depending on DBMS) is more of an issue than the data that is represented by the UNION. A single statement is still likely to be more efficient than multiple round-trips between application and server, unless there are ways to group statements as a batch of statements that I don't know of, which is a possibility.
Jonathan Leffler
A: 

Well, you could insert into a temporary table and then do the following:

INSERT INTO ...
SELECT FROM ...
David Andres
Warning: Chicken and egg problem.
Ben S
I actually read that hearing the voice of the computer from star trek in my head.
Preet Sangha
Yes, yes, I know.
David Andres
A: 

The SQL standard provides for multiple lists of values, each in its own set of parentheses, which is a minor variant on your (b):

INSERT INTO "#t" VALUES (1), (2), (3);

Not all DBMS support this notation, though, and I'd be surprised if SQL Server 2000 did.

If the code is 'setup' code (as the question implies) that is executed once and not redone, then worrying about the utmost in efficiency is usually a premature optimization. Make it simple and clear. Use mechanism (a).

Jonathan Leffler
@dave indicates that he is on SQL-Server-2000. The multi-insert is not available.
Raj More
Having tried it, I can confirm that SQL Server 2000 does not support multi-insert. I wasn't after performance, just clarity and brevity of code.
dave