[Wellington-pm] Perl database stuff....
Cliff Pratt
enkidu at cliffp.com
Sun Dec 24 01:29:34 PST 2006
Andrew McMillan wrote:
> On Sun, 2006-12-24 at 14:29 +1300, Cliff Pratt wrote:
>> I want to write a row, using Perl, to a PostgreSQL database, *but only
>> if the row does not already exist*. If I add a row, I need to know the
>> ID of the row.
>>
>> Currently what I have is:
>>
>> 1) Select the row using a WHERE clause to select the row I want to add,
>> to see if it is already there.
>>
>> 2) If the row does exist return an error (details don't matter).
>>
>> 3) If the row doesn't exist insert it, defaulting the ID which is
>> generated by a sequence.
>>
>> 4) Read it again to find the ID which was generated during the insert.
>>
>> Blah! This works but is long-winded, untidy and generally blah!
>>
>> Is there a smarter way to do it, either on the Perl side or on the
>> database side?
>
> Perhaps. Certainly using nextval() or currval() are better approaches
> for getting hold of the generated sequence.
>
> Here are some more alternative approaches:
>
> (a) On the database side you could write a function which accepted all
> of the row parameters, selected the row returning the id (possibly
> throwing an error). If the row didn't exist it could insert the row,
> returning the id either using currval('sequence') to get the sequence
> value after the fact, or by using nextval('sequence') and explicitly
> assigning that for the ID column.
>
> (b) On the database side you could write a fancy insert ... select ...
> statement such as:
>
> INSERT INTO table1 (col1,col2)
> SELECT 1 AS col1, 2 AS col2 FROM table1
> WHERE NOT exists(SELECT 1 FROM table1 WHERE col1=1 AND col2=2)
> LIMIT 1;
>
> That's a pretty sneaky one, and might not make maintenance of the
> program as straightforward as it might otherwise be. It won't give you
> an error when the row already exists - it will just silently not insert
> a row, which can sometimes be what you want.
>
>
> (c) In the perl you can make it "select, select, insert" as:
> 1. select the record (and fail).
> 2. select the sequence nextval
> 3. insert the row using the sequence.
>
> Which is actually the way I would tend to do it myself because it seems
> so much cleaner to know the ID in advance and then write multiple SQL
> calls using that value. I tend to take the (a) approach when I have
> some values that I want to 'either update or insert these values', which
> is slightly different from your question here.
>
> Cheers,
> Andrew.
>
Thanks for that. I like solution c) which is a bit neater than my
solution. Re solution b), I was wondering if there was a DB side answer,
but that is too tricky for me! a) is interesting and I might look
further into that.
Cheers,
Cliff
More information about the Wellington-pm
mailing list