0

I have a database table, let's call it Foo. Foo has an id column (which is long), and some data columns, let's call them Bar1 and Bar2

There is a script that used to work before there was an id column, that would simply add new stuff into the table like this:

INSERT INTO Foo
SELECT OldBar1, SUM(OldBar2)
FROM OldFoo
GROUP BY OldBar1

Now, after the id has been added, if I have a new, Foo table empty initially, then I can do this:

INSERT INTO Foo
SELECT row_number() OVER() as id, OldBar1, SUM(OldBar2)
FROM OldFoo
GROUP BY OldBar1;

And the data in Foo table will have their ids equal row numbers.

However, when there is existing data in the Foo table and I execute the previous query, I get an exception stating that "Key (id)=(1) already exists".

Obviously, I do not want the row_number to look at the source, the OldFoo table, but rather to the new, Foo table.

To draw a parallel example in Java, using HashMap<Integer, Foo> as the repository:

map.put(map.size() + 1, fooObject);

Is there a way to achieve this, to generate the ID which will be the same as row number in the target table?

2
  • 4
    You want to declare the column to be serial so the database handles the auto incrementing. See the numeric types here: postgresql.org/docs/9.4/static/datatype-numeric.html. Commented Mar 25, 2015 at 13:38
  • I forgot to mention, the tables are generated via JPA, so I'm not sure how to achieve this with entity classes. Commented Mar 25, 2015 at 13:40

1 Answer 1

2

I strongly recommend finding a way to use serial. However, assuming that there are no other insert operations occurring on the table, the following should work for you:

INSERT INTO Foo
    SELECT (f.maxId + row_number() OVER() )as id, OldBar1, SUM(OldBar2)
    FROM OldFoo CROSS JOIN
         (SELECT MAX(id) as MAX(ID) FROM Foo) f
    GROUP BY OldBar1, f.maxId;

A piece of advice: when using INSERT always include the column names. So your query should read something like INSERT INTO Foo(Id, OldBar). This makes the code easier to maintain and to understand.

Sign up to request clarification or add additional context in comments.

3 Comments

Of course, I was simply using Fooa and Bars to hide the real table and column names :D Could you tell me anything about the performace of this way of inserting?
A question tho: Using this approach the following error occurs: ERROR: column "f.maxid" must appear in the GROUP BY clause or be used in an aggregate function.
It appears that @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; translates into SERIAL, which makes my life a lot easier :D Thank you very much, answer accepted :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.