tags:

views:

123

answers:

3

Let's say I have the following tables: PartyRelationship EffectiveDatedAttributes

PartyRelationship contains a varchar column called class.
EffectiveDatedAttributes contains a foreign key to PartyRelationship called ProductAuthorization.

If I run this:

select unique 
        eda.productauthorization 
from 
        effectivedatedattributes eda  
inner join 
        partyrelationship pr
    on 
        eda.productauthorization = pr.ID  
where 
        pr.class = 'com.pmc.model.bind.ProductAuthorization'

it returns a list of ProductAuthorization IDs. I need to take this list of IDs and insert a new row into EffectiveDatedAttributes for every ID, containing the ID as well as some other data. How would I iterate over the returned IDs from the previous select statement in order to do this?

A: 

Actually insert can use the result from a select. Like:

insert into YourTable
(col1, col2, col3)
select col1, col2, col3
from OtherTable

it should be easy to adapt this to your situation.

Andomar
+2  A: 

You mean something like so?:

Insert EffectiveDatedAttributes ( Id, Col1, Col2....)
select unique eda.productauthorization, 'Attribute1', 'Attribute2'....
from effectivedatedattributes eda
    inner join partyrelationship pr
        on eda.productauthorization = pr.ID
where pr.class = 'com.pmc.model.bind.ProductAuthorization';

Or is it the case that you have other tables involved in what should be inserted?

EDIT Given the additional details you provided in comments, you will need to generate ID values that go into EffectiveDateAttributes. Here is a very of the query that would not require the use of Common Table Expressions:

Insert EffectiveDateAttributes( Id, Col1, Col2, Col3, ..., )
Select Distinct 
        (
        Select Count(*) + LastId.Id + 1
        From PartyRelationship As PR1
        Where PR1.class = 'com.pmc.model.bind.ProductAuthorization';
            And PR1.ID < PR.ID
        ) Id
    , PR.ID, 'Static Value 1', 'Static Value 2', PR.Col1, PR.Col2...
From PartyRelationship PR
    Join EffectiveDateAttributes EDA
        On EDA.ProductAuthorization = PR.ID
    Cross Join  (
                    Select Max(ID) Id
                    From EffectiveDateAttributes
                    ) As LastId
Where PR.class = 'com.pmc.model.bind.ProductAuthorization'

I'm still not quite convinced I need the join to EffectiveDateAttributes. It's only purpose is to ensure that any values we evaluate in the PartyRelationship table exist in the EffectiveDateAttributes table. If that does not matter, then it can be removed.

Second, I generated a sequence by querying for the count of all values of PartyRelationship less than the current value. That will give me a sequence of numbers starting at zero. I then add the highest ID value that currently exists in EffectiveDateAttributes and add one and that should give us the next available ID ignoring various transaction isolation issues. There is a simpler method which I'll post shortly.

Also note that in the select statement, you can include additional static values that are used to insert into your table. In your original query I notice that you used the word "unique" instead of Distinct. The ANSI standard word for ensuring uniqueness in the output of a select statement is Distinct and Oracle will recognize this.

EDIT Using a Common Table Expression, makes this a bit simpler:

With NumberedTables As
    (
        Select PR.ID
            , ROW_NUMBER() OVER( ORDER BY PR.ID ) As Num
        From PartyRelationship PR
            Join EffectiveDateAttributes EDA
                On EDA.ProductAuthorization = PR.ID
        Where PR.class = 'com.pmc.model.bind.ProductAuthorization'
        Group By PR.ID
    )
    , LastIdUsed As
    (
        Select Max(ID) Id
        From EffectiveDateAttributes
    )
Insert EffectiveDateAttributes( Id, Col1, Col2, Col3, ..., )
Select Num + LastIdUsed.Id,  'Static Value 1', 'Static Value 2', PR.Col1, PR.Col2...
From NumberedTables 
    Join PartyRelationship PR
        On PR.ID = NumberedTables.ID
    Cross Join LastIdUsed
Thomas
I"m not sure it's a good idea to insert into the same table you're selecting from, but fortunately I don't think it's necessary in this case unless the inner join is actually acting as a constraint here (ie. unless there are some pr.IDs that aren't in eda). He should be able to strip out the eda join altogether.
tloflin
@tloflin - Granted. Although the OP states that is what is trying do but not as much info on the goal he is trying to achieve.
Thomas
It's the case that the select statement returns more than one value. Will the above work when the select is returning multiple values? I don't have other tables involved in what should be inserted - it's mostly static data. Only the productauthorization in effectivedatedattributes will be different - it will be the ID from the join with partyrelationship. The rest is fixed data.
bergyman
@bergyman - It is difficult to answer that question definitively without knowing the schema of the tables involved. What is the primary key of each table? Are there any unique constraints? You may not need EffectiveDataAttributes in the FROM clause of the query depending on the requirements.
Thomas
@Thomas - Ultimately I just need to take a list of numbers, iterate through the list and insert a row into a table which contains each number and some other static data. Maybe I'm over complicating this.
bergyman
@bergyman - A list of numbers from where? From PartyRelationship? If so, then you can do it in a simple insert as I've presented.
Thomas
@Thomas - It's the list of numbers from above the select. I need to take each number in that list and insert a row for each number, containing the number itself and some other stuff. So if I have a list of (50, 87, 90) I need to insert 3 rows: One containing [50, true, "blah"], one with [87, true, "blah"] and one with [90, true, "blah"]. I suppose the above select could be rewritten to select from partyrelationship and do an inner join on effectivedatedattritubes instead, so yes. It could be a list taken from either table. Does your above solution actually write multiple rows to the table?
bergyman
@bergyman - Yes my solution will write multiple rows (assuming the SELECT returns multiple rows). However, I'm unclear about how you can take numbers from the `EffectiveDatedAttributes` table and putting those same numbers back into the table. It will, by definition, cause duplication. What is the primary key on `EffectiveDatedAttributes`?
Thomas
@Thomas - The primary key is ID on the EDA table. I know it will cause duplication - but that's how these table have been set up. There's already duplication of a sort in the EDA table - right now there's four rows that map to the same product authorization (they contain the same value for the foreign key to that table, but different data aside from that foreign key value) and I have the pleasure of going in to add a fifth row with the same foreign key value. So now there will be five rows in the EDA table that are going to map a specific ProductAuthorization in the PartyRelationship table.
bergyman
So I don't actually want to insert a value into ID in the EDA table - this is the primary key and is auto incremented.What I need to do is (in pseudo code): [45,50,130].each do |number| insert into EDA(productauthorization, class, productlimitgroup) values (number, 'my.class', 1) end
bergyman
@bergyman - Ok. Then the solution I presented will work fine. Instead of using the `VALUES` clause, you would use a SELECT statement as I've done in my solution and simply include the additional attributes (e.g. 'my.class', 1) as other columns in the SELECT statement.
Thomas
@Thomas - thanks so much for all the help. Apparently the primary key of EDA (ID) is NOT auto incremented. So when I try `insert into effectivedatedattributes(productauthorization, class, productlimitgroup)select unique eda.productauthorization, 'com.pmc.model.bind.ProductAuthProductLimitGroup', 1 from effectivedatedattributes edainner join partyrelationship pron eda.productauthorization = pr.idwhere pr.class = 'com.pmc.model.bind.ProductAuthorization' order by eda.productauthorization;` it complains about inserting NULL into the ID column. Sigh.
bergyman
@bergyman - Ah. I wondered about that. What is the actual database product in question here?
Thomas
@Thomas - Using oracle 10.2.
bergyman
@Thomas - And this is with java/hibernate. Apparently the IDs are coming from a hibernate sequence. Got our DB guy working on this and he's thus far come up with the same solution as you have above, but we obviously now need to insert an ID with this as well, using the hibernate sequence. I'll post what he comes up with. Thanks so much for all the help.
bergyman
And the answer from the DB guy, works like a charm:insert into effectivedatedattributes (productauthorization, class, productlimitgroup, id) select pa.productauthorization, 'com.pmc.model.bind.ProductAuthProductLimitGroup', 1, hibernate_sequence.nextval from (select unique(eda.productauthorization) from effectivedatedattributes eda inner join partyrelationship pr on eda.productauthorization = pr.id where pr.class = 'com.pmc.model.bind.ProductAuthorization') pa;
bergyman
A: 

I concur with Thomas, The select statement you have already got can form the basis of a separate table (virtual table).

So do this:

INSERT INTO EvvectiveDatedAtributes(VirtualTable.productauthorization , data, data, data)
FROM 
    (YourQueryHere) as VirtualTable
TerrorAustralis